/// <summary> /// Registers (creates) a new task in the folder using XML to define the 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="xmlText">An XML-formatted definition of the 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> /// <example><code lang="cs"><![CDATA[ /// // Define a basic task in XML /// var xml = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" + /// "<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">" + /// " <Principals>" + /// " <Principal id=\"Author\">" + /// " <UserId>S-1-5-18</UserId>" + /// " </Principal>" + /// " </Principals>" + /// " <Triggers>" + /// " <CalendarTrigger>" + /// " <StartBoundary>2017-09-04T14:04:03</StartBoundary>" + /// " <ScheduleByDay />" + /// " </CalendarTrigger>" + /// " </Triggers>" + /// " <Actions Context=\"Author\">" + /// " <Exec>" + /// " <Command>cmd</Command>" + /// " </Exec>" + /// " </Actions>" + /// "</Task>"; /// // Register the task in the root folder of the local machine using the SYSTEM account defined in XML /// TaskService.Instance.RootFolder.RegisterTaskDefinition("Test", xml); /// ]]></code></example> public Task RegisterTask(string path, [NotNull] string xmlText, TaskCreation createType = TaskCreation.CreateOrUpdate, string userId = null, string password = null, TaskLogonType logonType = TaskLogonType.S4U, string sddl = null) { if (v2Folder != null) { return(Task.CreateTask(TaskService, v2Folder.RegisterTask(path, xmlText, (int)createType, userId, password, logonType, sddl))); } TaskDefinition td = TaskService.NewTask(); XmlSerializationHelper.ReadObjectFromXmlText(xmlText, td); return(RegisterTaskDefinition(path, td, createType, userId ?? td.Principal.ToString(), password, logonType == TaskLogonType.S4U ? td.Principal.LogonType : logonType, sddl)); }
/// <summary> /// Registers (creates) a new task in the folder using XML to define the 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="XmlText">An XML-formatted definition of the 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 RegisterTask(string Path, string XmlText, TaskCreation createType = TaskCreation.CreateOrUpdate, string UserId = null, string password = null, TaskLogonType LogonType = TaskLogonType.S4U, string sddl = null) { if (v2Folder != null) { return(Task.CreateTask(this.TaskService, v2Folder.RegisterTask(Path, XmlText, (int)createType, UserId, password, LogonType, sddl))); } try { TaskDefinition td = this.TaskService.NewTask(); XmlSerializationHelper.ReadObjectFromXmlText(XmlText, td); return(this.RegisterTaskDefinition(Path, td, createType, UserId == null ? td.Principal.ToString() : UserId, password, LogonType == TaskLogonType.S4U ? td.Principal.LogonType : LogonType, sddl)); } catch { throw; // new NotV1SupportedException(); } }
/// <summary> /// Gets the task with the specified path. /// </summary> /// <param name="taskPath">The task path.</param> /// <returns>The task.</returns> public Task GetTask(string taskPath) { Task t = null; if (v2TaskService != null) { V2Interop.IRegisteredTask iTask = GetTask(this.v2TaskService, taskPath); if (iTask != null) { t = Task.CreateTask(this, iTask); } } else { V1Interop.ITask iTask = GetTask(this.v1TaskScheduler, taskPath); if (iTask != null) { t = new Task(this, iTask); } } return(t); }
/// <summary> /// Gets the task with the specified path. /// </summary> /// <param name="taskPath">The task path.</param> /// <returns>The <see cref="Task"/> instance matching the <paramref name="taskPath"/>, if found. If not found, this method returns <c>null</c>.</returns> public Task GetTask([NotNull] string taskPath) { Task t = null; if (v2TaskService != null) { V2Interop.IRegisteredTask iTask = GetTask(v2TaskService, taskPath); if (iTask != null) { t = Task.CreateTask(this, iTask); } } else { taskPath = System.IO.Path.GetFileNameWithoutExtension(taskPath); V1Interop.ITask iTask = GetTask(v1TaskScheduler, taskPath); if (iTask != null) { t = new Task(this, iTask); } } return(t); }
/// <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. 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"> /// Path;Task names may not include any characters which are invalid for file names. /// or /// Path;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> public Task RegisterTaskDefinition(string Path, TaskDefinition definition, TaskCreation createType, string UserId, string password = null, TaskLogonType LogonType = TaskLogonType.S4U, string sddl = null) { if (v2Folder != null) { definition.Actions.ConvertUnsupportedActions(); var iRegTask = v2Folder.RegisterTaskDefinition(Path, definition.v2Def, (int)createType, UserId, password, LogonType, sddl); if (createType == TaskCreation.ValidateOnly && iRegTask == null) { return(null); } return(Task.CreateTask(this.TaskService, iRegTask)); } // Check for V1 invalid task names string invChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())); if (System.Text.RegularExpressions.Regex.IsMatch(Path, @"[" + invChars + @"]")) { throw new ArgumentOutOfRangeException("Path", "Task names may not include any characters which are invalid for file names."); } if (System.Text.RegularExpressions.Regex.IsMatch(Path, @"\.[^" + invChars + @"]{0,3}\z")) { throw new ArgumentOutOfRangeException("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. V1Interop.TaskFlags flags = definition.v1Task.GetFlags(); if (LogonType == TaskLogonType.InteractiveTokenOrPassword && string.IsNullOrEmpty(password)) { LogonType = TaskLogonType.InteractiveToken; } if (string.IsNullOrEmpty(UserId)) { UserId = System.Security.Principal.WindowsIdentity.GetCurrent().Name; } 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 |= (V1Interop.TaskFlags.RunOnlyIfLoggedOn | V1Interop.TaskFlags.Interactive); if (String.IsNullOrEmpty(UserId)) { UserId = System.Security.Principal.WindowsIdentity.GetCurrent().Name; } definition.v1Task.SetAccountInformation(UserId, IntPtr.Zero); break; case TaskLogonType.ServiceAccount: flags &= ~(V1Interop.TaskFlags.Interactive | V1Interop.TaskFlags.RunOnlyIfLoggedOn); definition.v1Task.SetAccountInformation((String.IsNullOrEmpty(UserId) || UserId.Equals("SYSTEM", StringComparison.CurrentCultureIgnoreCase)) ? String.Empty : UserId, IntPtr.Zero); break; case TaskLogonType.InteractiveTokenOrPassword: flags |= V1Interop.TaskFlags.Interactive; using (V1Interop.CoTaskMemString cpwd = new V1Interop.CoTaskMemString(password)) definition.v1Task.SetAccountInformation(UserId, cpwd.DangerousGetHandle()); break; case TaskLogonType.Password: using (V1Interop.CoTaskMemString cpwd = new V1Interop.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(this.TaskService, definition.v1Task)); }