Ошибка расписания задач входа в систему C++: не было выполнено сопоставление между именами учетных записей и идентификаторами безопасности
Я пытаюсь написать задачу триггера входа в систему windows с помощью C++ в Windows 7.
но я сталкиваюсь с проблемой сохранения задачи в корневую папку. Здесь:
// ------------------------------------------------------
// Save the task in the root folder.
IRegisteredTask *pRegisteredTask = NULL;
hr = pRootFolder->RegisterTaskDefinition(
_bstr_t( wszTaskName ),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(L"BuiltinAdministrators"),
_variant_t(),
TASK_LOGON_GROUP,
_variant_t(L""),
&pRegisteredTask);
здесь hr
получаю ошибку : сопоставление имен учетных записей и идентификаторы безопасности было сделано
Я также попытался заменить _variant_t(L"BuiltinAdministrators")
С _variant_t(L"S-1-5-32-544")
чтобы обнулить язык проблема с кодированием, все еще не повезло.
как я могу заставить его работать?
2 ответов
Я подозреваю, что у вас есть демо-код XP-era, и он не был обновлен в соответствии с правилами Vista/Win7.
я обновил образец, чтобы установить настройки LUA после установки триггера входа в систему, и, похоже, работает:
hr = pLogonTrigger->put_UserId(_bstr_t(L"DOMAIN\username"));
if (FAILED(hr))
{
printf("\nCannot add user ID to logon trigger: %x", hr);
CoUninitialize();
return 1;
}
//*** NEW**** Set the LUA settings
CComPtr<IPrincipal> pPrincipal;
hr = pTask->get_Principal(&pPrincipal);
if (SUCCEEDED(hr))
{
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_LUA);
}
if (SUCCEEDED(hr))
{
hr = pPrincipal->put_GroupId(_bstr_t(L"Builtin\Administrators"));
}
if (FAILED(hr))
{
printf("\nCannot set runlevel/groupid: %x", hr);
CoUninitialize();
return 1;
}
Если вам нужно запустить его на XP, то вполне вероятно, что get_Principal
вызов завершится неудачей,так что пусть этот сбой.
окончательное решение для создания задачи TaskScheduler при запуске Windows
(С правами администратора, работающими для Windows 7, 8 и т. д. Обратите внимание, что это не отобразит всплывающее окно UAC при запуске Windows "вы уверены, что запустите это программное обеспечение с правами администратора?", вот почему метод TaskScheduler более интересен в этом случае, чем старый добрый HKEY_LOCAL_MACHINE\...\CurrentVersion равное\решение)
есть несколько вещей, чтобы обновить в этот учебник чтобы заставить его работать:
-
_variant_t(L"S-1-5-32-544")
вместо_variant_t(L"Builtin\Administrators")
- _CRT_SECURE_NO_WARNINGS
- в VC++ свойства проекта > свойства конфигурации > Компоновщик > файл манифеста > уровень выполнения UAC > requireAdministrator
- удалите границы даты, которые теперь устарели !
- заменить
hr = pLogonTrigger->put_UserId(_bstr_t(L"DOMAIN\UserName"));
либо жестко закодированным доменом\Username, либо некоторыми Домен\Имя Пользователя код обнаружения (я не мог заставить его работать), или просто закомментируйте эту строку, это сработало для меня! - добавить код
TASK_RUNLEVEL_HIGHEST
- добавьте код, чтобы включить задачу даже если работает от ноутбука на батареи (по умолчанию будет "не запускать задачу, если на батарейках"!), и некоторый код для предотвращения .exe быть убитым через некоторое время (по умолчанию задача будет остановлена через 72 часа после запуска), так далее.
тогда вы получите знаменитый:
успехов! Задача успешно зарегистрирована.
Фух! После нескольких часов в день и некоторых правок, теперь здесь работает полный main.cpp
:
#define SECURITY_WIN32
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <comdef.h>
#include <Security.h>
#include <taskschd.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")
using namespace std;
#define TASKNAME L"Logon Trigger Test Task"
int __cdecl wmain()
{
// Get the windows directory and set the path to notepad.exe.
wstring wstrExecutablePath = _wgetenv(L"WINDIR");
wstrExecutablePath += L"\SYSTEM32\NOTEPAD.EXE";
// Initialize COM
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) return 1;
// Set general COM security levels.
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
if (FAILED(hr)) goto cleanup0;
// Create an instance of the Task Service.
ITaskService *pService = NULL;
hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr)) goto cleanup0;
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr)) goto cleanup1;
// Get the pointer to the root task folder. This folder will hold the new task that is registered.
ITaskFolder *pRootFolder = NULL;
hr = pService->GetFolder(_bstr_t(L"\"), &pRootFolder);
if (FAILED(hr)) goto cleanup1;
// If the same task exists, remove it.
pRootFolder->DeleteTask(_bstr_t(TASKNAME), 0);
// Create the task builder object to create the task.
ITaskDefinition *pTask = NULL;
hr = pService->NewTask(0, &pTask);
// COM clean up. Pointer is no longer used.
pService->Release();
if (FAILED(hr)) { pRootFolder->Release(); CoUninitialize(); return 1; }
// Get the registration info for setting the identification.
IRegistrationInfo *pRegInfo = NULL;
hr = pTask->get_RegistrationInfo(&pRegInfo);
if (FAILED(hr)) goto cleanup2;
hr = pRegInfo->put_Author(L"Author Name");
pRegInfo->Release();
if (FAILED(hr)) goto cleanup2;
// Create the settings for the task
ITaskSettings *pSettings = NULL;
hr = pTask->get_Settings(&pSettings);
if (FAILED(hr)) goto cleanup2;
// Set setting values for the task.
pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
pSettings->put_ExecutionTimeLimit(_bstr_t(L"PT0S"));
pSettings->Release();
if (FAILED(hr)) goto cleanup2;
// Get the trigger collection to insert the logon trigger.
ITriggerCollection *pTriggerCollection = NULL;
hr = pTask->get_Triggers(&pTriggerCollection);
if (FAILED(hr)) goto cleanup2;
// Add the logon trigger to the task.
ITrigger *pTrigger = NULL;
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
pTriggerCollection->Release();
if (FAILED(hr)) goto cleanup2;
ILogonTrigger *pLogonTrigger = NULL;
hr = pTrigger->QueryInterface(IID_ILogonTrigger, (void**)&pLogonTrigger);
pTrigger->Release();
if (FAILED(hr)) goto cleanup2;
hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
if (FAILED(hr)) goto cleanup2;
// Define the user. The task will execute when the user logs on. The specified user must be a user on this computer.
//hr = pLogonTrigger->put_UserId(_bstr_t(L"DOMAIN\UserName"));
pLogonTrigger->Release();
if (FAILED(hr)) goto cleanup2;
IPrincipal *pPrincipal;
hr = pTask->get_Principal(&pPrincipal);
if (FAILED(hr)) goto cleanup2;
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
if (FAILED(hr)) goto cleanup2;
// Add an Action to the task. This task will execute .exe
IActionCollection *pActionCollection = NULL;
// Get the task action collection pointer.
hr = pTask->get_Actions(&pActionCollection);
if (FAILED(hr)) goto cleanup2;
// Create the action, specifying that it is an executable action.
IAction *pAction = NULL;
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
pActionCollection->Release();
if (FAILED(hr)) goto cleanup2;
// QI for the executable task pointer.
IExecAction *pExecAction = NULL;
hr = pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction);
pAction->Release();
if (FAILED(hr)) goto cleanup2;
// Set the path of the executable.
hr = pExecAction->put_Path(_bstr_t(wstrExecutablePath.c_str()));
pExecAction->Release();
if (FAILED(hr)) goto cleanup2;
// Save the task in the root folder.
IRegisteredTask *pRegisteredTask = NULL;
hr = pRootFolder->RegisterTaskDefinition(_bstr_t(TASKNAME), pTask, TASK_CREATE_OR_UPDATE, _variant_t(L"S-1-5-32-544"), _variant_t(), TASK_LOGON_GROUP, _variant_t(L""), &pRegisteredTask); //_variant_t(L"Builtin\Administrators"),
if (FAILED(hr)) goto cleanup2;
printf("Success! Task successfully registered.");
getchar();
pRootFolder->Release();
pTask->Release();
pRegisteredTask->Release();
CoUninitialize();
return 0;
cleanup0:
CoUninitialize();
return 1;
cleanup1:
pService->Release();
CoUninitialize();
return 1;
cleanup2:
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}