Sign in with
Sign up | Sign in
Your question

Help! A call to ITask::Run in Windows returns success but ..

Last response: in Windows XP
Share
August 18, 2005 5:10:19 PM

Archived from groups: microsoft.public.windowsxp.general (More info?)

I occasionally create a number of tasks via the ITaskScheduler
interface and then Run them immediately. For some reason, even though
Windows returns a successful response to the Run request, a task
occasionally fails to start up. No error code is ever given.

I've pulled together the essence of the VC++ program below. Take a look
and see if you have any ideas (other than suggesting the SDK is
flawed)! Note that you have to fill in the username and password at
the bottom before running it, as well as install a do-nothing program
named test1.exe into one of the directories in your path.

By default the program below, when compiled, will create 50 scheduled
tasks and try to run each one immediately. Note afterwards that some
of the tasks never run. Why??? By the way, I have tried this on a
slow system and a fast system, both running Windows XP with SP2.

/Martin

// testsched.cpp : Defines the entry point for the console application.

#include <stdio.h>
#include <mstask.h>
#include <sys/timeb.h>

const int MAX_NAME_LENGTH = 1024;

/********************************************************************
*
* FUNCTION: PersistTask
*
* DESCRIPTION: Calls QueryInterface to get a pointer to IPersistFile
* then IPersistFile::Save to save the task info. to disk.
*
* LIMITATIONS: Task name should be fewer than 1024 characters.
*
********************************************************************/

HRESULT PersistTask(ITask * const pITask)
{
HRESULT hr;
IPersistFile *pIPersistFile;


hr = pITask->QueryInterface(IID_IPersistFile,
(void **)&pIPersistFile);
if (FAILED(hr))
{
return hr;
}
hr = pIPersistFile->Save(NULL,
TRUE);
pIPersistFile->Release();
return hr;
}

/********************************************************************
*
* FUNCTION: CreateSchedItem
*
* DESCRIPTION: This function creates a new task for the scheduler.
* To run it or set up a trigger use one of the other
* functions below.
*
* LIMITATIONS: Task name should be fewer than 1024 characters.
*
********************************************************************/

HRESULT CreateSchedItem(const char *lpszTaskName,
const char *lpszAppName,
const char *lpszParms,
const char *lpszUserName,
const char *lpszPassword)

{
HRESULT hr = S_OK;
ITaskScheduler *pITS;

/////////////////////////////////////////////////////////////////
// Call CoInitialize to initialize the COM library and then
// CoCreateInstance to get the Task Scheduler object.
/////////////////////////////////////////////////////////////////

hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_CTaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskScheduler,
(void **) &pITS);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
}
else
{
return hr;
}

/////////////////////////////////////////////////////////////////
// Call ITaskScheduler::NewWorkItem to create new task.
/////////////////////////////////////////////////////////////////
wchar_t *lpwc = new wchar_t[MAX_NAME_LENGTH];
mbstowcs(lpwc, lpszTaskName, MAX_NAME_LENGTH);

ITask *pITask;
hr = pITS->NewWorkItem(lpwc, // Name of task
CLSID_CTask, // Class identifier
IID_ITask, // Interface
identifier
(IUnknown**)&pITask); // Address of task
interface

if (FAILED(hr))
{
CoUninitialize();
delete []lpwc;
return hr;
}

pITS->Release(); // release the scheduler
/////////////////////////////////////////////////////////////////
// Call ITask::SetApplicationName to associate an application with
the task
/////////////////////////////////////////////////////////////////

mbstowcs(lpwc, lpszAppName, MAX_NAME_LENGTH);
hr = pITask->SetApplicationName(lpwc);

if (FAILED(hr))
{
CoUninitialize();
delete []lpwc;
return hr;
}

/////////////////////////////////////////////////////////////////
// Call ITask::SetParameters to associate an application with the
task
/////////////////////////////////////////////////////////////////

mbstowcs(lpwc, lpszParms, MAX_NAME_LENGTH);
hr = pITask->SetParameters(lpwc);

if (FAILED(hr))
{
CoUninitialize();
delete []lpwc;
return hr;
}

/////////////////////////////////////////////////////////////////
// Call ITask::SetAccountInformation
/////////////////////////////////////////////////////////////////

wchar_t *lpwc2 = new wchar_t[MAX_NAME_LENGTH];

mbstowcs(lpwc, lpszUserName, MAX_NAME_LENGTH);
mbstowcs(lpwc2, lpszPassword, MAX_NAME_LENGTH);

hr = pITask->SetAccountInformation(lpwc, lpwc2);

delete [] lpwc; // Don't need name any more.
delete [] lpwc2; // Ditto
if (FAILED(hr))
{
CoUninitialize();
return hr;
}


hr = PersistTask(pITask);
pITask->Release();

CoUninitialize();
return hr;
}

/********************************************************************
*
* FUNCTION: RunSchedItem
*
* DESCRIPTION: This function runs the task immediately.
*
* LIMITATIONS: Task name should be fewer than 1024 characters.
*
********************************************************************/

HRESULT RunSchedItem(const char *lpszTaskName)

{
HRESULT hr = S_OK;
ITaskScheduler *pITS;

/////////////////////////////////////////////////////////////////
// Call CoInitialize to initialize the COM library and then
// CoCreateInstance to get the Task Scheduler object.
/////////////////////////////////////////////////////////////////

hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_CTaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskScheduler,
(void **) &pITS);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
}
else
{
return hr;
}
///////////////////////////////////////////////////////////////////
// Call ITaskScheduler::Activate to get the Task object.
///////////////////////////////////////////////////////////////////
wchar_t *lpwc = new wchar_t[MAX_NAME_LENGTH];
mbstowcs(lpwc, lpszTaskName, MAX_NAME_LENGTH);

ITask *pITask;
hr = pITS->Activate(lpwc,
IID_ITask,
(IUnknown**) &pITask);

delete [] lpwc; // Don't need name any more.
pITS->Release();
if (FAILED(hr))
{
CoUninitialize();
return hr;
}


///////////////////////////////////////////////////////////////////
// Call ITask::Run to start execution of "Test Task".
///////////////////////////////////////////////////////////////////

hr = pITask->Run();

pITask->Release();
CoUninitialize();
return hr;
}

/********************************************************************
*
* FUNCTION: main
*
* DESCRIPTION: Call CreateSchedItem and RunSchedItem numerous times
*
********************************************************************/
int main(int argc, char* argv[])
{
struct _timeb tstruct;
int icount, iresult;
char ts[20];
// if argument passed in, use it for number of loops else set to 50.
if (argc > 1) icount = atoi(argv[1]);
else icount = 50;
while (icount > 0)
{
_ftime( &tstruct); // Use UTC time in the task name to help figure
things out.
sprintf(ts,"Test
%02u-%02u-%02u-%03u",(tstruct.time%86400)/3600,(tstruct.time%3600)/60,tstruct.time%60,tstruct.millitm);
iresult = CreateSchedItem(ts,"Test1.exe","","***Fill in
Username***","***Fill in password***");
if (iresult != 0) return iresult;
iresult = RunSchedItem(ts);
if (iresult != 0) return iresult;
icount -= 1;
}
return 0;
}
Anonymous
August 19, 2005 10:18:38 AM

Archived from groups: microsoft.public.windowsxp.general (More info?)

Maybe you just don't read the SDK

Remarks
Run is an asynchronous operation. A return code of S_OK means that the request to run the work item has been made; it does not mean that the work item has started running. There may be a delay of a few seconds after Run returns before the work item actually starts running.

To determine whether the work item is running, call IScheduledWorkItem::GetStatus.



Use TS's Log to see why it's not running.


--
--------------------------------------------------------------------------------------------------
http://webdiary.smh.com.au/archives/_comment/001075.htm...
=================================================
"Martin" <mfraser@hillsdaleinv.com> wrote in message news:1124395819.685468.234460@g14g2000cwa.googlegroups.com...
>I occasionally create a number of tasks via the ITaskScheduler
> interface and then Run them immediately. For some reason, even though
> Windows returns a successful response to the Run request, a task
> occasionally fails to start up. No error code is ever given.
>
> I've pulled together the essence of the VC++ program below. Take a look
> and see if you have any ideas (other than suggesting the SDK is
> flawed)! Note that you have to fill in the username and password at
> the bottom before running it, as well as install a do-nothing program
> named test1.exe into one of the directories in your path.
>
> By default the program below, when compiled, will create 50 scheduled
> tasks and try to run each one immediately. Note afterwards that some
> of the tasks never run. Why??? By the way, I have tried this on a
> slow system and a fast system, both running Windows XP with SP2.
>
> /Martin
>
> // testsched.cpp : Defines the entry point for the console application.
>
> #include <stdio.h>
> #include <mstask.h>
> #include <sys/timeb.h>
>
> const int MAX_NAME_LENGTH = 1024;
>
> /********************************************************************
> *
> * FUNCTION: PersistTask
> *
> * DESCRIPTION: Calls QueryInterface to get a pointer to IPersistFile
> * then IPersistFile::Save to save the task info. to disk.
> *
> * LIMITATIONS: Task name should be fewer than 1024 characters.
> *
> ********************************************************************/
>
> HRESULT PersistTask(ITask * const pITask)
> {
> HRESULT hr;
> IPersistFile *pIPersistFile;
>
>
> hr = pITask->QueryInterface(IID_IPersistFile,
> (void **)&pIPersistFile);
> if (FAILED(hr))
> {
> return hr;
> }
> hr = pIPersistFile->Save(NULL,
> TRUE);
> pIPersistFile->Release();
> return hr;
> }
>
> /********************************************************************
> *
> * FUNCTION: CreateSchedItem
> *
> * DESCRIPTION: This function creates a new task for the scheduler.
> * To run it or set up a trigger use one of the other
> * functions below.
> *
> * LIMITATIONS: Task name should be fewer than 1024 characters.
> *
> ********************************************************************/
>
> HRESULT CreateSchedItem(const char *lpszTaskName,
> const char *lpszAppName,
> const char *lpszParms,
> const char *lpszUserName,
> const char *lpszPassword)
>
> {
> HRESULT hr = S_OK;
> ITaskScheduler *pITS;
>
> /////////////////////////////////////////////////////////////////
> // Call CoInitialize to initialize the COM library and then
> // CoCreateInstance to get the Task Scheduler object.
> /////////////////////////////////////////////////////////////////
>
> hr = CoInitialize(NULL);
> if (SUCCEEDED(hr))
> {
> hr = CoCreateInstance(CLSID_CTaskScheduler,
> NULL,
> CLSCTX_INPROC_SERVER,
> IID_ITaskScheduler,
> (void **) &pITS);
> if (FAILED(hr))
> {
> CoUninitialize();
> return hr;
> }
> }
> else
> {
> return hr;
> }
>
> /////////////////////////////////////////////////////////////////
> // Call ITaskScheduler::NewWorkItem to create new task.
> /////////////////////////////////////////////////////////////////
> wchar_t *lpwc = new wchar_t[MAX_NAME_LENGTH];
> mbstowcs(lpwc, lpszTaskName, MAX_NAME_LENGTH);
>
> ITask *pITask;
> hr = pITS->NewWorkItem(lpwc, // Name of task
> CLSID_CTask, // Class identifier
> IID_ITask, // Interface
> identifier
> (IUnknown**)&pITask); // Address of task
> interface
>
> if (FAILED(hr))
> {
> CoUninitialize();
> delete []lpwc;
> return hr;
> }
>
> pITS->Release(); // release the scheduler
> /////////////////////////////////////////////////////////////////
> // Call ITask::SetApplicationName to associate an application with
> the task
> /////////////////////////////////////////////////////////////////
>
> mbstowcs(lpwc, lpszAppName, MAX_NAME_LENGTH);
> hr = pITask->SetApplicationName(lpwc);
>
> if (FAILED(hr))
> {
> CoUninitialize();
> delete []lpwc;
> return hr;
> }
>
> /////////////////////////////////////////////////////////////////
> // Call ITask::SetParameters to associate an application with the
> task
> /////////////////////////////////////////////////////////////////
>
> mbstowcs(lpwc, lpszParms, MAX_NAME_LENGTH);
> hr = pITask->SetParameters(lpwc);
>
> if (FAILED(hr))
> {
> CoUninitialize();
> delete []lpwc;
> return hr;
> }
>
> /////////////////////////////////////////////////////////////////
> // Call ITask::SetAccountInformation
> /////////////////////////////////////////////////////////////////
>
> wchar_t *lpwc2 = new wchar_t[MAX_NAME_LENGTH];
>
> mbstowcs(lpwc, lpszUserName, MAX_NAME_LENGTH);
> mbstowcs(lpwc2, lpszPassword, MAX_NAME_LENGTH);
>
> hr = pITask->SetAccountInformation(lpwc, lpwc2);
>
> delete [] lpwc; // Don't need name any more.
> delete [] lpwc2; // Ditto
> if (FAILED(hr))
> {
> CoUninitialize();
> return hr;
> }
>
>
> hr = PersistTask(pITask);
> pITask->Release();
>
> CoUninitialize();
> return hr;
> }
>
> /********************************************************************
> *
> * FUNCTION: RunSchedItem
> *
> * DESCRIPTION: This function runs the task immediately.
> *
> * LIMITATIONS: Task name should be fewer than 1024 characters.
> *
> ********************************************************************/
>
> HRESULT RunSchedItem(const char *lpszTaskName)
>
> {
> HRESULT hr = S_OK;
> ITaskScheduler *pITS;
>
> /////////////////////////////////////////////////////////////////
> // Call CoInitialize to initialize the COM library and then
> // CoCreateInstance to get the Task Scheduler object.
> /////////////////////////////////////////////////////////////////
>
> hr = CoInitialize(NULL);
> if (SUCCEEDED(hr))
> {
> hr = CoCreateInstance(CLSID_CTaskScheduler,
> NULL,
> CLSCTX_INPROC_SERVER,
> IID_ITaskScheduler,
> (void **) &pITS);
> if (FAILED(hr))
> {
> CoUninitialize();
> return hr;
> }
> }
> else
> {
> return hr;
> }
> ///////////////////////////////////////////////////////////////////
> // Call ITaskScheduler::Activate to get the Task object.
> ///////////////////////////////////////////////////////////////////
> wchar_t *lpwc = new wchar_t[MAX_NAME_LENGTH];
> mbstowcs(lpwc, lpszTaskName, MAX_NAME_LENGTH);
>
> ITask *pITask;
> hr = pITS->Activate(lpwc,
> IID_ITask,
> (IUnknown**) &pITask);
>
> delete [] lpwc; // Don't need name any more.
> pITS->Release();
> if (FAILED(hr))
> {
> CoUninitialize();
> return hr;
> }
>
>
> ///////////////////////////////////////////////////////////////////
> // Call ITask::Run to start execution of "Test Task".
> ///////////////////////////////////////////////////////////////////
>
> hr = pITask->Run();
>
> pITask->Release();
> CoUninitialize();
> return hr;
> }
>
> /********************************************************************
> *
> * FUNCTION: main
> *
> * DESCRIPTION: Call CreateSchedItem and RunSchedItem numerous times
> *
> ********************************************************************/
> int main(int argc, char* argv[])
> {
> struct _timeb tstruct;
> int icount, iresult;
> char ts[20];
> // if argument passed in, use it for number of loops else set to 50.
> if (argc > 1) icount = atoi(argv[1]);
> else icount = 50;
> while (icount > 0)
> {
> _ftime( &tstruct); // Use UTC time in the task name to help figure
> things out.
> sprintf(ts,"Test
> %02u-%02u-%02u-%03u",(tstruct.time%86400)/3600,(tstruct.time%3600)/60,tstruct.time%60,tstruct.millitm);
> iresult = CreateSchedItem(ts,"Test1.exe","","***Fill in
> Username***","***Fill in password***");
> if (iresult != 0) return iresult;
> iresult = RunSchedItem(ts);
> if (iresult != 0) return iresult;
> icount -= 1;
> }
> return 0;
> }
>
August 19, 2005 10:30:18 AM

Archived from groups: microsoft.public.windowsxp.general (More info?)

I realize that Run is asynchronous and that S_OK means that the task
has only been queued. The problem is that the tasks never run. Much
later Task Scheduler shows Last Run Time = "Never", Next Run Time =
"Never", Last Result = 0 and an empty Status. No errors are reported.
If I right-click on the task and select "Run" it works fine.

Try the code and see. I've only tried on machines with Windows XP and
SP2 but it seems to be a general problem on the machines I have tried
it on.

I've scrutinized MSDN up and down, Googled left and right but nada so
far. I'm reluctant to cough up $250 to pester Microsoft as I figure
I'll only have to write a follow-up task using GetStatus that checks up
on the Scheduler for tasks that it has "forgotten" about.

Generally I like Windows but these quirks are making me think twice
about it.
Related resources
August 19, 2005 2:44:06 PM

Archived from groups: microsoft.public.windowsxp.general (More info?)

I've never looked at Task Scheduler's Advanced menu before. I spent
some time over lunch looking at the log and some of the other advanced
features.

None of the missed tasks appeared in the logs. I thought I also found a
few other tasks that weren't there but they may have been purged when
the logfile wrapped. In my last test of adding 40 jobs I found all but
the unscheduled tasks in the log (twice actually, once when the task
started and once when it completed).

I also played with the "Notify Me of Missed Tasks" option on the
Advanced Menu. It made me think, "hey, maybe they recognize that tasks
do get missed and I can get a program notification to help me with
automation". I checked the box, reran my test program, and noted that
as usual, a few tasks were missed but no notification popped up. This,
despite my being an administrator on the machine being tested. A
Google search of the "Notify Me of Missed Tasks" option indicated that
others had also experienced this; there were also a number of
grumblings, like mine, about the failures of the Task Scheduler.

Sigh! This last search did reveal a couple of third-party schedulers
that might be more robust. Now I just need to convince my clients to
pay for them. Or write my own notification for missed tasks.
August 19, 2005 4:11:21 PM

Archived from groups: microsoft.public.windowsxp.general (More info?)

I ran into the 0x8007007a problem last week after returning from a
week's vacation. A couple of weeks worth of scheduled tasks had
surpassed Microsoft's limit and my tasks were all halting on 0x8007007a
(it actually started the day I got back). I was surprised that Task
Scheduler seemed so limited (I only had about 1000 tasks in the
scheduler) and made me question the robustness of Task Scheduler. It
seems pretty rough around the edges.

The problem I have now only seems to happen with pITask->Run. I have
never had problems with triggered tasks (i.e. scheduled). I could
probably do away with Run altogether and simply fork off a shell to
execute the job. It just seems tidier to treat all jobs through the
same mechanism regardless of whether they await a scheduled time or can
be run immediately.

/Martin
Anonymous
August 20, 2005 3:58:26 AM

Archived from groups: microsoft.public.windowsxp.general (More info?)

What about Task Scheduler's log. Advanced menu.

--
--------------------------------------------------------------------------------------------------
http://webdiary.smh.com.au/archives/_comment/001075.htm...
=================================================
"Martin" <mfraser@hillsdaleinv.com> wrote in message news:1124458218.425506.193410@g44g2000cwa.googlegroups.com...
>I realize that Run is asynchronous and that S_OK means that the task
> has only been queued. The problem is that the tasks never run. Much
> later Task Scheduler shows Last Run Time = "Never", Next Run Time =
> "Never", Last Result = 0 and an empty Status. No errors are reported.
> If I right-click on the task and select "Run" it works fine.
>
> Try the code and see. I've only tried on machines with Windows XP and
> SP2 but it seems to be a general problem on the machines I have tried
> it on.
>
> I've scrutinized MSDN up and down, Googled left and right but nada so
> far. I'm reluctant to cough up $250 to pester Microsoft as I figure
> I'll only have to write a follow-up task using GetStatus that checks up
> on the Scheduler for tasks that it has "forgotten" about.
>
> Generally I like Windows but these quirks are making me think twice
> about it.
>
!