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

查询Windows Installer数据库出错的原因及修复方案咨询

错误原因
  1. MSI文件损坏:C:\Windows\Installer目录下的部分MSI可能因磁盘错误、卸载残留、病毒误删等原因损坏,直接用Windows Installer COM对象打开时会触发异常。而Win32_Product是从系统注册表和Windows Installer服务缓存读取信息,不需要直接打开损坏的MSI,所以能正常运行。
  2. 权限不足:部分MSI文件的权限设置限制了当前用户读取,COM对象调用时权限不够,但Win32_Product运行在系统服务上下文,权限更高,可绕过该限制。
  3. 函数资源释放错误:函数里的资源释放逻辑存在错误,比如用$ProductMsi.GetType().InvokeMember("CloseView"),但CloseView是View对象的方法,不是文件路径对象的方法。这类错误会导致资源泄漏,多次调用后触发COM对象异常。
  4. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:44:51