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

如何在全版本Windows10中用PowerShell无DLL调用IUpdateInstaller4.Commit?

兼容全Windows 10版本的IUpdateInstaller4.Commit调用方案

问题核心

Windows 10 20H2及以上版本的wuapi.dll类型库已内置IUpdateInstaller4接口,可直接调用Commit方法;但旧版本(如1909)的类型库未更新,无法直接识别该接口,却必须调用Commit才能避免更新回滚或系统异常状态。

解决方案:基于COM原生机制的动态调用

核心思路是利用COM的QueryInterface机制,将已创建的UpdateInstaller COM对象转换为自定义定义的IUpdateInstaller4接口,无需额外依赖互操作DLL即可实现全版本兼容。

完整PowerShell实现代码

# 定义COM接口与兼容调用工具类
$Source = @"
using System;
using System.Runtime.InteropServices;

namespace WinUpdateUtils
{
    [ComImport]
    [Guid("EF8208EA-2304-492D-9109-23813B0958E1")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IUpdateInstaller4
    {
        int Commit(uint dwFlags);
    }

    public static class InstallerExtensions
    {
        public static int CommitUpdate(dynamic installer, uint flags)
        {
            var installer4 = installer as IUpdateInstaller4;
            if (installer4 == null)
            {
                // 旧系统下手动调用COM QueryInterface获取接口
                IntPtr ptr = IntPtr.Zero;
                Guid iid = typeof(IUpdateInstaller4).GUID;
                int hr = Marshal.QueryInterface(Marshal.GetIUnknownForObject(installer), ref iid, out ptr);
                if (hr != 0) throw new System.ComponentModel.Win32Exception(hr);
                
                installer4 = Marshal.GetObjectForIUnknown(ptr) as IUpdateInstaller4;
                Marshal.Release(ptr);
            }
            return installer4.Commit(flags);
        }
    }
}
"@

Add-Type -TypeDefinition $Source

# 原有更新安装逻辑(保留你的业务代码)
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$Searcher.ServiceID = $UpdateServiceID
$Results = $Searcher.Search($UpdatesSearchString)
$Results.Updates | ForEach-Object {if($_.EulaAccepted -eq $false){$_.AcceptEula()}}
$UpdateList = $Results.Updates
$Updates = New-Object -ComObject Microsoft.Update.UpdateColl
$UpdateList | ForEach-Object {$null = $Updates.Add($_)}
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateInstaller = $UpdateSession.CreateUpdateInstaller()
while($UpdateInstaller.IsBusy) {Start-Sleep 5}
$UpdateInstaller.Updates = $Updates
$InstallResult = $UpdateInstaller.Install()

# 全版本兼容的Commit调用
try {
    $CommitResult = [WinUpdateUtils.InstallerExtensions]::CommitUpdate($UpdateInstaller, 0)
    Write-Host "Commit执行成功,返回值:$CommitResult"
}
catch {
    Write-Error "Commit执行失败:$_"
}

关键实现细节

  • 接口定义修正:将接口标记为InterfaceType.InterfaceIsIUnknown,贴合COM原生接口的调用逻辑,避免类型匹配错误。
  • 双重转换机制:先尝试直接类型转换(新版本系统可用),失败时通过Marshal.QueryInterface手动获取接口指针(旧版本系统兼容)。
  • 命名空间隔离:使用自定义命名空间WinUpdateUtils,避免与系统自带的wuapi类型冲突。

兼容性验证

  • 旧版本Windows 10(如1909):通过手动QueryInterface获取接口,正常执行Commit方法。
  • 新版本Windows 10(20H2+):直接类型转换生效,与原生调用逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:00:58