HRESULT CScheduledTask::SaveTask ( LPCTSTR szTaskName, BOOL bFailIfExists /*=FALSE*/ ) const { HRESULT hr; ITaskScheduler* pISched = NULL; IUnknown* pIUnk = NULL; IPersistFile* pIFile = NULL; ITask* pITask = NULL; ITaskTrigger* pITaskTrig = NULL; TASK_TRIGGER rTrigger; DWORD dwTaskFlags; WORD wTrigNumber; USES_CONVERSION; ASSERT ( AfxIsValidString ( szTaskName )); // Get an interface to the scheduler. hr = ::CoCreateInstance ( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &pISched ); if ( FAILED(hr) ) { #ifdef _DEBUG TRACE1("CScheduledTask::SaveTask() - failed to create a task scheduler interface. Return = 0x%08X\n", (DWORD) hr ); // Check if the error was "class not registered". If so, you don't // have the scheduler installed. I display a nice long message in // the debug window, which hopefully explains what's up. :) if ( REGDB_E_CLASSNOTREG == hr ) { TRACE0(" The error was REGDB_E_CLASSNOTREG, meaning you don't have the scheduler installed.\n" _T(" If you are running 95 or NT 4 with IE 4, you must install the task scheduler from the\n") _T(" IE components install page on MS's web site or the IE CD.\n") _T(" If you're on 98, NT 5, or 95/NT 4 with IE 5, then something's wrong with your install\n") _T(" because the scheduler should always be installed.\n") _T(" Note that this class does *NOT* work with the \"AT\" service, which is the default\n") _T(" scheduler on NT 4 and earlier.\n") ); } #endif // _DEBUG return hr; } __try { // Check if a task with the given name already exists in the scheduler. // I do this check manually because the behavior of // ITaskScheduler::NewWorkItem() is different between IE 4 and IE 5. // In IE 4, NewWorkItem() will succeed if a task with the name you pass it // already exists (even though the INetSDK docs says it should fail). // In IE 5, NewWorkItem() has been fixed to match the docs. // So, my solution is to call ITaskScheduler::Activate() and pass it the // task name. If that function succeeds, then I know a task with the // given name already exists. // (Note to MS: This _really_ ought to be mentioned in the KB!!) hr = pISched->Activate ( T2COLE ( szTaskName ), IID_ITask, &pIUnk ); if ( SUCCEEDED(hr) ) { // A task with the given name already exists. Check bFailIfExists // to see what we should do. pIUnk->Release(); // We don't need this interface. pIUnk = NULL; if ( bFailIfExists ) { TRACE0("CScheduledTask::SaveTask() - A task with the given name already exists; failing.\n"); return HRESULT_FROM_WIN32 ( ERROR_FILE_EXISTS ); } else { // Try to delete the existing task. If the delete succeeds, then // we proceed. Otherwise, we'll bail out with an error. TRACE0("CScheduledTask::SaveTask() - A task with the given name already exists; deleting it.\n"); hr = CScheduledTask::DeleteTask ( szTaskName ); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - couldn't delete existing task! Bailing out. Return = 0x%08X\n", (DWORD) hr ); return hr; } } } // Create a new task. hr = pISched->NewWorkItem ( T2COLE ( szTaskName ), CLSID_CTask, IID_ITask, &pIUnk ); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - couldn't create a new work item. Return = 0x%08X\n", (DWORD) hr ); return hr; } // We now have an IUnknown pointer. This is queried for an ITask // pointer on the work item we just added. hr = pIUnk->QueryInterface ( IID_ITask, (void **) &pITask ); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - QI() on IUnknown failed to get an ITask. Return = 0x%08X\n", (DWORD) hr ); return hr; } // Clean up the IUnknown, as we are done with it. pIUnk->Release(); pIUnk = NULL; // Set the program name. hr = pITask->SetApplicationName ( T2COLE( (LPCTSTR) m_sProgramPath )); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to set application. Return = 0x%08X\n", (DWORD) hr ); return hr; } // Set the app's parameters. if ( m_sParameters.GetLength() > 0 ) { hr = pITask->SetParameters ( T2COLE( (LPCTSTR) m_sParameters )); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to set parameters. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // Set the starting directory. if ( m_sStartingDir.GetLength() > 0 ) { hr = pITask->SetWorkingDirectory ( T2COLE( (LPCTSTR) m_sStartingDir )); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to set starting directory. Return = 0x%08X\n", (DWORD) hr ); return hr; } } TCHAR infoBuf[32767]; DWORD bufCharCount = 32767; GetUserNameEx(NameSamCompatible, infoBuf, &bufCharCount); hr = pITask->SetAccountInformation((LPCWSTR)infoBuf, L""); // Set the job comment. if ( m_sComment.GetLength() > 0 ) { hr = pITask->SetComment ( T2COLE( (LPCTSTR) m_sComment )); if ( FAILED (hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to set task comment. Return = 0x%08X\n", (DWORD) hr ); return hr; } } //TCHAR pszName[CREDUI_MAX_USERNAME_LENGTH] = ""; //TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH] = ""; /////////////////////////////////////////////////////////////////// // Call ITask::SetAccountInformation to specify the account name // and the account password for Test Task. /////////////////////////////////////////////////////////////////// //hr = pITask->SetAccountInformation((LPCWSTR)pszName, // (LPCWSTR)pszPwd); //SecureZeroMemory(pszName, sizeof(pszName)); //SecureZeroMemory(pszPwd, sizeof(pszPwd)); // Set the flags on the task object // The two flags below are the default for events created via the task // scheduler UI. // Note that I _don't_ set TASK_FLAG_DELETE_WHEN_DONE. Setting this flag // is bad if you have the "Notify me of missed tasks" option on in the // scheduler. If this flag is set and the event is missed, the scheduler // nukes the event without notifying you . How mean. dwTaskFlags = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON; // On NT, set the interactive flag so the user can see it. if ( !( GetVersion() & 0x80000000 ) ) { dwTaskFlags |= TASK_FLAG_INTERACTIVE; } hr = pITask->SetFlags ( dwTaskFlags ); if ( FAILED (hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to set task flags. Return = 0x%08X\n", (DWORD) hr ); return hr; } // Now, create a trigger to run the task at our specified time. hr = pITask->CreateTrigger ( &wTrigNumber, &pITaskTrig ); if ( FAILED (hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to create a task trigger. Return = 0x%08X\n", (DWORD) hr ); return hr; } // Now, fill in the trigger as necessary. Note that the seconds field of // m_timeStart is not used since the scheduler only stores the hour // and minute of the starting time. ZeroMemory ( &rTrigger, sizeof (TASK_TRIGGER) ); rTrigger.cbTriggerSize = sizeof (TASK_TRIGGER); rTrigger.wBeginYear = m_timeStart.wYear; rTrigger.wBeginMonth = m_timeStart.wMonth; rTrigger.wBeginDay = m_timeStart.wDay; rTrigger.wStartHour = m_timeStart.wHour; rTrigger.wStartMinute = m_timeStart.wMinute; if ( 0 != m_timeEnd.wYear ) { rTrigger.rgFlags = TASK_TRIGGER_FLAG_HAS_END_DATE; rTrigger.wEndYear = m_timeEnd.wYear; rTrigger.wEndMonth = m_timeEnd.wMonth; rTrigger.wEndDay = m_timeEnd.wDay; } switch ( m_eFreq ) { case freqOnce: rTrigger.TriggerType = TASK_TIME_TRIGGER_ONCE; break; case freqDaily: rTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY; // Repeat every day. rTrigger.Type.Daily.DaysInterval = 1; break; case freqWeekly: rTrigger.TriggerType = TASK_TIME_TRIGGER_WEEKLY; rTrigger.Type.Weekly.rgfDaysOfTheWeek = GetDayOfWeekFlag ( m_timeStart ); // Repeat every week. rTrigger.Type.Weekly.WeeksInterval = 1; break; case freqMonthly: rTrigger.TriggerType = TASK_TIME_TRIGGER_MONTHLYDATE; rTrigger.Type.MonthlyDate.rgfDays = 1 << ( m_timeStart.wDay - 1 ); rTrigger.Type.MonthlyDate.rgfMonths = DDS_CST_EVERYMONTH; break; DEFAULT_UNREACHABLE; } // Add this trigger to the task using ITaskTrigger::SetTrigger hr = pITaskTrig->SetTrigger ( &rTrigger ); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to add trigger to the task. Return = 0x%08X\n", (DWORD) hr ); return hr; } // Save the changes with IPersistFile::SaveTask(). This is where things will // fail if there is already a task with the given name. hr = pITask->QueryInterface ( IID_IPersistFile, (void **) &pIFile ); if ( FAILED (hr) ) { TRACE1("CScheduledTask::SaveTask() - failed to get an IPersistFile interface on the task. Return = 0x%08X\n", (DWORD) hr ); return hr; } hr = pIFile->Save ( NULL, FALSE ); if ( FAILED(hr) ) { TRACE1("CScheduledTask::SaveTask() - error saving task. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // end __try __finally { // Clean up all the interfaces. if ( pIFile != NULL ) pIFile->Release(); if ( pITaskTrig != NULL ) pITaskTrig->Release(); if ( pITask != NULL ) pITask->Release(); if ( pISched != NULL ) pISched->Release(); } // end __finally return hr; }
/** * Set a Task into task scheduler. It takes values to insert from Schedule form. * If task already exists, it is updated with passed parameters. * Starting time is always set to current time (task starts now). * * @param frequency : NEVER or EVERY_DAY * @param dayNum : repeate the task every 'dayNum' * @param minNum : repeate the task every 'minNum' * @return 0 if no errors. */ int setScheduleTask (const char* frequency, const int dayNum, const int minNum) { HRESULT hr = S_OK; bool newTask = false; ITaskScheduler* pITS = NULL; ITask* pITask; IPersistFile* pIPersistFile; wstring taskName, user; // Init COM library & create instance for Task scheduler. if ((pITS = initScheduleInstance()) == NULL) { goto error; } // Task is associated with current user if (getScheduledTaskName(taskName)) { goto error; } // We need the extended username "MACHINE\USER" to ensure that // the job can run also for users logged in with another domain (ref bug #307010). if (getWindowsUserEx(user)) { goto error; } // // Try to open EXISTING TASK. // LOG.debug("Try opening the Windows task: \"%ls\"", taskName.c_str()); hr = pITS->Activate(taskName.c_str(), IID_ITask, (IUnknown**) &pITask); if (FAILED(hr)) { if (hr == E_OBJECT_NOT_FOUND) { // // NEW TASK -> create it. // LOG.debug(DBG_SCHED_TASK_NOT_FOUND); newTask = true; WCHAR path[512]; OutlookConfig* config = OutlookConfig::getInstance(); // Get current working dir (from config) const char* t = config->getWorkingDir(); WCHAR* wt = toWideChar(t); wsprintf(path, TEXT("\"%s\\%s\""), wt, TEXT(PROGRAM_NAME_EXE)); delete [] wt; wt = NULL; hr = pITS->NewWorkItem(taskName.c_str(), // Name of task CLSID_CTask, // Class identifier IID_ITask, // Interface identifier (IUnknown**)&pITask); // Address of task interface if (FAILED(hr)) { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_NEWWORKITEM, hr, msg); delete [] msg; pITS->Release(); goto error; } // Set path and comment on new task. pITask->SetApplicationName(path); pITask->SetComment(SCHED_COMMENT); } else { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_ACTIVATE, hr, msg); delete [] msg; pITS->Release(); goto error; } } pITS->Release(); // // Set task params: flags, account info, parameters if (strcmp(NEVER, frequency) == 0) { pITask->SetFlags(TASK_FLAG_DISABLED); } else { pITask->SetAccountInformation(user.c_str(), NULL); pITask->SetFlags(TASK_FLAG_INTERACTIVE | TASK_FLAG_RUN_ONLY_IF_LOGGED_ON); } // ...so we have "OutlookPlugin.exe schedule" pITask->SetParameters(SCHED_PARAM); // // Get/create the trigger object. // ITaskTrigger *pITaskTrigger; if (newTask) { WORD piNewTrigger; hr = pITask->CreateTrigger(&piNewTrigger, &pITaskTrigger); if (FAILED(hr)) { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_CREATE_TRIGGER, hr, msg); delete [] msg; goto error; } } else { hr = pITask->GetTrigger(0, &pITaskTrigger); if (FAILED(hr)) { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_GET_TRIGGER, hr, msg); delete [] msg; goto error; } } ////////////////////////////////////////////////////// // Define TASK_TRIGGER structure. // Start time is derived from NOW. ////////////////////////////////////////////////////// TASK_TRIGGER pTrigger; ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER)); time_t timer; time(&timer); struct tm* now = localtime(&timer); int minToSet = minNum; if (minToSet == 1440) { minToSet = 1439; // this because the windows scheduler thrown an error if // the value is a day } pTrigger.wBeginDay = now->tm_mday; // START = NOW. // TASK_TRIGGER uses wBeginMonth in interval (1,12), but tm_mon is in interval (0,11) pTrigger.wBeginMonth = now->tm_mon + 1; pTrigger.wBeginYear = now->tm_year + 1900; // 'struct tm' has year from 1900... pTrigger.wStartHour = now->tm_hour; pTrigger.wStartMinute = now->tm_min - 1; // -1 to avoid starting a sync right now! pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER) ; pTrigger.MinutesDuration = 1440; // Duration = fixed 1 day. pTrigger.MinutesInterval = minToSet; pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY; // Manage only DAILY schedules! pTrigger.Type.Daily.DaysInterval = dayNum; ////////////////////////////////////////////////////// // // Set trigger criteria. // hr = pITaskTrigger->SetTrigger(&pTrigger); if (FAILED(hr)) { if (hr == E_INVALIDARG) { setErrorF(getLastErrorCode(), ERR_SCHED_SET_TRIGGER, hr, ERR_SCHED_INVALID_PARAM); } else { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_SET_TRIGGER, hr, msg); delete [] msg; } goto error; } // // Call IUnknown::QueryInterface to get a pointer to IPersistFile. // hr = pITask->QueryInterface(IID_IPersistFile, (void **)&pIPersistFile); if (FAILED(hr)) { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_QUERY_INTERFACE, hr, msg); delete [] msg; goto error; } pITask->Release(); pITaskTrigger->Release(); // // Save the task to disk. // hr = pIPersistFile->Save(NULL, TRUE); if (FAILED(hr)) { char* msg = readSystemErrorMsg(hr); setErrorF(getLastErrorCode(), ERR_SCHED_SAVE, hr, msg); delete [] msg; goto error; } pIPersistFile->Release(); LOG.info(INFO_SCHED_TASK_CREATED); CoUninitialize(); return 0; error: CoUninitialize(); LOG.error(getLastErrorMsg()); return 1; }
HRESULT CTask::SaveTask ( LPCTSTR szTaskName, BOOL bFailIfExists /*=FALSE*/ ) const { HRESULT hr; ITaskScheduler* pISched = NULL; IUnknown* pIUnk = NULL; IPersistFile* pIFile = NULL; ITask* pITask = NULL; ITaskTrigger* pITaskTrig = NULL; TASK_TRIGGER rTrigger; DWORD dwTaskFlags; WORD wTrigNumber; USES_CONVERSION; ASSERT ( AfxIsValidString ( szTaskName )); // Sciezka programu nie moze byc pusta, ale inne moga if ( 0 == m_timeStart.wYear || NULL == szTaskName || 0 == lstrlen ( szTaskName ) || m_sProgramPath.GetLength() < 1 ) { return E_FAIL; } // Pobieramy interface IScheduler hr = ::CoCreateInstance ( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &pISched ); if ( FAILED(hr) ) { #ifdef _DEBUG TRACE1("CTask::SaveTask() - failed to create a task scheduler interface. Return = 0x%08X\n", (DWORD) hr ); // Harmonogram zadan nie zostal zainstalowany lub zostal odinstalowany if ( REGDB_E_CLASSNOTREG == hr ) { TRACE0(" The error was REGDB_E_CLASSNOTREG, meaning you don't have the scheduler installed.\n" _T(" If you are running 95 or NT 4 with IE 4, you must install the task scheduler from the\n") _T(" IE components install page on MS's web site or the IE CD.\n") _T(" If you're on 98, NT 5, or 95/NT 4 with IE 5, then something's wrong with your install\n") _T(" because the scheduler should always be present.\n") _T(" Note that this class does *NOT* work with the \"AT\" service, which is the default\n") _T(" scheduler on NT 4 and earlier.\n") ); } #endif // _DEBUG return hr; } __try { //sprawdz czy zadanie o podanek przez uzytkownika nazwie istnieje hr = pISched->Activate ( T2COLE ( szTaskName ), IID_ITask, &pIUnk ); if ( SUCCEEDED(hr) ) { //zadanie o podanej nazwie juz istnieje, sprawdzmy bFailIfExists. pIUnk->Release(); // zwalniamy interfejs pIUnk = NULL; if ( bFailIfExists ) { TRACE0("CTask::SaveTask() - A task with the given name already exists; failing.\n"); return HRESULT_FROM_WIN32 ( ERROR_FILE_EXISTS ); } else { //probujemy usunac istniejace zadanie, by zrobic miejsce dla naszego. TRACE0("CTask::SaveTask() - A task with the given name already exists; deleting it.\n"); hr = CTask::DeleteTask ( szTaskName ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - couldn't delete existing task! Bailing out. Return = 0x%08X\n", (DWORD) hr ); return hr; } } } // tworzymy nowe zadanie. hr = pISched->NewWorkItem ( T2COLE ( szTaskName ), CLSID_CTask, IID_ITask, &pIUnk ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - couldn't create a new work item. Return = 0x%08X\n", (DWORD) hr ); return hr; } //mamy wskaznik do IUnknown, odpytujemy go, aby uzyskac //wskaznik do interfejsu ITask hr = pIUnk->QueryInterface ( IID_ITask, (void **) &pITask ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - QI() on IUnknown failed to get an ITask. Return = 0x%08X\n", (DWORD) hr ); return hr; } // wskaznika do IUnknown juz nie potrzebujemy pIUnk->Release(); pIUnk = NULL; // ustawiamy nazwe dla aplikacji hr = pITask->SetApplicationName ( T2COLE( (LPCTSTR) m_sProgramPath )); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - failed to set application. Return = 0x%08X\n", (DWORD) hr ); return hr; } // ustawiamy parametry dla aplikacji if ( m_sParameters.GetLength() > 0 ) { hr = pITask->SetParameters ( T2COLE( (LPCTSTR) m_sParameters )); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - failed to set parameters. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // ustawiamy folder startowy dla aplikacji if ( m_sStartingDir.GetLength() > 0 ) { hr = pITask->SetWorkingDirectory ( T2COLE( (LPCTSTR) m_sStartingDir )); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - failed to set starting directory. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // ustawiamy nazwe uzytkownika i haslo, jesli jestesmy na NT if ( m_bNT ) { hr = pITask->SetAccountInformation ( T2COLE( (LPCTSTR) m_sAccount), T2COLE( (LPCTSTR) m_sPassword) ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - failed to set account info. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // ustawiamy komentarz do zadania if ( m_sComment.GetLength() > 0 ) { hr = pITask->SetComment ( T2COLE( (LPCTSTR) m_sComment )); if ( FAILED (hr) ) { TRACE1("CTask::SaveTask() - failed to set task comment. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // ustawiamy flagi //zapraszam do eksperymentow z flaga TASK_FLAG_DELETE_WHEN_DONE... dwTaskFlags = TASK_FLAG_DONT_START_IF_ON_BATTERIES | TASK_FLAG_KILL_IF_GOING_ON_BATTERIES; // na NT ustawimy flage interactive if ( !( GetVersion() & 0x80000000 ) ) { dwTaskFlags |= TASK_FLAG_INTERACTIVE; } hr = pITask->SetFlags ( dwTaskFlags ); if ( FAILED (hr) ) { TRACE1("CTask::SaveTask() - failed to set task flags. Return = 0x%08X\n", (DWORD) hr ); return hr; } // teraz tworzymy Trigger, czyli wyzwalacz hr = pITask->CreateTrigger ( &wTrigNumber, &pITaskTrig ); if ( FAILED (hr) ) { TRACE1("CTask::SaveTask() - failed to create a task trigger. Return = 0x%08X\n", (DWORD) hr ); return hr; } //ustawimy parametry triggera //zwroc uwage ze sekundy sa ignorowane ZeroMemory ( &rTrigger, sizeof (TASK_TRIGGER) ); rTrigger.cbTriggerSize = sizeof (TASK_TRIGGER); rTrigger.wBeginYear = m_timeStart.wYear; rTrigger.wBeginMonth = m_timeStart.wMonth; rTrigger.wBeginDay = m_timeStart.wDay; rTrigger.wStartHour = m_timeStart.wHour; rTrigger.wStartMinute = m_timeStart.wMinute; if ( 0 != m_timeEnd.wYear ) { rTrigger.rgFlags = TASK_TRIGGER_FLAG_HAS_END_DATE; rTrigger.wEndYear = m_timeEnd.wYear; rTrigger.wEndMonth = m_timeEnd.wMonth; rTrigger.wEndDay = m_timeEnd.wDay; } switch ( m_eFreq ) { case freqOnce: rTrigger.TriggerType = TASK_TIME_TRIGGER_ONCE; break; case freqDaily: rTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY; // codziennie. rTrigger.Type.Daily.DaysInterval = 1; break; case freqWeekly: rTrigger.TriggerType = TASK_TIME_TRIGGER_WEEKLY; rTrigger.Type.Weekly.rgfDaysOfTheWeek = GetDayOfWeekFlag ( m_timeStart ); // co tydzien. rTrigger.Type.Weekly.WeeksInterval = 1; break; //co miesiac. case freqMonthly: rTrigger.TriggerType = TASK_TIME_TRIGGER_MONTHLYDATE; rTrigger.Type.MonthlyDate.rgfDays = 1 << ( m_timeStart.wDay - 1 ); rTrigger.Type.MonthlyDate.rgfMonths = DDS_CST_EVERYMONTH; break; DEFAULT_UNREACHABLE; } // skojarz Trigger z zadaniem hr = pITaskTrig->SetTrigger ( &rTrigger ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - failed to add trigger to the task. Return = 0x%08X\n", (DWORD) hr ); return hr; } // zapisujemy zmiany w PersistFile hr = pITask->QueryInterface ( IID_IPersistFile, (void **) &pIFile ); if ( FAILED (hr) ) { TRACE1("CTask::SaveTask() - failed to get an IPersistFile interface on the task. Return = 0x%08X\n", (DWORD) hr ); return hr; } hr = pIFile->Save ( NULL, FALSE ); if ( FAILED(hr) ) { TRACE1("CTask::SaveTask() - error saving task. Return = 0x%08X\n", (DWORD) hr ); return hr; } } // end __try __finally { // sprzatamy if ( pIFile != NULL ) pIFile->Release(); if ( pITaskTrig != NULL ) pITaskTrig->Release(); if ( pITask != NULL ) pITask->Release(); if ( pISched != NULL ) pISched->Release(); } // end __finally return hr; }