Simple way to just update an existing task?

Aug 20, 2008 at 12:51 PM
I have to supply many parameters to TaskFolder.RegisterTaskDefinition() instead of just calling Task.Save() as it was in previous version of Task Scheduler 1.0 wrapper from CodeProject.
Coordinator
Oct 14, 2008 at 11:17 PM
Edited Oct 14, 2008 at 11:23 PM
The equivalent to Task.Save() is TaskFolder.RegisterTaskDefinition(Task.Path, Task.Definition). An example follows:

TaskService ts = new TaskService();
Task t = ts.RootFolder.Tasks["MyTask"];
t.Definition.Settings.Enabled =
false;
ts.RootFolder.RegisterTaskDefinition(t.Path, t.Definition);

Mar 12, 2010 at 2:18 AM
Edited Mar 12, 2010 at 2:22 AM

Hi David,

When I was trying to enable/disable an existing task I came to exact same thing - gettings a task, changing its properties and re-registering it with TaskService. Unfortunately, ts.RootFolder.RegisterTaskDefinition(t.Path, t.Definition) doesn't work as expected and, in fact, it throws $exception {"The task has been configured with an unsupported combination of account settings and run time options. (Exception from HRESULT: 0x80041314)"} System.Exception {System.Runtime.InteropServices.COMException}.

The problem is that this task has been initially created with some custom credentials as either:

_taskService.RootFolder.RegisterTaskDefinition(
	"Task Name",
td, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.ServiceAccount, null);

or

_taskService.RootFolder.RegisterTaskDefinition(
	"Task Name",
td, TaskCreation.CreateOrUpdate, job.Schedule.AccountInformation.Account, job.Schedule.AccountInformation.Password, TaskLogonType.Password, null);

Now, in order to update an existing task I have to specify these credentials again, which is not very efficient in my case. Is there any posibility to update an existing task, preserving the original credentials?

Thanks!

Coordinator
Mar 12, 2010 at 4:46 PM

What happens when you call RegisterTaskDefinition with only two parameters like in my example above? This should pull the account name and type out of the task definition's Principal object which it got from the last registration.

Mar 15, 2010 at 2:35 AM

When I call RegisterTaskDefinition with only two parameters as shown above it throws $exception {"The task has been configured with an unsupported combination of account settings and run time options. (Exception from HRESULT: 0x80041314)"} System.Exception {System.Runtime.InteropServices.COMException}.

Coordinator
Mar 16, 2010 at 7:06 PM

Let me know if you're doing this under XP. If not, I have done some testing under Vista and have found the following:

  • Re-registering a task using TaskFolder.RegisterTaskDefinition(string path, TaskDefinition definition) works every time if you first register the task using:
    • folder.RegisterTaskDefinition(path, definition), or
    • folder.RegisterTaskDefinition(path, definition, TaskCreation.Create, null, null, LogonType.InteractiveToken, null), or
    • folder.RegisterTaskDefinition(path, definition, TaskCreation.Create, "DOMAIN\\user", null, LogonType.S4U, null), or
    • folder.RegisterTaskDefinition(path, definition, "SYSTEM", null, LogonType.ServiceAccount, null)
  • Re-registering a task using TaskFolder.RegisterTaskDefinition(string path, TaskDefinition definition) fails every time if you have initially registered and supplied a password.

I also found a problem with the way MS implemented the IRegisteredTask.Definition property. It returns a unique COM interface with every call. This causes a problem with the code I supplied above as a replacement for task.Save(). I have worked around the problem in the code by retaining the first ITaskDefinition that I get back from that property and using it. I will update the source code here shortly. I have added a new method to the Task class called RegisterChanges that will allow the following code:

TaskService ts = new TaskService();
Task t = ts.GetTask("MyTask");
t.Definition.Settings.Enabled = false;
t.RegisterChanges();
Mar 17, 2010 at 3:31 AM
Edited Mar 17, 2010 at 3:31 AM

Yes, I'm working under Windows XP SP3.

I was initially registering the task using either TaskLogonType.ServiceAccount or supplying a username and password as shown above in my first post.

By the way, here I've got a question. When using LogonType.ServiceAccount do I always need to call folder.RegisterTaskDefinition(path, definition, "SYSTEM", null, LogonType.ServiceAccount, null) or folder.RegisterTaskDefinition(path, definition, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.ServiceAccount, null) is also fine?

Thank you for support and investigation you've done!
Looking forward for a new update.

Coordinator
Mar 17, 2010 at 7:03 AM

After further testing, under V1 or V2 you must supply the username, password and logon type any time you register or re-register a task that stores its password.

To answer your question on whether or not "SYSTEM" must be supplied, the answer is "it depends". For compatibility between V1 and V2 instances you should supply it. If this will only ever act against V1 schedulers, then you don't have to as V1 provides a special condition where if the type is ServiceAccount and the name is an empty string, it assumes the SYSTEM account. Personally I would recommend always including it for code readability and for compatibility.