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

使用WUAPILib安装Windows更新后,更新仍显示为待处理

Windows更新安装后WU界面状态不刷新问题

问题描述

使用自定义的WindowsUpdate类安装Windows更新时,更新已完成下载和安装,但Windows Update(WU)图形界面仍显示未安装状态,点击界面中的“立即安装”按钮后才会刷新显示已安装。调试日志显示更新确实安装成功,询问是否需要使用不同版本的IUpdateInstaller来解决此问题。

自定义WindowsUpdate类代码

class WindowsUpdate:IDownloadProgressChangedCallback,IDownloadCompletedCallback, IInstallationCompletedCallback, IInstallationProgressChangedCallback
{
    public static UpdateSession session = new UpdateSession();
    public UpdateCollection neededUpdates = new UpdateCollection();

    UpdateDownloader downloader = session.CreateUpdateDownloader();
    IUpdateInstaller installer = session.CreateUpdateInstaller();

    public Status currentStatus;
    
    bool enableDebugLogging = false;
    bool enableInstall = true;
    bool enableDownload = true;
    public bool rebootPending = false;

    public List<string> messages = new List<string>();

    public void checkForUpdates()
    {
        debugLog("New WU: Checking for Updates");
        currentStatus = Status.Starting;

        IUpdateSearcher searcher = session.CreateUpdateSearcher();
        ISearchResult results = searcher.Search("IsInstalled=0 AND IsHidden=0");
        debugLog(string.Format("{0} Updates Found", results.Updates.Count));
        downloader.Updates = new UpdateCollection();

        for (int x = 0; x < results.Updates.Count; x++)
        {
            IUpdate u = results.Updates[x];

            if (!u.EulaAccepted)
            {
                u.AcceptEula();
            }

            neededUpdates.Add(u);
            debugLog(string.Format("Update {0} Needed", u.Title));

            if (!u.IsDownloaded)
            {
                debugLog(string.Format("Adding {0} To the WU Download Queue", u.Title), false);
                downloader.Updates.Add(u);
                debugLog(string.Format("Added {0} To the WU Download Queue", u.Title));
            }                
        }

        debugLog("New WU: Search Complete");

        if (downloader.Updates.Count > 0 && enableDownload)
        {
            downloadUpdates();
        }else if(downloader.Updates.Count == 0 && results.Updates.Count > 0)
        {
            debugLog(string.Format("{0} Updates, None pending download", downloader.Updates.Count));

            if (enableInstall)
            {
                debugLog("Queing Install");
            }
            installUpdates();

        }else if(!enableDownload && downloader.Updates.Count > 0)
        {
            debugLog(string.Format("{0} Updates Pending Download, Download Not Enabled", downloader.Updates.Count));
        }else if(neededUpdates.Count == 0)
        {
            currentStatus = Status.Ready;
        }
    }

    void installUpdates()
    {
        debugLog(string.Format("Beginning Installation of {0} Updates", neededUpdates.Count));
        installer.Updates = neededUpdates;

        installer.BeginInstall(this, this, null);
    }

    void downloadUpdates()
    {
        debugLog(string.Format("Beginning Download of {0} Updates", downloader.Updates.Count));
 
        IDownloadJob job = downloader.BeginDownload(this, this, null);
    }

    void IDownloadCompletedCallback.Invoke(IDownloadJob downloadJob, IDownloadCompletedCallbackArgs callbackArgs)
    {
        debugLog("Download Completed Callback");
        foreach (IUpdate u in downloadJob.Updates)
        {
            debugLog(string.Format("{0} Download Completed", u.Title));
        }

        debugLog("All Updates Downloaded, Beginning Install");
        currentStatus = Status.Installing;
        installUpdates();
    }

    void IDownloadProgressChangedCallback.Invoke(IDownloadJob downloadJob, IDownloadProgressChangedCallbackArgs callbackArgs)
    {
        debugLog("Download Status Callback", false);
        currentStatus = Status.Downloading;

        IDownloadProgress progress = callbackArgs.Progress;
        debugLog(string.Format("WUA_DownloadingProgress:{0}|{1}|{2}",
            progress.CurrentUpdateIndex + 1,
            progress.CurrentUpdatePercentComplete,
            progress.PercentComplete), false);
    }

    void IInstallationCompletedCallback.Invoke(IInstallationJob installationJob, IInstallationCompletedCallbackArgs callbackArgs)
    {
        debugLog("Install Complete Callback");
        foreach(IUpdate u in installationJob.Updates)
        {
            debugLog(string.Format("Installation Complete: {0}", u.Title));
        }

        debugLog("Ending WU Install", false);

        IInstallationResult installationResult = installer.EndInstall(installationJob);
        debugLog("After Installer Ended", false);

        if (installationResult.RebootRequired)
        {
            debugLog("Reboot Required, Setting Flag", false);
            rebootPending = true;
        }

        debugLog("Starting Cleanup");
        //installationJob.CleanUp();
        
        debugLog("Ending Cleanup");

        currentStatus = Status.Installed;
    }

    void IInstallationProgressChangedCallback.Invoke(IInstallationJob installationJob, IInstallationProgressChangedCallbackArgs callbackArgs)
    {
        debugLog("Install Progress Callback", false);
        currentStatus = Status.Installing;

        IInstallationProgress p = callbackArgs.Progress;
      
        debugLog(string.Format("Installation Progress: {0} {1} {2}",
            p.CurrentUpdateIndex + 1,
            p.CurrentUpdatePercentComplete,
            p.PercentComplete), false);
    }

    void debugLog(string message, bool showInResults = true)
    {
        if (enableDebugLogging)
        {
            Logging.WriteToTextLog(message);
        }
        if (showInResults)
        {
            messages.Add(message);
        }
    }

    public enum Status
    {
        Starting = 0,
        Ready = 1,
        Downloading = 2,
        Installing = 3,
        Installed = 4
    }

    public WindowsUpdate(bool logging, bool install)
    {
        enableDebugLogging = logging;
        enableInstall = install;
        currentStatus = Status.Starting;
        debugLog("WU Instance Called");
    }

    public string getStatus()
    {
        StringBuilder sb = new StringBuilder();

        foreach(string s in messages)
        {
            sb.Append(s);
            sb.Append(Environment.NewLine);
        }

        return sb.ToString();
    }
}

解决方案

这个问题和IUpdateInstaller版本无关,根源是Windows Update界面依赖的本地更新状态缓存没有被同步更新。手动点击“立即安装”时,WU界面会触发一次重新搜索,从而刷新了状态。

具体修复步骤

在安装完成的回调方法IInstallationCompletedCallback.Invoke末尾,添加强制刷新WU状态缓存的逻辑:

// 刷新WU本地状态缓存,让界面同步最新安装状态
IUpdateSearcher refreshSearcher = session.CreateUpdateSearcher();
try
{
    refreshSearcher.Search("IsInstalled=1"); // 执行搜索触发缓存更新
    debugLog("WU状态缓存已刷新");
}
catch (Exception ex)
{
    debugLog($"刷新缓存失败: {ex.Message}");
}

原理说明

执行UpdateSearcher.Search操作会让Windows Update Agent(WUA)重新查询系统的更新状态,并更新本地缓存。WU界面在读取状态时会优先使用这个缓存,因此刷新后就能显示正确的安装状态,无需手动点击“立即安装”。

备选方案(不推荐)

如果上述方法无效,可以尝试重启Windows Update服务(wuauserv),但这种方式会中断正在进行的WU相关操作,仅作为最后手段:

using (var serviceController = new ServiceController("wuauserv"))
{
    if (serviceController.Status == ServiceControllerStatus.Running)
    {
        serviceController.Stop();
        serviceController.WaitForStatus(ServiceControllerStatus.Stopped);
        serviceController.Start();
        serviceController.WaitForStatus(ServiceControllerStatus.Running);
        debugLog("Windows Update服务已重启");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:09:49