Я работаю над проектом, которому необходимо установить ряд задач планировщика задач Windows, и для этого я создал проект Wix и пользовательское действие, которое заботится обо всех деталях. Это пользовательское действие было создано с использованием C++, чтобы избежать зависимостей от .NET Framework.TaskScheduler ExecAction put_WorkingDirectory не обновляет свое значение
Сначала я начал выполнять SCHTASKS.EXE из пользовательского действия Wix, но после того, как мне удалось создать правильную командную строку для правильной установки задачи, я понял, что не могу установить Рабочий каталог Action («Начать в», в пользовательском интерфейсе планировщика заданий) из командной строки SCHTASKS.EXE, потому что у него просто не было опции ...
Я решил затем использовать COM в C++ (#import <taskschd.dll> raw_interfaces_only
), чтобы добраться до планировщика заданий и настроить WorkFolder, используя API, после установки задачи с использованием SCHTASKS.EXE, который отлично работал с этой деталью. Мне удалось добраться до задачи и прочитать ее значения после правильной установки задачи, но когда я выполнил метод put_WorkingDirectory
с текущим значением, которое действительно не сработало, но значение не было сохранено в задаче.
У кого-нибудь есть ключ, почему я не мог туда добраться? Это часть кода, который я использовал для доступа к ExecAction, и установил значение успешно. Помните, что это выполняется в пользовательском действии Wix, поэтому некоторые вызовы методов - это Wix.
Этот код фактически работает, и в журнале отображается правильный путь, который я намереваюсь установить, но задача не изменяется. Что я делаю не так?
HRESULT UpdateWorkingDirectory(TaskScheduler::ITaskFolderPtr rootFolder, BSTR taskName, BSTR installFolder)
{
HRESULT hr = S_OK;
TaskScheduler::IRegisteredTaskCollectionPtr taskCollection;
LONG numTasks = 0;
TaskScheduler::IRegisteredTaskPtr thisTask;
TaskScheduler::ITaskDefinitionPtr definition;
TaskScheduler::IActionCollectionPtr actions;
TaskScheduler::IActionPtr action;
TaskScheduler::IExecActionPtr execAction;
long actionCount;
hr = rootFolder->GetTasks(NULL, &taskCollection);
ExitOnFailure(hr, "Cannot get task collection pointer");
hr = taskCollection->get_Count(&numTasks);
ExitOnFailure(hr, "Cannot get task collection item count");
for (LONG taskIdx = 0; taskIdx < numTasks; taskIdx++) {
TaskScheduler::IRegisteredTaskPtr registeredTask;
bstr_t taskIdxName;
hr = taskCollection->get_Item(variant_t(taskIdx + 1), ®isteredTask);
ExitOnFailure(hr, "Cannot get task item %d", taskIdx + 1);
hr = registeredTask->get_Name(&taskIdxName.GetBSTR());
ExitOnFailure(hr, "Cannot get task name");
WcaLog(LOGMSG_STANDARD, " registered task name = %s", (LPCSTR)taskIdxName);
if (strcmp(bstr_t(taskName), taskIdxName) == 0) {
thisTask = registeredTask;
break;
}
}
if (thisTask == NULL) {
hr = E_FAIL;
ExitOnFailure(hr, "task {%S} not found", taskName);
}
hr = thisTask->get_Definition(&definition);
ExitOnFailure(hr, "error getting task definition for {%S}", taskName);
hr = definition->get_Actions(&actions);
ExitOnFailure(hr, "error getting actions for {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " got actions from %S", taskName);
hr = actions->get_Count(&actionCount);
ExitOnFailure(hr, "error getting action count for {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " got count = %d from {%S}", actionCount, taskName);
if (actionCount > 0) {
bstr_t actionId;
bstr_t arguments;
bstr_t path;
hr = actions->get_Item(1, &action);
ExitOnFailure(hr, "error getting action[1] for {%S}", taskName);
hr = action->QueryInterface(&execAction);
ExitOnFailure(hr, "error getting ExecAction for {%S}", taskName);
hr = execAction->get_Id(&actionId.GetBSTR());
ExitOnFailure(hr, "error getting Exec Action id for first exec action of {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " first Exec Action Id is %s", (LPCSTR)actionId);
hr = execAction->get_Arguments(&arguments.GetBSTR());
ExitOnFailure(hr, "error getting Exec Action arguments for first exec action of {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " first Exec Action arguments are %s", (LPCSTR)arguments);
hr = execAction->get_Path(&path.GetBSTR());
ExitOnFailure(hr, "error getting Exec Action path for first exec action of {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " first Exec Action path is %s", (LPCSTR)path);
hr = execAction->put_WorkingDirectory(installFolder);
ExitOnFailure(hr, "error putting working directory for {%S}", taskName);
WcaLog(LOGMSG_STANDARD, " successful put working directory to %S", installFolder);
}
LExit:
return hr;
}
ПРИМЕЧАНИЕ: Все C++ образцы, которые я нашел используется простой интерфейс указателей вместо смарт-указатели, я предпочел смарт-указатели, чтобы избежать заботиться об освобождении от себя
Это для TaskScheduler 1.0, и я хочу установить его в версии 2.0. Новая версия имеет более сложную иерархию объектов, и на этом уровне у нее нет метода SetWorkingDirectory. В любом случае, спасибо –