Author | Message | Time |
---|---|---|
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 |