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

如何通过C++获取Windows最后一次成功更新时间

你当前调用PowerShell的方案性能差,核心原因是每次调用都要启动独立的powershell.exe进程,加载整个PowerShell运行时,开销非常大。要实现原生C++获取Windows最后一次成功更新的日期时间,不需要依赖外部程序,直接在进程内调用Windows Update Agent提供的COM接口即可,和你PowerShell脚本访问的是完全相同的数据源,返回结果完全一致,且调用开销只有毫秒级。

实现要点
  • 核心逻辑和原PowerShell方案完全对应:创建Microsoft.Update.AutoUpdate COM对象,读取其Results.LastSearchSuccessDate属性
  • 调用COM接口前需要先初始化COM套间,单线程套间即可满足需求
  • 读取到的LastSearchSuccessDate是OLE DATE类型,可通过系统自带APIVariantTimeToSystemTime转换为SYSTEMTIME结构,再按需格式化为字符串
  • 所有COM接口指针、VARIANT变量用完后需要手动释放,避免资源泄漏
  • 接口调用不需要管理员权限,普通用户权限下即可正常获取数据,和原PowerShell方案的权限要求一致
  • 编译仅需要链接系统默认自带的oleaut32.lib,不需要额外引入第三方依赖
可直接运行的示例代码
#include <windows.h>
#include <comdef.h>
#include <stdio.h>

// 对应COM对象的CLSID和接口IID,无需额外引入头文件即可使用
const CLSID CLSID_AutomaticUpdates = {0x6398794D, 0x3C89, 0x4870, {0xA3, 0x68, 0x83, 0x99, 0x46, 0x7A, 0x96, 0x68}};

int main()
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED(hr)) return 1;

    IDispatch* pAutoUpdate = NULL;
    IDispatch* pResults = NULL;
    VARIANT vResults, vLastSuccessDate;
    SYSTEMTIME st;
    VariantInit(&vResults);
    VariantInit(&vLastSuccessDate);

    do 
    {
        // 创建AutoUpdate COM实例
        hr = CoCreateInstance(CLSID_AutomaticUpdates, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pAutoUpdate);
        if (FAILED(hr)) break;

        // 读取Results属性
        DISPID dispidResults;
        OLECHAR* szResultsProp = L"Results";
        hr = pAutoUpdate->GetIDsOfNames(IID_NULL, &szResultsProp, 1, LOCALE_USER_DEFAULT, &dispidResults);
        if (FAILED(hr)) break;

        DISPPARAMS noArgs = {NULL, NULL, 0, 0};
        hr = pAutoUpdate->Invoke(dispidResults, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &noArgs, &vResults, NULL, NULL);
        if (FAILED(hr) || vResults.vt != VT_DISPATCH) break;
        pResults = vResults.pdispVal;

        // 读取LastSearchSuccessDate属性
        DISPID dispidLastDate;
        OLECHAR* szDateProp = L"LastSearchSuccessDate";
        hr = pResults->GetIDsOfNames(IID_NULL, &szDateProp, 1, LOCALE_USER_DEFAULT, &dispidLastDate);
        if (FAILED(hr)) break;

        hr = pResults->Invoke(dispidLastDate, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &noArgs, &vLastSuccessDate, NULL, NULL);
        if (FAILED(hr) || vLastSuccessDate.vt != VT_DATE) break;

        // 时间格式转换与输出
        if (VariantTimeToSystemTime(vLastSuccessDate.date, &st))
        {
            wchar_t timeBuf[256] = {0};
            swprintf(timeBuf, _countof(timeBuf), L"最后一次成功更新搜索时间: %d-%02d-%02d %02d:%02d:%02d", 
                st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
            wprintf(L"%s\n", timeBuf);
        }
    } while (false);

    // 释放所有资源
    if (pResults) pResults->Release();
    if (pAutoUpdate) pAutoUpdate->Release();
    VariantClear(&vLastSuccessDate);
    VariantClear(&vResults);
    CoUninitialize();

    return FAILED(hr) ? 1 : 0;
}

如果你觉得手写IDispatch调用逻辑繁琐,可以在代码开头加入下面的类型库导入语句,编译器会自动生成对应COM接口的强类型包装,代码可以进一步简化,不需要手动处理DISPID和VARIANT参数解析:

#import "wuapi.tlb" named_guids raw_interfaces_only

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:09:14