C++任务调度错误:未完成帐户名称和安全ID之间的Map

sirbozc5  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(81)

我正在尝试在Windows 7上使用C++编写一个Windows触发器任务。
我是this microsoft tutorial
但我在保存任务到根文件夹面临的问题.这里:

//  ------------------------------------------------------
    //  Save the task in the root folder.
    IRegisteredTask *pRegisteredTask = NULL;

    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t( wszTaskName ),
            pTask,
            TASK_CREATE_OR_UPDATE, 
            _variant_t(L"Builtin\\Administrators"), 
            _variant_t(), 
            TASK_LOGON_GROUP,
            _variant_t(L""),
            &pRegisteredTask);

字符串
hr出现错误的地方:* 没有在帐户名称和安全ID之间进行Map *
我也试过用_variant_t(L"S-1-5-32-544")替换_variant_t(L"Builtin\\Administrators"),以解决语言硬编码问题,仍然没有运气。
我怎么才能让它工作?

6pp0gazn

6pp0gazn1#

Windows启动时创建任务队列任务的解决方案

(with管理员权限,适用于Windows 7,8等。请注意,这不会在Windows启动时显示UAC弹出窗口“您确定要使用管理员权限运行此软件吗?",这就是为什么任务验证方法在这种情况下比旧的HKEY_REQ_MACHINE...\CurrentVersion\Run解决方案更有趣)
this tutorial中需要更新一些东西才能使其工作:

  • _variant_t(L"S-1-5-32-544")而不是_variant_t(L"Builtin\\Administrators")
  • _CRT_SECURE_NO_WARNINGS
  • 在VC++中,项目属性>配置属性>链接器>清单文件> UAC执行级别> requireAdministrator
  • 删除现在已经过时的日期界限!
  • 用一个硬编码的域\xm替换hr = pLogonTrigger->put_UserId(_bstr_t(L"DOMAIN\\UserName"));,或者用一些Domain\Username detection code(我不能让它工作),或者只是注解这一行,它对我有用!
  • TASK_RUNLEVEL_HIGHEST添加一些代码
  • 添加一些代码来启用任务**,即使从笔记本电脑上运行电池**(默认情况下将是“不运行任务,如果电池”!),并添加一些代码来防止.exe在一段时间后被杀死(By default, a task will be stopped 72 hours after it starts to run)等。

然后你会得到著名的:
成功!任务注册成功!
呼!经过每天几个小时的编辑,现在是一个完整的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;
}

字符串

pxq42qpu

pxq42qpu2#

我怀疑你的演示代码是XP时代的,还没有更新到符合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调用很可能会失败,所以让这个失败通过。

相关问题