查询Windows Installer数据库出错的原因及修复方案咨询
错误原因
- MSI文件损坏:
C:\Windows\Installer目录下的部分MSI可能因磁盘错误、卸载残留、病毒误删等原因损坏,直接用Windows Installer COM对象打开时会触发异常。而Win32_Product是从系统注册表和Windows Installer服务缓存读取信息,不需要直接打开损坏的MSI,所以能正常运行。 - 权限不足:部分MSI文件的权限设置限制了当前用户读取,COM对象调用时权限不够,但
Win32_Product运行在系统服务上下文,权限更高,可绕过该限制。 - 函数资源释放错误:函数里的资源释放逻辑存在错误,比如用
$ProductMsi.GetType().InvokeMember("CloseView"),但CloseView是View对象的方法,不是文件路径对象的方法。这类错误会导致资源泄漏,多次调用后触发COM对象异常。 - Windows Installer服务异常:个别系统的msiexec服务状态异常,导致COM对象调用失败,但WMI服务仍能正常交互,因此
Win32_Product不受影响。
修复方法
一、修复损坏的MSI或Windows Installer服务
- 重新注册Windows Installer:打开管理员PowerShell执行:
msiexec /unregister msiexec /regserver - 修复对应程序:找到触发错误的程序,重新运行其安装包并选择“修复”选项,系统会重新生成
C:\Windows\Installer中对应的MSI文件。 - 清理无效MSI:如果某个MSI对应已卸载的程序,确认后可直接删除该文件(注意:不要随意删除未知MSI,避免影响已安装程序的修复)。
二、修复函数的资源泄漏问题
将函数中错误的资源释放代码替换为以下内容,且要放在Return $value之前(否则Return后代码不会执行):
# 关闭各个View对象 if ($PCView) { $PCView.GetType().InvokeMember("CloseView", "InvokeMethod", $null, $PCView, $null) } if ($PVView) { $PVView.GetType().InvokeMember("CloseView", "InvokeMethod", $null, $PVView, $null) } if ($PNView) { $PNView.GetType().InvokeMember("CloseView", "InvokeMethod", $null, $PNView, $null) } if ($MFView) { $MFView.GetType().InvokeMember("CloseView", "InvokeMethod", $null, $MFView, $null) } # 关闭数据库 $MSIDatabase.GetType().InvokeMember("Close", "InvokeMethod", $null, $MSIDatabase, $null) # 释放COM对象 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($MSIDatabase) | Out-Null # 清空变量 $WindowsInstaller = $null $MSIDatabase = $null $value = $null $ProductMsi = $null
三、添加容错处理
在处理每个MSI文件时单独加入try-catch,避免单个文件出错导致整个函数终止:
Get-Item "$Path" -Force -ErrorAction Stop | ForEach-Object { try { $ProductMsi = $_.FullName $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer -ErrorAction Stop $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $WindowsInstaller, @($ProductMsi, 0)) # 原有的Switch逻辑和返回代码 # 资源释放代码放在这里 } catch { Write-Warning "处理MSI文件失败: $ProductMsi - $($_.Exception.Message)" continue } }
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

