dahall / TaskScheduler

Provides a .NET wrapper for the Windows Task Scheduler. It aggregates the multiple versions, provides an editor and allows for localization.
MIT License
1.21k stars 191 forks source link

Daily task with SessionStateChangeTrigger is giving COMException: '(11,27):Duration:PT15M' #892

Closed kondareddy closed 3 years ago

kondareddy commented 3 years ago

I want to create app update scheduled task which run daily once when system is locked. I have attempted with below code but I am getting "System.Runtime.InteropServices.COMException: '(11,27):Duration:PT15M'"

What I am doing wrong here? Any help please?

// Create a new task definition for the local machine and assign properties TaskDefinition td = TaskService.Instance.NewTask(); td.RegistrationInfo.Description = "This keeps app upto date with latest updates.";

// Add a trigger that, that runs every day at 5 AM var todayDate = DateTime.Now.ToString("yyyy-MM-dd") + " 05"; var startDate = DateTime.ParseExact(todayDate, "yyyy-MM-dd HH", System.Globalization.CultureInfo.InvariantCulture); //// session locked SessionStateChangeTrigger st = new SessionStateChangeTrigger { StateChange = TaskSessionStateChangeType.SessionLock }; st.Delay = TimeSpan.FromMinutes(5); st.StartBoundary = startDate.AddDays(1);
st.Repetition.Interval = TimeSpan.FromDays(1); st.Repetition.Duration = TimeSpan.FromMinutes(15); st.Repetition.StopAtDurationEnd = true; td.Triggers.Add(st); //td.Principal.RunLevel = TaskRunLevel.Highest;

//Create an action that will launch Notepad whenever the trigger fires td.Actions.Add(new ExecAction(@"c:\program data\app\app.exe", "/SilentInstall")); td.Settings.WakeToRun = true; td.Settings.DisallowStartIfOnBatteries = false; TaskService.Instance.RootFolder.RegisterTaskDefinition("appUpdate", td);

dahall commented 3 years ago

The value for Interval must be less than or equal to the value for Duration when registering the task. I think you have the meaning of the two switched.

Also, to make the system work less for the StartBoundary, use st.StartBoundary = DateTime.Today.AddDays(1).AddHours(5);. Then you can ignore all the work parsing for startDate.

To be more brief, you could construct st as follows:

td.Triggers.Add(new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock) { Delay = TimeSpan.FromMinutes(5),
   StartBoundary = DateTime.Today.AddDays(1).AddHours(5), Repetition = new RepetitionPattern(TimeSpan.FromMinutes(15),
   TimeSpan.FromDays(1), true) });
kondareddy commented 3 years ago

Thanks for reply. I have attempted like below but - got below exception "(46,4):UserId:" - Any Idea what's the mistake here?

var st = new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock) { Delay = TimeSpan.FromMinutes(5), StartBoundary = DateTime.Today.AddDays(1).AddHours(5), Repetition = new RepetitionPattern(TimeSpan.FromMinutes(15), TimeSpan.FromDays(1), true) }; // Register the task in the root folder of the local machine const string taskName = "AppUpdate"; Task td = TaskService.Instance.AddTask(taskName, st, new ExecAction(@"c:\program data\jmb\app.exe", "/SilentInstall"), "This keeps app upto date with latest updates.");

dahall commented 3 years ago

Hm. Try using String.Empty as the second parameter to the SessionStateChangeTrigger constructor.

kondareddy commented 3 years ago

Thanks for reply. Can I run only once task with below code? even though system got locked multiple time - want to run only once? is that possible?

var st = new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock) { Delay = TimeSpan.FromMinutes(5), StartBoundary = DateTime.Today.AddDays(1).AddHours(5), Repetition = new RepetitionPattern(TimeSpan.FromDays(1), TimeSpan.FromDays(1), true) };

dahall commented 3 years ago

This will run starting the next day at 5:00 a.m., 5 minutes after the system is locked, and then will repeat one time, 24 hours later. Is that what you were expecting?

kondareddy commented 3 years ago

No - happening multiple times - for each unlock // Add a trigger that starts from every day at 5 AM var st = new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock) { Delay = TimeSpan.FromMinutes(5), StartBoundary = DateTime.Today.AddDays(1).AddHours(5), Repetition = new RepetitionPattern(TimeSpan.FromDays(1), TimeSpan.FromDays(1), true) };

st.UserId = Environment.UserName; td.Triggers.Add(st); td.Settings.RunOnlyIfNetworkAvailable = true; td.Settings.StartWhenAvailable = true;

Capture

dahall commented 3 years ago

Just to be clear, there are 5 system events for each task run (129,100,200,201,102). From the screenshot, it appears that the system was locked at 5:25:22 and 5:38:19. Is that the case? Let me rephrase what I said earlier: The task will run 5 minutes after each time the system is locked after the next day at 5:00 a.m. and then will repeat one time, 24 hours later. Please clarify or provide more of the system log with details about when the system was actually locked.

dahall commented 3 years ago

Also, save a line of code and provide the user in the constructor: new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock, Environment.UserName).

kondareddy commented 3 years ago

Thanks for prompt replies. The task will run 5 minutes after each time the system is locked after the next day at 5:00 a.m. and then will repeat one time, 24 hours later. How can make it run only once per day - starting from tomorrow Please clarify or provide more of the system log with details about when the system was actually locked. Do you want event viewer as logs?

dahall commented 3 years ago

If you just need a task to run every day at 5 a.m. starting tomorrow, then just use:

td.Triggers.Add(new DailyTrigger(1) { StartBoundary = DateTime.Today.AddHours(24 + 5) });
kondareddy commented 3 years ago

So with below code with/with-out repetitions - task will run every time system is locked? Please confirm?

var st = new SessionStateChangeTrigger(TaskSessionStateChangeType.SessionLock) { Delay = TimeSpan.FromMinutes(5), StartBoundary = DateTime.Today.AddMinutes(1), };

dahall commented 3 years ago

Yes, 5 minutes after every lock.

kondareddy commented 3 years ago

Thanks - we are good to close