Thursday, April 26, 2007

Scheduling Tasks

Stonefield Query has had a reports scheduler for several years. We simply use the Windows Task Scheduler to run Stonefield Query, with the name of the report to run and where to send the output as parameters, at the desired schedule. To communicate with the Task Scheduler, we use the freeware TaskScheduler.DLL, written by Mark Pryor. It doesn't look like the site I downloaded it from is available anymore, so it's in the download mentioned later.

However, after upgrading to Windows Vista, I discovered the scheduler didn't work. In researching this issue, I discovered that Vista includes Task Scheduler 2.0, while the DLL was written to support Task Scheduler 1.0, which has a completely different interface. So, back to the drawing board.

Fortunately, the MSDN documentation on Task Scheduler 2.0 has tons of detail and several examples in VBScript, which are easily converted to VFP. Because I still need to use Task Scheduler 1.0 with XP and earlier systems, I decided to create a TaskScheduler base class and XP and Vista subclasses of it.

I won't show the code for these classes here because it's fairly lengthy (you can download it from the Technical Papers page of my Web site), but here are some examples of how easy they are to use to schedule tasks. These examples run on Vista; use XPTaskScheduler instead for Windows XP or earlier.
* Create a task that runs at 3:00 AM every day.

loSchedule = createobject('VistaTaskScheduler')
with loSchedule
.TaskName = 'My Task Name'
.UserName = 'Your Windows UserName'
.Password = 'Your Windows Password'
.StartTime = {^2007-04-26 03:00:00}
.EXEName = 'Full path to EXE'
.EXEParameters = 'Any parameters to pass'
.ScheduleType = 1 && daily
if not .CreateTask()
messagebox(.ErrorMessage)
endif not .CreateTask()
endwith

* Create a weekly task that runs at 3:00 AM Tues, Thurs, and Sat
* of every second week.

loSchedule = createobject('VistaTaskScheduler')
with loSchedule
.TaskName = 'My Task Name'
.UserName = 'Your Windows UserName'
.Password = 'Your Windows Password'
.StartTime = {^2007-04-26 03:00:00}
.EXEName = 'Full path to EXE'
.EXEParameters = 'Any parameters to pass'
.ScheduleType = 2 && weekly
.Interval = 2
store .T. to .DaysOfWeek[3], .DaysOfWeek[5], .DaysOfWeek[7]
if not .CreateTask()
messagebox(.ErrorMessage)
endif not .CreateTask()
endwith

* Create a monthly task that runs at 3:00 AM on the 1st and 15th
* of every month.

loSchedule = createobject('VistaTaskScheduler')
with loSchedule
.TaskName = 'My Task Name'
.UserName = 'Your Windows UserName'
.Password = 'Your Windows Password'
.StartTime = {^2007-04-26 03:00:00}
.EXEName = 'Full path to EXE'
.EXEParameters = 'Any parameters to pass'
.ScheduleType = 3
store .T. to .DaysOfMonth[1], .DaysOfMonth[15]
.MonthsOfYear = .T. && initialize all 12 elements of array to .T.
if not .CreateTask()
messagebox(.ErrorMessage)
endif not .CreateTask()
endwith

12 comments:

Anonymous said...

Doug,
Any idea how to get the scheduled task to run using the 'NT AUTHORITY\SYSTEM' account instead of a defined user name and password?

I have tried passing Empty and Null to the username and password properties, but no luck.

Thanks

Chris

Doug Hennig said...

Sorry, I don't know.

Anonymous said...

IScheduledWorkItem::SetAccountInformation
The SetAccountInformation method sets the account name and password used to run the work item.

HRESULT SetAccountInformation(
LPCWSTR pwszAccountName,
LPCWSTR pwszPassword
);

Parameters
pwszAccountName
[in] String that contains the name of the user account in which the work item will run. To specify the local system account, use the empty string, L"". Do not use any other string to specify the local system account. For more information, see Remarks.
pwszPassword
[in] String that contains the password for the account specified in pwszAccountName.
Set this parameter to NULL if the local account is specified or, optionally, for an account other than local system if the TASK_FLAG_RUN_ONLY_IF_LOGGED_ON flag was not passed to IScheduledWorkItem::SetFlags. (The TASK_FLAG_RUN_ONLY_IF_LOGGED_ON flag is provided so that applications can schedule tasks in their own accounts without knowing their own accounts' passwords.) For more information, see Remarks.

Task Scheduler stores account information only once for all tasks that use the same account. If the account password is updated for one task, then all tasks using that same account will use the updated password.

Byron said...

I have used the task scheduling api and the task gets put on the schedule but doesn't run. There are other tasks on the schedule placed there by other companies which do run. Going through the properties of those that do run and mine I cannot tell why mine does not. The only difference i can ascertain is that each of those also has a .job file in the Windows/Tasks folder and mine does not. I'm running Windows 7.

Any thoughts?

Doug Hennig said...

I create tasks all the time without a .job file and they run fine. Do you mean they don't get started at all or they do get started but raise an error? If the latter, you'll likely have to instrument your app (we do that heavily) to determine where it crashes.

Byron said...

They are on the schedule but do not start at all.

Doug Hennig said...

I've seen this happen when there's a permissions issue. Try Googling any error code that's displayed.

Byron said...

there are no error messages. i can, from the Task Scheduler screen, click on the entry and the click on the Run option and nothing happens

Byron said...

If there were a way of sending you the image or images of the schedule and the properties of the task i would, I have compared the properties with those of the others and there is very little difference. Not enough to keep it from working.

Maybe there is a permission thing set on my system that doesn't allow it to work. Any idea of where to look?

Doug Hennig said...

You won't see any error message but there should be an error code of some kind, either in Task Scheduler or in the Windows Event Log.

Byron said...

Where might i find the error code? I don't know where to find the Windows Event Log and have not found, in the Task Scheduler, where to find it.

Doug Hennig said...

Your best bet is to post your question on one of the various support forums.