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

如何用C++调用Windows API枚举Windows任务计划程序所有任务?

用C++遍历Windows任务计划程序的所有任务

要实现类似PowerShell Get-ScheduledTask 的效果,核心是递归遍历任务计划程序的所有文件夹——因为任务是按层级文件夹组织的,根目录为\,每个文件夹下可能包含子文件夹和任务。以下是完整的实现代码:

#define _WIN32_DCOM
#include <windows.h>
#include <iostream>
#include <taskschd.h>
#include <comdef.h>

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

// 递归遍历任务文件夹及其子文件夹中的所有任务
void TraverseTaskFolder(ITaskFolder* pFolder)
{
    if (!pFolder) return;

    // 获取当前文件夹下的所有任务
    ITaskCollection* pTasks = nullptr;
    HRESULT hr = pFolder->GetTasks(TASK_ENUM_HIDDEN, &pTasks);
    if (SUCCEEDED(hr) && pTasks)
    {
        LONG taskCount = 0;
        pTasks->get_Count(&taskCount);

        for (LONG i = 0; i < taskCount; ++i)
        {
            IRunningTask* pRunningTask = nullptr;
            hr = pTasks->get_Item(_variant_t(i + 1), &pRunningTask);
            if (SUCCEEDED(hr) && pRunningTask)
            {
                ITaskDefinition* pTaskDef = nullptr;
                hr = pRunningTask->get_Definition(&pTaskDef);
                if (SUCCEEDED(hr) && pTaskDef)
                {
                    IRegistrationInfo* pRegInfo = nullptr;
                    hr = pTaskDef->get_RegistrationInfo(&pRegInfo);
                    if (SUCCEEDED(hr) && pRegInfo)
                    {
                        BSTR taskName = nullptr;
                        hr = pRegInfo->get_Description(&taskName);
                        if (FAILED(hr))
                        {
                            // 如果没有描述,获取任务名称
                            pRunningTask->get_Name(&taskName);
                        }

                        // 获取任务状态
                        TASK_STATE taskState = TASK_STATE_UNKNOWN;
                        pRunningTask->get_State(&taskState);

                        // 输出任务信息
                        std::wcout << L"任务名称: " << taskName << L" | 状态: ";
                        switch (taskState)
                        {
                        case TASK_STATE_DISABLED: std::wcout << L"已禁用"; break;
                        case TASK_STATE_QUEUED: std::wcout << L"已排队"; break;
                        case TASK_STATE_READY: std::wcout << L"就绪"; break;
                        case TASK_STATE_RUNNING: std::wcout << L"运行中"; break;
                        default: std::wcout << L"未知"; break;
                        }
                        std::wcout << std::endl;

                        SysFreeString(taskName);
                        pRegInfo->Release();
                    }
                    pTaskDef->Release();
                }
                pRunningTask->Release();
            }
        }
        pTasks->Release();
    }

    // 获取当前文件夹下的所有子文件夹,递归遍历
    IFolderCollection* pFolders = nullptr;
    hr = pFolder->GetFolders(0, &pFolders);
    if (SUCCEEDED(hr) && pFolders)
    {
        LONG folderCount = 0;
        pFolders->get_Count(&folderCount);

        for (LONG i = 0; i < folderCount; ++i)
        {
            ITaskFolder* pSubFolder = nullptr;
            hr = pFolders->get_Item(_variant_t(i + 1), &pSubFolder);
            if (SUCCEEDED(hr) && pSubFolder)
            {
                TraverseTaskFolder(pSubFolder);
                pSubFolder->Release();
            }
        }
        pFolders->Release();
    }
}

int main()
{
    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    if (FAILED(hr))
    {
        std::cout << "COM初始化失败,错误码: " << hr << std::endl;
        return 1;
    }

    // 设置COM安全级别
    hr = CoInitializeSecurity(
        nullptr,
        -1,
        nullptr,
        nullptr,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        nullptr,
        0,
        nullptr);
    if (FAILED(hr))
    {
        std::cout << "设置COM安全级别失败,错误码: " << hr << std::endl;
        CoUninitialize();
        return 1;
    }

    ITaskService* pTaskService = nullptr;
    hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pTaskService);
    if (FAILED(hr))
    {
        std::cout << "创建TaskScheduler实例失败,错误码: " << hr << std::endl;
        CoUninitialize();
        return 1;
    }

    // 连接到本地任务计划服务
    hr = pTaskService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if (FAILED(hr))
    {
        std::cout << "连接任务计划服务失败,错误码: " << hr << std::endl;
        pTaskService->Release();
        CoUninitialize();
        return 1;
    }

    // 获取根任务文件夹
    ITaskFolder* pRootFolder = nullptr;
    hr = pTaskService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
    if (SUCCEEDED(hr) && pRootFolder)
    {
        std::wcout << L"开始遍历所有任务:" << std::endl << std::endl;
        TraverseTaskFolder(pRootFolder);
        pRootFolder->Release();
    }
    else
    {
        std::cout << "获取根文件夹失败,错误码: " << hr << std::endl;
    }

    pTaskService->Release();
    CoUninitialize();

    return 0;
}

关键说明

  1. 递归遍历逻辑:从根文件夹\开始,先枚举当前文件夹的所有任务,再枚举子文件夹并递归处理,确保不会遗漏任何层级的任务。
  2. COM对象管理:所有COM接口使用后必须调用Release()释放,避免内存泄漏。
  3. 任务信息获取:通过IRunningTask接口获取任务名称、状态,IRegistrationInfo获取任务描述(如果存在)。
  4. 权限注意:部分系统任务需要管理员权限才能访问,建议以管理员身份运行程序以获取完整的任务列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:23:36