• Welcome to Valhalla Legends Archive.
 

ITaskScheduler, from a web interface

Started by KrAzY_NuK, December 17, 2004, 09:59 AM

Previous topic - Next topic

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:

#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;
}


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


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++).

quasi-modo

so what exactly is this? Its just a taskscheduler that you can maintain from the internet with an asp.net page?
WAR EAGLE!
Quote(00:04:08) zdv17: yeah i quit doing that stuff cause it jacked up the power bill too much
(00:04:19) nick is a turtle: Right now im not paying the power bill though
(00:04:33) nick is a turtle: if i had to pay the electric bill
(00:04:47) nick is a turtle: id hibernate when i go to class
(00:04:57) nick is a turtle: or at least when i go to sleep
(00:08:50) zdv17: hibernating in class is cool.. esp. when you leave a drool puddle

MyndFyre

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.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

KrAzY_NuK

Quote from: quasi-modo on December 17, 2004, 05:42 PM
so what exactly is this? Its just a taskscheduler that you can maintain from the internet with an asp.net page?

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


Quote from: MyndFyre on December 19, 2004, 03:22 AM
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.

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)