/// <summary> /// Registers (creates) a task in a specified location using a <see cref="TaskDefinition" /> instance to define a task. /// </summary> /// <param name="Path"> The task name. If this value is NULL, the task will be registered in the root task folder and the task name will be a GUID value that is created by the Task Scheduler service. A task name cannot begin or end with a space character. The '.' character cannot be used to specify the current task folder and the '..' characters cannot be used to specify the parent task folder in the path. </param> /// <param name="definition"> /// The <see cref="TaskDefinition" /> of the registered task. /// </param> /// <param name="createType"> /// A union of <see cref="TaskCreation" /> flags. /// </param> /// <param name="UserId"> The user credentials used to register the task. </param> /// <param name="password"> The password for the userId used to register the task. </param> /// <param name="LogonType"> /// A <see cref="TaskLogonType" /> value that defines what logon technique is used to run the registered task. /// </param> /// <param name="sddl"> The security descriptor associated with the registered task. You can specify the access control list (ACL) in the security descriptor for a task in order to allow or deny certain users and groups access to a task. </param> /// <returns> /// A <see cref="Task" /> instance that represents the new task. /// </returns> public Task RegisterTaskDefinition(string Path, TaskDefinition definition, TaskCreation createType, string UserId, string password = null, TaskLogonType LogonType = TaskLogonType.S4U, string sddl = null) { if (v2Folder != null) { return(new Task(TaskService, v2Folder.RegisterTaskDefinition(Path, definition.v2Def, (int)createType, UserId, password, LogonType, sddl))); } // Adds ability to set a password for a V1 task. Provided by Arcao. var flags = definition.v1Task.GetFlags(); if (LogonType == TaskLogonType.InteractiveTokenOrPassword && string.IsNullOrEmpty(password)) { LogonType = TaskLogonType.InteractiveToken; } switch (LogonType) { case TaskLogonType.Group: case TaskLogonType.S4U: case TaskLogonType.None: throw new NotV1SupportedException("This LogonType is not supported on Task Scheduler 1.0."); case TaskLogonType.InteractiveToken: flags |= (TaskFlags.RunOnlyIfLoggedOn | TaskFlags.Interactive); if (String.IsNullOrEmpty(UserId)) { UserId = WindowsIdentity.GetCurrent().Name; } definition.v1Task.SetAccountInformation(UserId, IntPtr.Zero); break; case TaskLogonType.ServiceAccount: flags &= ~(TaskFlags.Interactive | TaskFlags.RunOnlyIfLoggedOn); definition.v1Task.SetAccountInformation( (String.IsNullOrEmpty(UserId) || UserId.Equals("SYSTEM", StringComparison.CurrentCultureIgnoreCase)) ? String.Empty : UserId, IntPtr.Zero); break; case TaskLogonType.InteractiveTokenOrPassword: flags |= TaskFlags.Interactive; using (var cpwd = new CoTaskMemString(password)) { definition.v1Task.SetAccountInformation(UserId, cpwd.DangerousGetHandle()); } break; case TaskLogonType.Password: using (var cpwd = new CoTaskMemString(password)) { definition.v1Task.SetAccountInformation(UserId, cpwd.DangerousGetHandle()); } break; default: break; } definition.v1Task.SetFlags(flags); switch (createType) { case TaskCreation.Create: case TaskCreation.CreateOrUpdate: case TaskCreation.Disable: case TaskCreation.Update: if (createType == TaskCreation.Disable) { definition.Settings.Enabled = false; } definition.V1Save(Path); break; case TaskCreation.DontAddPrincipalAce: throw new NotV1SupportedException("Security settings are not available on Task Scheduler 1.0."); case TaskCreation.IgnoreRegistrationTriggers: throw new NotV1SupportedException("Registration triggers are not available on Task Scheduler 1.0."); case TaskCreation.ValidateOnly: throw new NotV1SupportedException("Xml validation not available on Task Scheduler 1.0."); default: break; } return(new Task(TaskService, definition.v1Task)); }
/// <summary> /// Registers (creates) a task in a specified location using a <see cref="TaskDefinition" /> instance to define a task. /// </summary> /// <param name="path">The task name. If this value is NULL, the task will be registered in the root task folder and the task name will be a GUID value that is created by the Task Scheduler service. A task name cannot begin or end with a space character. The '.' character cannot be used to specify the current task folder and the '..' characters cannot be used to specify the parent task folder in the path.</param> /// <param name="definition">The <see cref="TaskDefinition" /> of the registered task.</param> /// <param name="createType">A union of <see cref="TaskCreation" /> flags.</param> /// <param name="userId">The user credentials used to register the task.</param> /// <param name="password">The password for the userId used to register the task.</param> /// <param name="logonType">A <see cref="TaskLogonType" /> value that defines what logon technique is used to run the registered task.</param> /// <param name="sddl">The security descriptor associated with the registered task. You can specify the access control list (ACL) in the security descriptor for a task in order to allow or deny certain users and groups access to a task.</param> /// <returns> /// A <see cref="Task" /> instance that represents the new task. This will return <c>null</c> if <paramref name="createType"/> is set to <c>ValidateOnly</c> and there are no validation errors. /// </returns> /// <exception cref="System.ArgumentOutOfRangeException"> /// Task names may not include any characters which are invalid for file names. /// or /// Task names ending with a period followed by three or fewer characters cannot be retrieved due to a bug in the native library. /// </exception> /// <exception cref="NotV1SupportedException">This LogonType is not supported on Task Scheduler 1.0. /// or /// Security settings are not available on Task Scheduler 1.0. /// or /// Registration triggers are not available on Task Scheduler 1.0. /// or /// XML validation not available on Task Scheduler 1.0.</exception> /// <remarks>This method is effectively the "Save" method for tasks. It takes a modified <c>TaskDefinition</c> instance and registers it in the folder defined by this <c>TaskFolder</c> instance. Optionally, you can use this method to override the user, password and logon type defined in the definition and supply security against the task.</remarks> /// <example> /// <para>This first example registers a simple task with a single trigger and action using the default security.</para> /// <code lang="cs"><![CDATA[ /// // Create a new task definition for the local machine and assign properties /// TaskDefinition td = TaskService.Instance.NewTask(); /// td.RegistrationInfo.Description = "Does something"; /// /// // Add a trigger that, starting tomorrow, will fire every other week on Monday and Saturday /// td.Triggers.Add(new WeeklyTrigger(DaysOfTheWeek.Monday | DaysOfTheWeek.Saturday, 2)); /// /// // Create an action that will launch Notepad whenever the trigger fires /// td.Actions.Add("notepad.exe", "c:\\test.log"); /// /// // Register the task in the root folder of the local machine using the current user and the S4U logon type /// TaskService.Instance.RootFolder.RegisterTaskDefinition("Test", td); /// ]]></code> /// <para>This example registers that same task using the SYSTEM account.</para> /// <code lang="cs"><![CDATA[ /// TaskService.Instance.RootFolder.RegisterTaskDefinition("TaskName", taskDefinition, TaskCreation.CreateOrUpdate, "SYSTEM", null, TaskLogonType.ServiceAccount); /// ]]></code> /// <para>This example registers that same task using a specific username and password along with a security definition.</para> /// <code lang="cs"><![CDATA[ /// TaskService.Instance.RootFolder.RegisterTaskDefinition("TaskName", taskDefinition, TaskCreation.CreateOrUpdate, "userDomain\\userName", "userPassword", TaskLogonType.Password, @"O:BAG:DUD:(A;ID;0x1f019f;;;BA)(A;ID;0x1f019f;;;SY)(A;ID;FA;;;BA)(A;;FR;;;BU)"); /// ]]></code></example> public Task RegisterTaskDefinition([NotNull] string path, [NotNull] TaskDefinition definition, TaskCreation createType, string userId, string password = null, TaskLogonType logonType = TaskLogonType.S4U, string sddl = null) { if (definition.Actions.Count < 1 || definition.Actions.Count > 32) { throw new ArgumentOutOfRangeException(nameof(definition.Actions), @"A task must be registered with at least one action and no more than 32 actions."); } userId = userId ?? definition.Principal.Account; if (userId == string.Empty) { userId = null; } User user = new User(userId); if (v2Folder != null) { definition.Actions.ConvertUnsupportedActions(); if (logonType == TaskLogonType.ServiceAccount) { if (string.IsNullOrEmpty(userId) || !user.IsServiceAccount) { throw new ArgumentException(@"A valid system account name must be supplied for TaskLogonType.ServiceAccount. Valid entries are ""NT AUTHORITY\SYSTEM"", ""SYSTEM"", ""NT AUTHORITY\LOCALSERVICE"", or ""NT AUTHORITY\NETWORKSERVICE"".", nameof(userId)); } if (password != null) { throw new ArgumentException(@"A password cannot be supplied when specifying TaskLogonType.ServiceAccount.", nameof(password)); } } /*else if ((LogonType == TaskLogonType.Password || LogonType == TaskLogonType.InteractiveTokenOrPassword || * (LogonType == TaskLogonType.S4U && UserId != null && !user.IsCurrent)) && password == null) * { * throw new ArgumentException("A password must be supplied when specifying TaskLogonType.Password or TaskLogonType.InteractiveTokenOrPassword or TaskLogonType.S4U from another account.", nameof(password)); * }*/ else if (logonType == TaskLogonType.Group && password != null) { throw new ArgumentException(@"A password cannot be supplied when specifying TaskLogonType.Group.", nameof(password)); } // The following line compensates for an omission in the native library that never actually sets the registration date (thanks ixm7). if (definition.RegistrationInfo.Date == DateTime.MinValue) { definition.RegistrationInfo.Date = DateTime.Now; } var iRegTask = v2Folder.RegisterTaskDefinition(path, definition.v2Def, (int)createType, userId ?? user.Name, password, logonType, sddl); if (createType == TaskCreation.ValidateOnly && iRegTask == null) { return(null); } return(Task.CreateTask(TaskService, iRegTask)); } // Check for V1 invalid task names string invChars = Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())); if (Regex.IsMatch(path, @"[" + invChars + @"]")) { throw new ArgumentOutOfRangeException(nameof(path), @"Task names may not include any characters which are invalid for file names."); } if (Regex.IsMatch(path, @"\.[^" + invChars + @"]{0,3}\z")) { throw new ArgumentOutOfRangeException(nameof(path), @"Task names ending with a period followed by three or fewer characters cannot be retrieved due to a bug in the native library."); } // Adds ability to set a password for a V1 task. Provided by Arcao. TaskFlags flags = definition.v1Task.GetFlags(); if (logonType == TaskLogonType.InteractiveTokenOrPassword && string.IsNullOrEmpty(password)) { logonType = TaskLogonType.InteractiveToken; } switch (logonType) { case TaskLogonType.Group: case TaskLogonType.S4U: case TaskLogonType.None: throw new NotV1SupportedException("This LogonType is not supported on Task Scheduler 1.0."); case TaskLogonType.InteractiveToken: flags |= (TaskFlags.RunOnlyIfLoggedOn | TaskFlags.Interactive); definition.v1Task.SetAccountInformation(user.Name, IntPtr.Zero); break; case TaskLogonType.ServiceAccount: flags &= ~(TaskFlags.Interactive | TaskFlags.RunOnlyIfLoggedOn); definition.v1Task.SetAccountInformation((String.IsNullOrEmpty(userId) || user.IsSystem) ? String.Empty : user.Name, IntPtr.Zero); break; case TaskLogonType.InteractiveTokenOrPassword: flags |= TaskFlags.Interactive; using (CoTaskMemString cpwd = new CoTaskMemString(password)) definition.v1Task.SetAccountInformation(user.Name, cpwd.DangerousGetHandle()); break; case TaskLogonType.Password: using (CoTaskMemString cpwd = new CoTaskMemString(password)) definition.v1Task.SetAccountInformation(user.Name, cpwd.DangerousGetHandle()); break; default: throw new ArgumentOutOfRangeException(nameof(logonType), logonType, null); } definition.v1Task.SetFlags(flags); switch (createType) { case TaskCreation.Create: case TaskCreation.CreateOrUpdate: case TaskCreation.Disable: case TaskCreation.Update: if (createType == TaskCreation.Disable) { definition.Settings.Enabled = false; } definition.V1Save(path); break; case TaskCreation.DontAddPrincipalAce: throw new NotV1SupportedException("Security settings are not available on Task Scheduler 1.0."); case TaskCreation.IgnoreRegistrationTriggers: throw new NotV1SupportedException("Registration triggers are not available on Task Scheduler 1.0."); case TaskCreation.ValidateOnly: throw new NotV1SupportedException("XML validation not available on Task Scheduler 1.0."); default: throw new ArgumentOutOfRangeException(nameof(createType), createType, null); } return(new Task(TaskService, definition.v1Task)); }
/// <summary> /// Registers (creates) a task in a specified location using a <see cref="TaskDefinition" /> instance to define a task. /// </summary> /// <param name="Path"> The task name. If this value is NULL, the task will be registered in the root task folder and the task name will be a GUID value that is created by the Task Scheduler service. A task name cannot begin or end with a space character. The '.' character cannot be used to specify the current task folder and the '..' characters cannot be used to specify the parent task folder in the path. </param> /// <param name="definition"> The <see cref="TaskDefinition" /> of the registered task. </param> /// <param name="createType"> A union of <see cref="TaskCreation" /> flags. </param> /// <param name="UserId"> The user credentials used to register the task. </param> /// <param name="password"> The password for the userId used to register the task. </param> /// <param name="LogonType"> A <see cref="TaskLogonType" /> value that defines what logon technique is used to run the registered task. </param> /// <param name="sddl"> The security descriptor associated with the registered task. You can specify the access control list (ACL) in the security descriptor for a task in order to allow or deny certain users and groups access to a task. </param> /// <returns> A <see cref="Task" /> instance that represents the new task. </returns> public Task RegisterTaskDefinition(string Path, TaskDefinition definition, TaskCreation createType, string UserId, string password = null, TaskLogonType LogonType = TaskLogonType.S4U, string sddl = null) { if (v2Folder != null) { return new Task(TaskService, v2Folder.RegisterTaskDefinition(Path, definition.v2Def, (int) createType, UserId, password, LogonType, sddl)); } // Adds ability to set a password for a V1 task. Provided by Arcao. var flags = definition.v1Task.GetFlags(); if (LogonType == TaskLogonType.InteractiveTokenOrPassword && string.IsNullOrEmpty(password)) { LogonType = TaskLogonType.InteractiveToken; } switch (LogonType) { case TaskLogonType.Group: case TaskLogonType.S4U: case TaskLogonType.None: throw new NotV1SupportedException("This LogonType is not supported on Task Scheduler 1.0."); case TaskLogonType.InteractiveToken: flags |= (TaskFlags.RunOnlyIfLoggedOn | TaskFlags.Interactive); if (String.IsNullOrEmpty(UserId)) { UserId = WindowsIdentity.GetCurrent().Name; } definition.v1Task.SetAccountInformation(UserId, IntPtr.Zero); break; case TaskLogonType.ServiceAccount: flags &= ~(TaskFlags.Interactive | TaskFlags.RunOnlyIfLoggedOn); definition.v1Task.SetAccountInformation( (String.IsNullOrEmpty(UserId) || UserId.Equals("SYSTEM", StringComparison.CurrentCultureIgnoreCase)) ? String.Empty : UserId, IntPtr.Zero); break; case TaskLogonType.InteractiveTokenOrPassword: flags |= TaskFlags.Interactive; using (var cpwd = new CoTaskMemString(password)) { definition.v1Task.SetAccountInformation(UserId, cpwd.DangerousGetHandle()); } break; case TaskLogonType.Password: using (var cpwd = new CoTaskMemString(password)) { definition.v1Task.SetAccountInformation(UserId, cpwd.DangerousGetHandle()); } break; default: break; } definition.v1Task.SetFlags(flags); switch (createType) { case TaskCreation.Create: case TaskCreation.CreateOrUpdate: case TaskCreation.Disable: case TaskCreation.Update: if (createType == TaskCreation.Disable) { definition.Settings.Enabled = false; } definition.V1Save(Path); break; case TaskCreation.DontAddPrincipalAce: throw new NotV1SupportedException("Security settings are not available on Task Scheduler 1.0."); case TaskCreation.IgnoreRegistrationTriggers: throw new NotV1SupportedException("Registration triggers are not available on Task Scheduler 1.0."); case TaskCreation.ValidateOnly: throw new NotV1SupportedException("Xml validation not available on Task Scheduler 1.0."); default: break; } return new Task(TaskService, definition.v1Task); }