You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Win32 API 1.0创建任务不显示于任务计划程序GUI且保存失败

问题描述
  • 运行微软文档中的任务创建示例程序,生成了C:\Windows\Tasks下的.job文件,但任务计划程序GUI中无法看到该任务,怀疑是使用了Task Scheduler 1.0接口导致。
  • 后续在示例基础上添加TASK_FLAG_RUN_ONLY_IF_LOGGED_ON标志,并调用SetAccountInformation设置账户信息,现在保存任务失败,错误信息:(任务XML包含意外节点) : 保存任务失败,错误码 = 0x80041316

附上代码:

void stringError(HRESULT hr) {
    _com_error err(hr);
    LPCTSTR errMsg = err.ErrorMessage();
    fprintf(stderr, "错误信息 (%ls) : ", errMsg);
}

int main()
{
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "初始化COM库失败,错误码 = 0x%x\n", hr);
        return 1;
    }

    ITaskScheduler* pITS = NULL;
    hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&pITS);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "创建任务计划程序实例失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    LPCWSTR pwszTaskName = L"SampleTask";
    ITask* pITask = NULL;
    IPersistFile* pIPersistFile = NULL;

    hr = pITS->NewWorkItem(pwszTaskName, CLSID_CTask, IID_ITask, (IUnknown**)&pITask);
    if (FAILED(hr))
    {
        if (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS))
        {
            fprintf(stderr, "任务已存在,尝试删除...\n");
            hr = pITS->Delete(pwszTaskName);
            if (FAILED(hr))
            {
                stringError(hr);
                fprintf(stderr, "删除现有任务失败,错误码 = 0x%x\n", hr);
                pITS->Release();
                CoUninitialize();
                return 1;
            }

            hr = pITS->NewWorkItem(pwszTaskName, CLSID_CTask, IID_ITask, (IUnknown**)&pITask);
            if (FAILED(hr))
            {
                stringError(hr);
                fprintf(stderr, "删除后创建新任务失败,错误码 = 0x%x\n", hr);
                pITS->Release();
                CoUninitialize();
                return 1;
            }
        }
        else
        {
            stringError(hr);
            fprintf(stderr, "创建新任务失败,错误码 = 0x%x\n", hr);
            pITS->Release();
            CoUninitialize();
            return 1;
        }
    }   

    pITS->Release();

    hr = pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "设置任务标志失败,错误码 = 0x%x\n", hr);
        pITask->Release();
        CoUninitialize();
        return 1;
    }

    hr = pITask->SetAccountInformation(L"", NULL);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "设置账户信息失败,错误码 = 0x%x\n", hr);
        pITask->Release();
        CoUninitialize();
        return 1;
    }

    hr = pITask->QueryInterface(IID_IPersistFile, (void**)&pIPersistFile);
    pITask->Release();
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "查询IPersistFile接口失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    hr = pIPersistFile->Save(NULL, TRUE);
    pIPersistFile->Release();
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "保存任务失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    CoUninitialize();
    printf("任务创建成功。\n");
    return 0;
}
解决方案
  1. 问题根源:你使用的是Task Scheduler 1.0旧接口(CLSID_CTaskScheduler/ITask),该接口生成的是传统.job格式任务,不会在现代任务计划程序GUI中显示;而0x80041316错误是因为新版Windows系统对旧任务的XML格式兼容性限制,导致保存失败。

  2. 解决办法:改用Task Scheduler 2.0接口(Windows Vista及以上系统支持),使用ITaskService、ITaskDefinition等新接口创建任务,生成的任务会正常显示在GUI中,且不会出现XML节点错误。

  3. 修复后的代码示例:

#include <windows.h>
#include <taskschd.h>
#include <comdef.h>
#include <stdio.h>

#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")

void stringError(HRESULT hr) {
    _com_error err(hr);
    LPCTSTR errMsg = err.ErrorMessage();
    fprintf(stderr, "错误信息 (%ls) : ", errMsg);
}

int main()
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "初始化COM库失败,错误码 = 0x%x\n", hr);
        return 1;
    }

    ITaskService* pTaskService = NULL;
    hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pTaskService);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "创建任务计划程序服务实例失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    hr = pTaskService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "连接任务计划程序服务失败,错误码 = 0x%x\n", hr);
        pTaskService->Release();
        CoUninitialize();
        return 1;
    }

    ITaskFolder* pRootFolder = NULL;
    hr = pTaskService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
    pTaskService->Release();
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "获取根任务文件夹失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    // 检查任务是否存在,存在则删除
    VARIANT_BOOL taskExists = VARIANT_FALSE;
    hr = pRootFolder->Exists(_bstr_t(L"SampleTask"), &taskExists);
    if (SUCCEEDED(hr) && taskExists)
    {
        fprintf(stderr, "任务已存在,尝试删除...\n");
        hr = pRootFolder->DeleteTask(_bstr_t(L"SampleTask"), 0);
        if (FAILED(hr))
        {
            stringError(hr);
            fprintf(stderr, "删除现有任务失败,错误码 = 0x%x\n", hr);
            pRootFolder->Release();
            CoUninitialize();
            return 1;
        }
    }

    ITaskDefinition* pTaskDef = NULL;
    hr = pRootFolder->NewTask(0, &pTaskDef);
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "创建任务定义失败,错误码 = 0x%x\n", hr);
        pRootFolder->Release();
        CoUninitialize();
        return 1;
    }

    // 设置任务设置
    ITaskSettings* pSettings = NULL;
    hr = pTaskDef->get_Settings(&pSettings);
    if (SUCCEEDED(hr))
    {
        pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
        pSettings->put_RunOnlyIfLoggedOn(VARIANT_TRUE); // 对应TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
        pSettings->Release();
    }

    // 设置触发器(这里设置为启动时触发,可根据需求修改)
    ITriggerCollection* pTriggerCollection = NULL;
    hr = pTaskDef->get_Triggers(&pTriggerCollection);
    if (SUCCEEDED(hr))
    {
        ITrigger* pTrigger = NULL;
        hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger);
        if (SUCCEEDED(hr))
        {
            pTrigger->Release();
        }
        pTriggerCollection->Release();
    }

    // 设置操作(这里设置为运行notepad.exe,可根据需求修改)
    IActionCollection* pActionCollection = NULL;
    hr = pTaskDef->get_Actions(&pActionCollection);
    if (SUCCEEDED(hr))
    {
        IAction* pAction = NULL;
        hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
        if (SUCCEEDED(hr))
        {
            IExecAction* pExecAction = NULL;
            hr = pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction);
            if (SUCCEEDED(hr))
            {
                pExecAction->put_Path(_bstr_t(L"C:\\Windows\\notepad.exe"));
                pExecAction->Release();
            }
            pAction->Release();
        }
        pActionCollection->Release();
    }

    // 注册任务
    IRegisteredTask* pRegisteredTask = NULL;
    hr = pRootFolder->RegisterTaskDefinition(
        _bstr_t(L"SampleTask"),
        pTaskDef,
        TASK_CREATE_OR_UPDATE,
        _variant_t(), // 当前用户
        _variant_t(),
        TASK_LOGON_INTERACTIVE_TOKEN,
        _variant_t(L""),
        &pRegisteredTask
    );

    pTaskDef->Release();
    pRootFolder->Release();
    if (FAILED(hr))
    {
        stringError(hr);
        fprintf(stderr, "注册任务失败,错误码 = 0x%x\n", hr);
        CoUninitialize();
        return 1;
    }

    printf("任务创建成功,可在任务计划程序GUI中查看。\n");
    pRegisteredTask->Release();
    CoUninitialize();
    return 0;
}

内容的提问来源于stack exchange,提问作者NImIPKZvUc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:14:53