This project has moved. For the latest updates, please go here.

Task properties that are not defined

Nov 17, 2008 at 4:35 PM

Is possible to determine that specific property of the task is not defined?

For example, Task 'test' was never run.

Task.LastRunTime returns '1899-12-13 0:00:00' instead of null value or exception.
Task.LastTaskResult returns '1' instead of null or exception.

Maybe these properties should be nullable or exception should be thrown.

Nov 19, 2008 at 6:37 AM
I have updated Task.cs so that the LastRunTime property will return DateTime.MinValue if the task was never run. This should minimize breaking the existing code base and makes the return value for either 1.0 or 2.0 version tasks the same. Previously, 1.0 tasks returned DateTime.MinValue but 2.0 tasks returned the COM DATE structure that equated to '1899-12-30 0:00:00'. I'll include this in the next release as this has the potential to break existing code if developers were checking for that strange 1899 date. The LastRunTime can then be checked to see if the LastTaskResult value is valid.
Nov 24, 2008 at 1:05 PM
Edited Nov 25, 2008 at 2:10 PM

Thanks for reply. I will use this feature.
I have some questions about specific flags returned by v1 ITask::GetFlags() method.

This flag seems to be missing in your class. Maybe it is possible to combine it with TaskSettings.DeleteExpiredTaskAfter.

The description of this flag in MSDN  says "The work item causes the system to be resumed, or awakened, if the system is running on battery power. This flag is supported only on systems that support resume timers."

You implemented it as TaskPrincipal.LogonType. Is it correct? I think that it should be returned by TaskSettings.WakeToRun property.

public TaskLogonType LogonType
if (v2Principal != null)
return v2Principal.LogonType;
if ((v1Task.GetFlags() & V1Interop.TaskFlags.Interactive) == V1Interop.TaskFlags.Interactive)
return TaskLogonType.InteractiveToken;
else if ((v1Task.GetFlags() & V1Interop.TaskFlags.SystemRequired) == V1Interop.TaskFlags.SystemRequired)
return TaskLogonType.ServiceAccount;
throw new NotV1SupportedException();

There are no such property in the TaskSettings class.
According to MSDN TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD (IPrincipal::LogonType) and TASK_FLAG_INTERACTIVE (ITask::GetFlags) are different but Task Scheduler Wrapper thinks that they are the same (see source code fragment above).

Nov 30, 2008 at 10:14 AM

I implement TASK_DELETE_WHEN_DONE into DeleteExpiredTaskAfter property. To set this flag simply set the property to value greater or equal to TimeSpan.FromSeconds(1). If the TASK_DELETE_WHEN_DONE is not set, it return TimeSpan.Zero otherwise TimeSpan.FromSeconds(1) for V1 and something greater or equal to TimeSpan.FromSeconds(1).

public TimeSpan DeleteExpiredTaskAfter
if (v2Settings != null)
return Task.StringToTimeSpan(v2Settings.DeleteExpiredTaskAfter);
return (v1Task.GetFlags() & V1Interop.TaskFlags.DeleteWhenDone) == V1Interop.TaskFlags.DeleteWhenDone
? TimeSpan.FromSeconds(1)
: TimeSpan.Zero;
if (v2Settings != null)
v2Settings.DeleteExpiredTaskAfter = Task.TimeSpanToString(value);
V1Interop.TaskFlags flags = v1Task.GetFlags();
if (value >= TimeSpan.FromSeconds(1))
v1Task.SetFlags(flags |= V1Interop.TaskFlags.DeleteWhenDone);
v1Task.SetFlags(flags &= ~V1Interop.TaskFlags.DeleteWhenDone);
Dec 3, 2008 at 9:29 AM

Thanks for the catch on the TASK_FLAG_SYSTEM_REQUIRED flag. I have corrected it in the code, removing it from the LogonType property and applying it to the WakeOnRun property.

I also incorporated Arcao's code around DeleteWhenDone. Also a nice catch.

On the interactive flag, there is disparity between the two versions and my implementation was the closest I could come to mapping the two together. If you have a better way, please post your code.