如何在全版本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
相关产品推荐
相关产品推荐

