Valhalla Legends Forums Archive | Web Development | ITaskScheduler, from a web interface

AuthorMessageTime
KrAzY_NuK
Hi,

I'm trying to implement a watered down version of the windows task scheduler using ITaskScheduler.  I can't use AT.exe because it doesn't let you name the task, I can't use the WMI task scheduler because it's based on AT.  I also can't use schtasks because this needs to work on both win2k and win2k3 servers.

I've already written the program, and it's been quite a while since i've done any c/c++ programming.  The program works fine when I run it from the console on a server, or when i run it from the console on my own computer.

When i plug it in to a web interface however, it doesn't run.  I've wrapped it in a bat file so that i can redirect the output to a TXT file, and when I run it I get absolutely nothing from the program output to the file, but i do get all the output from the bat file.

Now, if i comment out the majority of the Task Scheduler program (ie everything EXCEPT the call to NewWorkItem() ), I get output from the program, including "Failed calling NewWorkItem, error = 0x80070005".  I've looked everywhere for that error, but have had no success at all!

Currently I'm running windows 2000, and the test webserver is running IIS 6.0 on a windows 2003 machine.  The web interface is in ASP.NET using VB.NET on the server side.  If there's any more information required, please ask and i'll post it.

Here's the code:
[code]
#include <windows.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <objidl.h>
#include <wchar.h>
#include <stdio.h>
#include <atlbase.h>

#define DELIM ":"
#define APPLICATION_NAME L"d:\\apps\\cow\\scripts\\autoshutdown\\autoshutdown.cmd"
#define WORKING_DIRECTORY L"d:\\apps\\cow\\scripts\\autoshutdown"
#define ACCOUNT L"myAccount"
#define PASSWORD L"myPassword"

void printUsage( char *error )
{
    if ( error != NULL )
        printf( "%s\n\n", error );

    printf( "Usage: TaskScheduler [options]\n" );
    printf( "\nRequired Options:\n" );
    printf( "\t/name:<name of the task>\n" );
    printf( "\t/server:<UNC path of the server to run the task on>\n" );
    printf( "\t/type:<iis | oracle>\n" );
    printf( "\t/nature:<recycle | shutdown>\n" );
    printf( "\t/shu:<normal | force>\n" );
    printf( "\t/stime:<starting time HHmm>\n" );
    printf( "\t/sdate:<starting date YYYYMMDD>\n" );

    printf( "\t/run:<once | weekly-(umtwrfs)>\n" );
   
    printf( "\nOther Options:\n" );
    printf( "\t/v Will run the application in verbose mode\n" );
//            printf( "\t\n" );
//            printf( "\t\n" );
//            printf( "\t\n" );
    printf( "\n/? Will display this help screen\n" );

    exit(1);
}

void doRunStuff( TASK_TRIGGER_TYPE *oTriggerType, TRIGGER_TYPE_UNION *oType, WEEKLY *oWeek, char* info)
{
    if( strcmp( info, "once" ) == 0 )
    {
        *oTriggerType = TASK_TIME_TRIGGER_ONCE;
       
    }
    else if( strncmp( info, "weekly", 6 ) == 0 )
    {
        *oTriggerType = TASK_TIME_TRIGGER_WEEKLY;
        oWeek->WeeksInterval = 1;
        oWeek->rgfDaysOfTheWeek = 0;
       
        for( unsigned int i = 6; i < strlen( info ); i++ )
        {
            switch ( info[i] )
            {
                case 'u': oWeek->rgfDaysOfTheWeek |= TASK_SUNDAY; break;
                case 'm': oWeek->rgfDaysOfTheWeek |= TASK_MONDAY; break;
                case 't': oWeek->rgfDaysOfTheWeek |= TASK_TUESDAY; break;
                case 'w': oWeek->rgfDaysOfTheWeek |= TASK_WEDNESDAY; break;
                case 'r': oWeek->rgfDaysOfTheWeek |= TASK_THURSDAY; break;
                case 'f': oWeek->rgfDaysOfTheWeek |= TASK_FRIDAY; break;
                case 's': oWeek->rgfDaysOfTheWeek |= TASK_SATURDAY; break;
            }
        }
       
        oType->Weekly = *oWeek;
    }
}

int main(int argc, char **argv)
{
    printf("Started the program\n");
    /////////////////////////////////////////////////////////////////
    // Grab the arguments before we do anything else.
    /////////////////////////////////////////////////////////////////
    char *tmpArg = NULL;
    char *startTime = NULL;
    char *startDate = NULL;
    CComBSTR taskName = NULL;
    CComBSTR serverName = NULL;
    CComBSTR serverType = NULL;
    CComBSTR nature = NULL;
    CComBSTR typeOfShutdown = NULL;
    CComBSTR verbose = "  ";
    CComBSTR params = NULL;
    WORD day = NULL;
    WORD month = NULL;
    WORD year = NULL;
    WORD hour = NULL;
    WORD min = NULL;
    TASK_TRIGGER_TYPE oTriggerType;
    TRIGGER_TYPE_UNION oType;
    WEEKLY oWeek;
   
    TASK_TRIGGER Trigger;   
   
    if ( argc <= 1 )
    {
        printUsage( "No arguments specified." );
    }
   
    for( int i = 1; i < argc; i++ )
    {
        tmpArg = strtok( strlwr( argv[i] ), DELIM );
       
        if( strcmp( "/?", tmpArg ) == 0 ) printUsage( NULL );
        else if( strcmp( tmpArg, "/name" ) == 0 ) taskName = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/server" ) == 0 ) serverName = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/type" ) == 0 ) serverType = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/nature" ) == 0 ) nature = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/shu" ) == 0 ) typeOfShutdown = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/stime" ) == 0 ) startTime = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/sdate" ) == 0 ) startDate = strtok( NULL, DELIM );
        else if( strcmp( tmpArg, "/run" ) == 0 ) doRunStuff( &oTriggerType, &oType, &oWeek, strtok( NULL, DELIM ) );
        else if( strcmp( tmpArg, "/v" ) == 0 ) verbose = L"-v";
        else printUsage( strcat( tmpArg, " is an invalid argument." ) );
    }
printf( "Read in all the arguments\n");   
    if( taskName == NULL ) printUsage( "Please specify a Task Name" );
    if( serverName == NULL ) printUsage( "Please specify a Server Name" );
    if( serverType == NULL ) printUsage( "Please specify a Server Type" );
    if( nature == NULL ) printUsage( "Please specify the nature of the task" );
    if( typeOfShutdown == NULL ) printUsage( "Please specify a type of shutdown" );
    if( startTime == NULL ) printUsage( "Please specify a starting time" );
    if( startDate == NULL ) printUsage( "Please specify a starting date" );
printf("validated arguments\n");   
    day = atoi( startDate + 6 );
    startDate[6] = '\0';
    month = atoi( startDate + 4 );
    startDate[4] = '\0';
    year = atoi( startDate );
    min = atoi( startTime + 2 );
    startTime[2] = '\0';
    hour = atoi( startTime );
   
    tmpArg = new char[256];
    sprintf( tmpArg, "%S %S %S %S", typeOfShutdown, nature, serverType, verbose );
    params = tmpArg;
    delete( tmpArg );
printf("creating trigger\n"); 

    ZeroMemory(&Trigger, sizeof(TASK_TRIGGER));

    Trigger.cbTriggerSize = sizeof(TASK_TRIGGER);
    Trigger.wBeginDay = day;
    Trigger.wBeginMonth = month;
    Trigger.wBeginYear = year;
    Trigger.wStartHour = hour;
    Trigger.wStartMinute = min;
    Trigger.rgFlags = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END;
    Trigger.TriggerType = oTriggerType;
    Trigger.Type = oType;
printf("trigger created\n");

    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();
            printf( "Failed calling CoCreateInstance, error = 0x%x\n", hr );
            return 1;
        }
    }
    else
    {
        printf( "Failed calling CoInitialize, error = 0x%x\n", hr );
        return 1;
    }
     
     
    /////////////////////////////////////////////////////////////////
    // Call ITaskScheduler::NewWorkItem to create new task.
    /////////////////////////////////////////////////////////////////
    ITask *pITask;
    IPersistFile *pIPersistFile;
/*REMOVE ME
    hr = pITS->SetTargetComputer( serverName );
    if (FAILED(hr))
    {
        CoUninitialize();
        printf("Failed calling SetTargetComputer, error = 0x%x\n",hr);
        pITS->Release();
        return 1;
    }
REMOVE ME*/

    hr = pITS->NewWorkItem(taskName,           // Name of task
                            CLSID_CTask,            // Class identifier
                            IID_ITask,              // Interface identifier
                            (IUnknown**)&pITask); // Address of task interface
     
    pITS->Release();                               // Release object
    if (FAILED(hr))
    {
        CoUninitialize();
        printf("Failed calling NewWorkItem, error = 0x%x\n",hr);
        return 1;
    }
   
/*REMOVE ME
    hr = pITask->SetApplicationName( APPLICATION_NAME );
    if ( FAILED( hr ) )
    {
        pITask->Release();
        CoUninitialize();
        printf("Failed calling SetApplicationName, error = 0x%x\n", hr );
        return 1;
    }
   
    hr = pITask->SetWorkingDirectory( WORKING_DIRECTORY );
    if( FAILED( hr ) )
    {
        pITask->Release();
        CoUninitialize();
        printf("Failed calling SetWorkingDirectory, error = 0x%x\n", hr );
        return 1;
    }

    hr = pITask->SetAccountInformation( ACCOUNT, PASSWORD );
    if( FAILED( hr ) )
    {
        pITask->Release();
        CoUninitialize();
        printf("Failed calling SetAccountInformation, error = 0x%x\n", hr );
        return 1;
    }
   
    hr = pITask->SetParameters( params );
    if ( FAILED( hr ) )
    {
        pITask->Release();
        CoUninitialize();
        printf("Failed calling SetParameters, error = 0x%x\n", hr );
        return 1;
    }
   
    WORD iTrigger;
    ITaskTrigger *pITT;
    hr = pITask->CreateTrigger( &iTrigger, &pITT );
    if( FAILED(hr) )
    {
        pITask->Release();
        pITT->Release();
        CoUninitialize();
        printf("Failed calling CreateTrigger, error = 0x%x\n", hr );
        return 1;
    }
   
    hr = pITT->SetTrigger( &Trigger );
    if( FAILED(hr) )
    {
        pITask->Release();
        pITT->Release();
        CoUninitialize();
        printf("Failed calling SetTrigger, error = 0x%x\n", hr );
        return 1;
    }

    // Release the ITaskTrigger when we're done with it.
    pITT->Release();
     
    /////////////////////////////////////////////////////////////////
    // Call IUnknown::QueryInterface to get a pointer to
    // IPersistFile and IPersistFile::Save to save
    // the new task to disk.
    /////////////////////////////////////////////////////////////////
    hr = pITask->QueryInterface(IID_IPersistFile,
                                (void **)&pIPersistFile);
     
    pITask->Release();
    if (FAILED(hr))
    {
        CoUninitialize();
        printf("Failed calling QueryInterface, error = 0x%x\n",hr);
        return 1;
    }

    hr = pIPersistFile->Save(NULL,
                            TRUE);
    pIPersistFile->Release();
    if (FAILED(hr))
    {
        CoUninitialize();
        printf("Failed calling Save, error = 0x%x\n",hr);
        return 1;
    }
REMOVE ME*/     
    printf( "Successfully created task %S on %S.\nThe task is to %S %S the %S server.", taskName, serverName, typeOfShutdown, nature, serverType );
    return 0;
}
[/code]

When i run this through the web interface i get the following output:
[code]Started the program
Read in all the arguments
validated arguments
creating trigger
trigger created
Failed calling NewWorkItem, error = 0x80070005[/code]

if i remove the comment blocks that say "REMOVE ME" I don't get any output, as if the program never ran.

I'm pretty sure this is a web development issue, as my program works fine from the console.  Unfortunately i haven't done much web development (and obviously it's been a long time since i've done c++).
December 17, 2004, 3:59 PM
peofeoknight
so what exactly is this? Its just a taskscheduler that you can maintain from the internet with an asp.net page?
December 17, 2004, 11:42 PM
Myndfyr
I looked through the first page of Google results for "0x80070005" and they have a common theme -- "Access denied."  In other words, you can't create a new work item with the ASPNET or IUSR_MACHINENAME account.  You need more privileges.
December 19, 2004, 9:22 AM
KrAzY_NuK
[quote author=quasi-modo link=topic=9931.msg92723#msg92723 date=1103326964]
so what exactly is this? Its just a taskscheduler that you can maintain from the internet with an asp.net page?
[/quote]

Yeah, well kinda.  It'll never be on the internet, just sitting on our intranet...


[quote author=MyndFyre link=topic=9931.msg92923#msg92923 date=1103448137]
I looked through the first page of Google results for "0x80070005" and they have a common theme -- "Access denied."  In other words, you can't create a new work item with the ASPNET or IUSR_MACHINENAME account.  You need more privileges.
[/quote]

What's really blowing my mind is that if I un-comment everything, it doesn't run at all, I also had, and continue to have that page set to run as my own username (just to stay away from worrying about priviledges for now)
December 20, 2004, 5:29 PM

Search