如何用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; }
关键说明
- 递归遍历逻辑:从根文件夹
\开始,先枚举当前文件夹的所有任务,再枚举子文件夹并递归处理,确保不会遗漏任何层级的任务。 - COM对象管理:所有COM接口使用后必须调用
Release()释放,避免内存泄漏。 - 任务信息获取:通过
IRunningTask接口获取任务名称、状态,IRegistrationInfo获取任务描述(如果存在)。 - 权限注意:部分系统任务需要管理员权限才能访问,建议以管理员身份运行程序以获取完整的任务列表。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

