Usposobil sem namestitev opravil na Windows 7. Zdaj je treba samo še dokončati in vse temeljito preizkusiti.
This commit is contained in:
parent
f6707528d5
commit
99c6bc3ac4
@ -27,7 +27,7 @@ ScheduledTask Application N Formatted Task application name.
|
|||||||
ScheduledTask Parameters Y Formatted Task command line parameters.
|
ScheduledTask Parameters Y Formatted Task command line parameters.
|
||||||
ScheduledTask WorkingDir N Formatted Task working directory. If the working directory is set to "", when the application is run, the current directory will be the directory in which the task scheduler service executable, Mstask.exe, resides.
|
ScheduledTask WorkingDir N Formatted Task working directory. If the working directory is set to "", when the application is run, the current directory will be the directory in which the task scheduler service executable, Mstask.exe, resides.
|
||||||
ScheduledTask Flags N DoubleInteger Task's flags to pass in IScheduledWorkItem::SetFlags() call.
|
ScheduledTask Flags N DoubleInteger Task's flags to pass in IScheduledWorkItem::SetFlags() call.
|
||||||
ScheduledTask Priority N DoubleInteger 32;64;128;256 Task's priority to pass in ITask::SetPriority() call.
|
ScheduledTask Priority N DoubleInteger 32;64;128;256;16384,32768 Task's priority to pass in ITask::SetPriority() call.
|
||||||
ScheduledTask User Y Formatted Account name to run task as. Use empty string for system account.
|
ScheduledTask User Y Formatted Account name to run task as. Use empty string for system account.
|
||||||
ScheduledTask Password Y Formatted Account password to run task as. Use NULL for system account.
|
ScheduledTask Password Y Formatted Account password to run task as. Use NULL for system account.
|
||||||
ScheduledTask Description Y Formatted Task description.
|
ScheduledTask Description Y Formatted Task description.
|
||||||
|
@ -136,8 +136,8 @@ UINT MSITSCA_API EvaluateScheduledTasks(MSIHANDLE hInstall)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
olExecute.AddTail(opCreateTask);
|
olExecute.AddTail(opCreateTask);
|
||||||
} else if (iAction >= INSTALLSTATE_ADVERTISED) {
|
} else if (iAction >= INSTALLSTATE_REMOVED) {
|
||||||
// Component is installed, but should be degraded to advertised. Delete the task.
|
// Component is installed, but should be degraded to advertised/removed. Delete the task.
|
||||||
olExecute.AddTail(new CMSITSCAOpDeleteTask(sDisplayName, MSITSCA_TASK_TICK_SIZE));
|
olExecute.AddTail(new CMSITSCAOpDeleteTask(sDisplayName, MSITSCA_TASK_TICK_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#pragma comment(lib, "taskschd.lib")
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// CMSITSCAOp
|
// CMSITSCAOp
|
||||||
@ -176,9 +178,9 @@ CMSITSCAOpCreateTask::~CMSITSCAOpCreateTask()
|
|||||||
HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession)
|
HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
CComPtr<ITask> pTask;
|
|
||||||
POSITION pos;
|
POSITION pos;
|
||||||
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
|
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
|
||||||
|
CComPtr<ITaskService> pService;
|
||||||
|
|
||||||
// Display our custom message in the progress bar.
|
// Display our custom message in the progress bar.
|
||||||
verify(::MsiRecordSetStringW(hRecordMsg, 1, m_sValue) == ERROR_SUCCESS);
|
verify(::MsiRecordSetStringW(hRecordMsg, 1, m_sValue) == ERROR_SUCCESS);
|
||||||
@ -194,52 +196,350 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession)
|
|||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the new task.
|
hr = pService.CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER);
|
||||||
hr = pSession->m_pTaskScheduler->NewWorkItem(m_sValue, CLSID_CTask, IID_ITask, (IUnknown**)&pTask);
|
if (SUCCEEDED(hr)) {
|
||||||
if (pSession->m_bRollbackEnabled) {
|
// Windows Vista or newer.
|
||||||
// Order rollback action to delete the task. ITask::NewWorkItem() might made a blank task already.
|
CComVariant vEmpty;
|
||||||
pSession->m_olRollback.AddHead(new CMSITSCAOpDeleteTask(m_sValue));
|
CComPtr<ITaskDefinition> pTaskDefinition;
|
||||||
}
|
CComPtr<ITaskSettings> pTaskSettings;
|
||||||
if (FAILED(hr)) return hr;
|
CComPtr<IPrincipal> pPrincipal;
|
||||||
|
CComPtr<IActionCollection> pActionCollection;
|
||||||
|
CComPtr<IAction> pAction;
|
||||||
|
CComPtr<IIdleSettings> pIdleSettings;
|
||||||
|
CComPtr<IExecAction> pExecAction;
|
||||||
|
CComPtr<IRegistrationInfo> pRegististrationInfo;
|
||||||
|
CComPtr<ITriggerCollection> pTriggerCollection;
|
||||||
|
CComPtr<IRegisteredTask> pTask;
|
||||||
|
CStringW str;
|
||||||
|
UINT iTrigger;
|
||||||
|
TASK_LOGON_TYPE logonType;
|
||||||
|
CComBSTR bstrContext(L"Author");
|
||||||
|
|
||||||
// Set its properties.
|
// Connect to local task service.
|
||||||
hr = pTask->SetApplicationName (m_sApplicationName ); if (FAILED(hr)) return hr;
|
hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty);
|
||||||
hr = pTask->SetComment (m_sComment ); if (FAILED(hr)) return hr;
|
|
||||||
hr = pTask->SetParameters (m_sParameters ); if (FAILED(hr)) return hr;
|
|
||||||
hr = pTask->SetWorkingDirectory(m_sWorkingDirectory); if (FAILED(hr)) return hr;
|
|
||||||
if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) {
|
|
||||||
// The task is supposed to be enabled.
|
|
||||||
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
|
|
||||||
pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE));
|
|
||||||
m_dwFlags |= TASK_FLAG_DISABLED;
|
|
||||||
}
|
|
||||||
hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) return hr;
|
|
||||||
hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) return hr;
|
|
||||||
if (!m_sAccountName.IsEmpty()) {
|
|
||||||
hr = pTask->SetAccountInformation(m_sAccountName, m_sPassword.IsEmpty() ? NULL : m_sPassword);
|
|
||||||
if (FAILED(hr)) return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) return hr;
|
|
||||||
hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) return hr;
|
|
||||||
|
|
||||||
// Add triggers.
|
|
||||||
for (pos = m_lTriggers.GetHeadPosition(); pos;) {
|
|
||||||
WORD wTriggerIdx;
|
|
||||||
CComPtr<ITaskTrigger> pTrigger;
|
|
||||||
TASK_TRIGGER &ttData = m_lTriggers.GetNext(pos);
|
|
||||||
|
|
||||||
hr = pTask->CreateTrigger(&wTriggerIdx, &pTrigger);
|
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
hr = pTrigger->SetTrigger(&ttData);
|
// Prepare the definition for a new task.
|
||||||
|
hr = pService->NewTask(0, &pTaskDefinition);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Get the task's settings.
|
||||||
|
hr = pTaskDefinition->get_Settings(&pTaskSettings);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Configure Task Scheduler 1.0 compatible task.
|
||||||
|
hr = pTaskSettings->put_Compatibility(TASK_COMPATIBILITY_V1);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Enable/disable task.
|
||||||
|
if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) {
|
||||||
|
// The task is supposed to be enabled.
|
||||||
|
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
|
||||||
|
pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE));
|
||||||
|
m_dwFlags |= TASK_FLAG_DISABLED;
|
||||||
|
}
|
||||||
|
hr = pTaskSettings->put_Enabled(m_dwFlags & TASK_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Get task actions.
|
||||||
|
hr = pTaskDefinition->get_Actions(&pActionCollection);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Add execute action.
|
||||||
|
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pAction.QueryInterface(&pExecAction);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Configure the action.
|
||||||
|
hr = pExecAction->put_Path (CComBSTR(m_sApplicationName )); if (FAILED(hr)) return hr;
|
||||||
|
hr = pExecAction->put_Arguments (CComBSTR(m_sParameters )); if (FAILED(hr)) return hr;
|
||||||
|
hr = pExecAction->put_WorkingDirectory(CComBSTR(m_sWorkingDirectory)); if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Set task description.
|
||||||
|
hr = pTaskDefinition->get_RegistrationInfo(&pRegististrationInfo);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pRegististrationInfo->put_Description(CComBSTR(m_sComment));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
hr = pRegististrationInfo->put_Author(CComBSTR(L"Amebis, d. o. o., Kamnik"));
|
||||||
|
|
||||||
|
// Configure task "flags".
|
||||||
|
if (m_dwFlags & TASK_FLAG_DELETE_WHEN_DONE) {
|
||||||
|
hr = pTaskSettings->put_DeleteExpiredTaskAfter(CComBSTR(L"PT24H"));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
hr = pTaskSettings->put_Hidden(m_dwFlags & TASK_FLAG_HIDDEN ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pTaskSettings->put_WakeToRun(m_dwFlags & TASK_FLAG_SYSTEM_REQUIRED ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pTaskSettings->put_DisallowStartIfOnBatteries(m_dwFlags & TASK_FLAG_DONT_START_IF_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pTaskSettings->put_StopIfGoingOnBatteries(m_dwFlags & TASK_FLAG_KILL_IF_GOING_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Configure task priority.
|
||||||
|
hr = pTaskSettings->put_Priority(
|
||||||
|
m_dwPriority == REALTIME_PRIORITY_CLASS ? 0 :
|
||||||
|
m_dwPriority == HIGH_PRIORITY_CLASS ? 1 :
|
||||||
|
m_dwPriority == ABOVE_NORMAL_PRIORITY_CLASS ? 2 :
|
||||||
|
m_dwPriority == NORMAL_PRIORITY_CLASS ? 4 :
|
||||||
|
m_dwPriority == BELOW_NORMAL_PRIORITY_CLASS ? 7 :
|
||||||
|
m_dwPriority == IDLE_PRIORITY_CLASS ? 9 : 7);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Get task principal.
|
||||||
|
hr = pTaskDefinition->get_Principal(&pPrincipal);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
if (m_sAccountName.IsEmpty()) {
|
||||||
|
logonType = TASK_LOGON_SERVICE_ACCOUNT;
|
||||||
|
hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr;
|
||||||
|
hr = pPrincipal->put_UserId(CComBSTR(L"S-1-5-18")); if (FAILED(hr)) return hr;
|
||||||
|
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) return hr;
|
||||||
|
} else if (m_dwFlags & TASK_FLAG_RUN_ONLY_IF_LOGGED_ON) {
|
||||||
|
logonType = TASK_LOGON_INTERACTIVE_TOKEN;
|
||||||
|
hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr;
|
||||||
|
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_LUA); if (FAILED(hr)) return hr;
|
||||||
|
} else {
|
||||||
|
logonType = TASK_LOGON_PASSWORD;
|
||||||
|
hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr;
|
||||||
|
hr = pPrincipal->put_UserId(CComBSTR(m_sAccountName)); if (FAILED(hr)) return hr;
|
||||||
|
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect principal and action collection.
|
||||||
|
hr = pPrincipal->put_Id(bstrContext);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pActionCollection->put_Context(bstrContext);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Configure idle settings.
|
||||||
|
hr = pTaskSettings->put_RunOnlyIfIdle(m_dwFlags & TASK_FLAG_START_ONLY_IF_IDLE ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pTaskSettings->get_IdleSettings(&pIdleSettings);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uS", m_wIdleMinutes*60);
|
||||||
|
hr = pIdleSettings->put_IdleDuration(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uS", m_wDeadlineMinutes*60);
|
||||||
|
hr = pIdleSettings->put_WaitTimeout(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pIdleSettings->put_RestartOnIdle(m_dwFlags & TASK_FLAG_RESTART_ON_IDLE_RESUME ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pIdleSettings->put_StopOnIdleEnd(m_dwFlags & TASK_FLAG_KILL_ON_IDLE_END ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Configure task runtime limit.
|
||||||
|
str.Format(L"PT%uS", m_dwMaxRuntimeMS != INFINITE ? (m_dwMaxRuntimeMS + 500) / 1000 : 0);
|
||||||
|
hr = pTaskSettings->put_ExecutionTimeLimit(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Get task trigger colection.
|
||||||
|
hr = pTaskDefinition->get_Triggers(&pTriggerCollection);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Add triggers.
|
||||||
|
for (pos = m_lTriggers.GetHeadPosition(), iTrigger = 0; pos; iTrigger++) {
|
||||||
|
CComPtr<ITrigger> pTrigger;
|
||||||
|
TASK_TRIGGER &ttData = m_lTriggers.GetNext(pos);
|
||||||
|
|
||||||
|
switch (ttData.TriggerType) {
|
||||||
|
case TASK_TIME_TRIGGER_ONCE: {
|
||||||
|
CComPtr<ITimeTrigger> pTriggerTime;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_TIME, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerTime); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerTime->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_TIME_TRIGGER_DAILY: {
|
||||||
|
CComPtr<IDailyTrigger> pTriggerDaily;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_DAILY, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerDaily); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerDaily->put_DaysInterval(ttData.Type.Daily.DaysInterval); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerDaily->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_TIME_TRIGGER_WEEKLY: {
|
||||||
|
CComPtr<IWeeklyTrigger> pTriggerWeekly;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_WEEKLY, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerWeekly); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerWeekly->put_WeeksInterval(ttData.Type.Weekly.WeeksInterval); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerWeekly->put_DaysOfWeek(ttData.Type.Weekly.rgfDaysOfTheWeek); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerWeekly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_TIME_TRIGGER_MONTHLYDATE: {
|
||||||
|
CComPtr<IMonthlyTrigger> pTriggerMonthly;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLY, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerMonthly); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerMonthly->put_DaysOfMonth(ttData.Type.MonthlyDate.rgfDays); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerMonthly->put_MonthsOfYear(ttData.Type.MonthlyDate.rgfMonths); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerMonthly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_TIME_TRIGGER_MONTHLYDOW: {
|
||||||
|
CComPtr<IMonthlyDOWTrigger> pTriggerMonthlyDOW;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLYDOW, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerMonthlyDOW); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerMonthlyDOW->put_WeeksOfMonth(
|
||||||
|
ttData.Type.MonthlyDOW.wWhichWeek == TASK_FIRST_WEEK ? 0x01 :
|
||||||
|
ttData.Type.MonthlyDOW.wWhichWeek == TASK_SECOND_WEEK ? 0x02 :
|
||||||
|
ttData.Type.MonthlyDOW.wWhichWeek == TASK_THIRD_WEEK ? 0x04 :
|
||||||
|
ttData.Type.MonthlyDOW.wWhichWeek == TASK_FOURTH_WEEK ? 0x08 :
|
||||||
|
ttData.Type.MonthlyDOW.wWhichWeek == TASK_LAST_WEEK ? 0x10 : 0x00); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerMonthlyDOW->put_DaysOfWeek(ttData.Type.MonthlyDOW.rgfDaysOfTheWeek); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTriggerMonthlyDOW->put_MonthsOfYear(ttData.Type.MonthlyDOW.rgfMonths); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerMonthlyDOW->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_EVENT_TRIGGER_ON_IDLE: {
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_IDLE, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: {
|
||||||
|
CComPtr<IBootTrigger> pTriggerBoot;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerBoot); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerBoot->put_Delay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TASK_EVENT_TRIGGER_AT_LOGON: {
|
||||||
|
CComPtr<ILogonTrigger> pTriggerLogon;
|
||||||
|
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTrigger.QueryInterface(&pTriggerLogon); if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.wRandomMinutesInterval);
|
||||||
|
hr = pTriggerLogon->put_Delay(CComBSTR(str)); if (FAILED(hr)) return hr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set trigger ID.
|
||||||
|
str.Format(L"%u", iTrigger);
|
||||||
|
hr = pTrigger->put_Id(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Set trigger start date.
|
||||||
|
str.Format(L"%04u-%02u-%02uT%02u:%02u:00", ttData.wBeginYear, ttData.wBeginMonth, ttData.wBeginDay, ttData.wStartHour, ttData.wStartMinute);
|
||||||
|
hr = pTrigger->put_StartBoundary(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
if (ttData.rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) {
|
||||||
|
// Set trigger end date.
|
||||||
|
str.Format(L"%04u-%02u-%02u", ttData.wEndYear, ttData.wEndMonth, ttData.wEndDay);
|
||||||
|
hr = pTrigger->put_EndBoundary(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set trigger repetition duration and interval.
|
||||||
|
if (ttData.MinutesDuration || ttData.MinutesInterval) {
|
||||||
|
CComPtr<IRepetitionPattern> pRepetitionPattern;
|
||||||
|
|
||||||
|
hr = pTrigger->get_Repetition(&pRepetitionPattern);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.MinutesDuration);
|
||||||
|
hr = pRepetitionPattern->put_Duration(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
str.Format(L"PT%uM", ttData.MinutesInterval);
|
||||||
|
hr = pRepetitionPattern->put_Interval(CComBSTR(str));
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
hr = pRepetitionPattern->put_StopAtDurationEnd(ttData.rgFlags & TASK_TRIGGER_FLAG_KILL_AT_DURATION_END ? VARIANT_TRUE : VARIANT_FALSE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable/disable trigger.
|
||||||
|
hr = pTrigger->put_Enabled(ttData.rgFlags & TASK_TRIGGER_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the task folder.
|
||||||
|
CComPtr<ITaskFolder> pTaskFolder;
|
||||||
|
hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
CComBSTR xml;
|
||||||
|
hr = pTaskDefinition->get_XmlText(&xml);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Register the task.
|
||||||
|
hr = pTaskFolder->RegisterTaskDefinition(
|
||||||
|
CComBSTR(m_sValue), // path
|
||||||
|
pTaskDefinition, // pDefinition
|
||||||
|
TASK_CREATE, // flags
|
||||||
|
vEmpty, // userId
|
||||||
|
logonType != TASK_LOGON_SERVICE_ACCOUNT && !m_sPassword.IsEmpty() ? CComVariant(m_sPassword) : vEmpty, // password
|
||||||
|
logonType, // logonType
|
||||||
|
vEmpty, // sddl
|
||||||
|
&pTask); // ppTask
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
} else {
|
||||||
|
// Windows XP or older.
|
||||||
|
CComPtr<ITask> pTask;
|
||||||
|
|
||||||
|
// Create the new task.
|
||||||
|
hr = pSession->m_pTaskScheduler->NewWorkItem(m_sValue, CLSID_CTask, IID_ITask, (IUnknown**)&pTask);
|
||||||
|
if (pSession->m_bRollbackEnabled) {
|
||||||
|
// Order rollback action to delete the task. ITask::NewWorkItem() might made a blank task already.
|
||||||
|
pSession->m_olRollback.AddHead(new CMSITSCAOpDeleteTask(m_sValue));
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Set its properties.
|
||||||
|
hr = pTask->SetApplicationName (m_sApplicationName ); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTask->SetParameters (m_sParameters ); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTask->SetWorkingDirectory(m_sWorkingDirectory); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTask->SetComment (m_sComment ); if (FAILED(hr)) return hr;
|
||||||
|
if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) {
|
||||||
|
// The task is supposed to be enabled.
|
||||||
|
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
|
||||||
|
pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE));
|
||||||
|
m_dwFlags |= TASK_FLAG_DISABLED;
|
||||||
|
}
|
||||||
|
hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
if (!m_sAccountName.IsEmpty()) {
|
||||||
|
hr = pTask->SetAccountInformation(m_sAccountName, m_sPassword.IsEmpty() ? NULL : m_sPassword);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) return hr;
|
||||||
|
hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
// Add triggers.
|
||||||
|
for (pos = m_lTriggers.GetHeadPosition(); pos;) {
|
||||||
|
WORD wTriggerIdx;
|
||||||
|
CComPtr<ITaskTrigger> pTrigger;
|
||||||
|
TASK_TRIGGER &ttData = m_lTriggers.GetNext(pos);
|
||||||
|
|
||||||
|
hr = pTask->CreateTrigger(&wTriggerIdx, &pTrigger);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
hr = pTrigger->SetTrigger(&ttData);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the task.
|
||||||
|
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
||||||
|
if (!pTaskFile) return E_NOINTERFACE;
|
||||||
|
|
||||||
|
hr = pTaskFile->Save(NULL, TRUE);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the task.
|
|
||||||
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
|
||||||
hr = pTaskFile->Save(NULL, TRUE);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,6 +557,10 @@ UINT CMSITSCAOpCreateTask::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord)
|
|||||||
|
|
||||||
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 5, m_sWorkingDirectory);
|
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 5, m_sWorkingDirectory);
|
||||||
if (uiResult != ERROR_SUCCESS) return uiResult;
|
if (uiResult != ERROR_SUCCESS) return uiResult;
|
||||||
|
if (!m_sWorkingDirectory.IsEmpty() && m_sWorkingDirectory.GetAt(m_sWorkingDirectory.GetLength() - 1) == L'\\') {
|
||||||
|
// Trim trailing backslash.
|
||||||
|
m_sWorkingDirectory.Truncate(m_sWorkingDirectory.GetLength() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sComment);
|
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sComment);
|
||||||
if (uiResult != ERROR_SUCCESS) return uiResult;
|
if (uiResult != ERROR_SUCCESS) return uiResult;
|
||||||
@ -295,7 +599,7 @@ UINT CMSITSCAOpCreateTask::SetTriggersFromView(MSIHANDLE hView)
|
|||||||
ULONGLONG ullValue;
|
ULONGLONG ullValue;
|
||||||
FILETIME ftValue;
|
FILETIME ftValue;
|
||||||
SYSTEMTIME stValue;
|
SYSTEMTIME stValue;
|
||||||
int iValue, iStartTime, iStartTimeRand;
|
int iValue;
|
||||||
|
|
||||||
// Fetch one record from the view.
|
// Fetch one record from the view.
|
||||||
uiResult = ::MsiViewFetch(hView, &hRecord);
|
uiResult = ::MsiViewFetch(hView, &hRecord);
|
||||||
@ -331,16 +635,15 @@ UINT CMSITSCAOpCreateTask::SetTriggersFromView(MSIHANDLE hView)
|
|||||||
ttData.rgFlags |= TASK_TRIGGER_FLAG_HAS_END_DATE;
|
ttData.rgFlags |= TASK_TRIGGER_FLAG_HAS_END_DATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get StartTime and StartTimeRand.
|
// Get StartTime.
|
||||||
iStartTime = ::MsiRecordGetInteger(hRecord, 4);
|
iValue = ::MsiRecordGetInteger(hRecord, 4);
|
||||||
if (iStartTime == MSI_NULL_INTEGER) return ERROR_INVALID_FIELD;
|
if (iValue == MSI_NULL_INTEGER) return ERROR_INVALID_FIELD;
|
||||||
iStartTimeRand = ::MsiRecordGetInteger(hRecord, 5);
|
ttData.wStartHour = (WORD)(iValue / 60);
|
||||||
if (iStartTimeRand != MSI_NULL_INTEGER) {
|
ttData.wStartMinute = (WORD)(iValue % 60);
|
||||||
// Add random delay to StartTime.
|
|
||||||
iStartTime += ::MulDiv(rand(), iStartTimeRand, RAND_MAX);
|
// Get StartTimeRand.
|
||||||
}
|
iValue = ::MsiRecordGetInteger(hRecord, 5);
|
||||||
ttData.wStartHour = (WORD)(iStartTime / 60);
|
ttData.wRandomMinutesInterval = iValue != MSI_NULL_INTEGER ? (WORD)iValue : 0;
|
||||||
ttData.wStartMinute = (WORD)(iStartTime % 60);
|
|
||||||
|
|
||||||
// Get MinutesDuration.
|
// Get MinutesDuration.
|
||||||
iValue = ::MsiRecordGetInteger(hRecord, 6);
|
iValue = ::MsiRecordGetInteger(hRecord, 6);
|
||||||
@ -469,6 +772,8 @@ HRESULT CMSITSCAOpDeleteTask::Execute(CMSITSCASession *pSession)
|
|||||||
|
|
||||||
// Save the backup copy.
|
// Save the backup copy.
|
||||||
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
||||||
|
if (!pTaskFile) return E_NOINTERFACE;
|
||||||
|
|
||||||
hr = pTaskFile->Save(NULL, TRUE);
|
hr = pTaskFile->Save(NULL, TRUE);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
@ -540,7 +845,7 @@ HRESULT CMSITSCAOpEnableTask::Execute(CMSITSCASession *pSession)
|
|||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
// Save the task.
|
// Save the task.
|
||||||
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
||||||
hr = pTaskFile->Save(NULL, TRUE);
|
hr = pTaskFile ? pTaskFile->Save(NULL, TRUE) : E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,6 +884,8 @@ HRESULT CMSITSCAOpCopyTask::Execute(CMSITSCASession *pSession)
|
|||||||
|
|
||||||
// Save the task.
|
// Save the task.
|
||||||
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
CComQIPtr<IPersistFile> pTaskFile(pTask);
|
||||||
|
if (!pTaskFile) return E_NOINTERFACE;
|
||||||
|
|
||||||
hr = pTaskFile->Save(NULL, TRUE);
|
hr = pTaskFile->Save(NULL, TRUE);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
- Dodano opravilo se ne vidi med opravili v Task Scheduler-ju.
|
- Naredi še o(ne)mogoèanje opravil z uporabo Task Scheduler 2.0.
|
||||||
|
- Preizkusi vse nastavitve opravila in vrste sprožilcev, èe se pravilno izdelajo.
|
||||||
- Tudi akcije deferred/commit/rollback naj pošiljajo obvestila o napakah.
|
- Tudi akcije deferred/commit/rollback naj pošiljajo obvestila o napakah.
|
||||||
|
@ -43,6 +43,7 @@ using namespace ATL;
|
|||||||
#include <msiquery.h>
|
#include <msiquery.h>
|
||||||
#include <mstask.h>
|
#include <mstask.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <taskschd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
Loading…
x
Reference in New Issue
Block a user