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

通过Ansible远程执行PowerShell脚本读取MSI的ProductGUID报错

问题

尝试通过Ansible在远程Windows主机上运行PowerShell脚本读取MSI文件的ProductGUID,本地直接运行ps1文件正常,但通过Ansible执行时抛出“Object reference not set to an instance of an object”错误。

Ansible代码

- name: Run PowerShell script to find out Product Code
  ansible.windows.win_powershell:
    script: |
           $windowsInstaller = New-Object -ComObject WindowsInstaller.Installer
           $database = $windowsInstaller.OpenDatabase($msiFilePath, 0)
           $query = 'SELECT Value FROM Property WHERE Property = ''ProductCode'''
           $view = $database.OpenView($query)
           $view.Execute()
           $record = $view.Fetch()

           if ($record) {
                $productGUID = $record.StringData(1)
                echo "Product GUID: $productGUID"
           } else {
                echo "Product GUID not found in the MSI file."
           }

           if ($view) {
                $view.Close()
           }
    parameters:
      msiFilePath: '<Path_to_MSI>'
  register: PS_output
  tags:
    - read_msi

- name: Show PS_output
  debug:
    var: PS_output
  tags:
    - read_msi 

执行错误输出

changed: [mb018-windows] => {
"changed": true,
"debug": [],
"error": [
{
"category_info": {
"activity": "",
"category": "OperationStopped",
"category_id": 14,
"reason": "NullReferenceException",
"target_name": "",
"target_type": ""
},
"error_details": null,
"exception": {
"help_link": null,
"hresult": -2147467261,
"inner_exception": null,
"message": "Object reference not set to an instance of an object.",
"source": "System.Management.Automation",
"type": "System.NullReferenceException"
},
"fully_qualified_error_id": "System.NullReferenceException",
"output": "Object reference not set to an instance of an object.\r\nAt line:2 char:1\r\n+ $database = $windowsInstaller.OpenDatabase($msiFilePath, 0)\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    + CategoryInfo          : OperationStopped: (:) [], NullReferenceException\r\n    + FullyQualifiedErrorId : System.NullReferenceException\r\n \r\n",
"pipeline_iteration_info": [],
"script_stack_trace": "at , : line 2",
"target_object": null
},
{
"category_info": {
"activity": "",
"category": "InvalidOperation",
"category_id": 7,
"reason": "RuntimeException",
"target_name": "",
"target_type": ""
},
"error_details": null,
"exception": {
"help_link": null,
"hresult": -2146233087,
"inner_exception": null,
"message": "You cannot call a method on a null-valued expression.",
"source": "Anonymously Hosted DynamicMethods Assembly",
"type": "System.Management.Automation.RuntimeException"
},
"fully_qualified_error_id": "InvokeMethodOnNull",
"output": "You cannot call a method on a null-valued expression.\r\nAt line:4 char:1\r\n+ $view = $database.OpenView($query)\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException\r\n    + FullyQualifiedErrorId : InvokeMethodOnNull\r\n \r\n",
"pipeline_iteration_info": [],
"script_stack_trace": "at , : line 4",
"target_object": null
}
]
}

解决方法

1. 检查MSI文件路径

  • 确保msiFilePath是远程Windows主机上的绝对路径,比如C:\installers\app.msi,而非本地路径。Ansible在远程主机执行脚本,无法直接访问本地文件。
  • 如果MSI文件在本地,先通过win_copy模块上传到远程主机:
    - name: Copy MSI to remote host
      ansible.windows.win_copy:
        src: /local/path/to/your/file.msi
        dest: C:\remote\path\file.msi
      tags:
        - read_msi
    

2. 验证权限

  • 使用具有本地管理员权限的用户连接远程Windows主机,确保该用户能读取目标MSI文件,且有权限调用Windows Installer COM对象。

3. 优化PowerShell脚本(添加错误处理)

修改脚本增加错误捕获和空对象检查,避免空引用异常,同时正确释放COM资源:

try {
    # 初始化Windows Installer COM对象并捕获错误
    $windowsInstaller = New-Object -ComObject WindowsInstaller.Installer -ErrorAction Stop
    if (-not $windowsInstaller) {
        throw "无法初始化Windows Installer COM对象"
    }

    # 打开MSI数据库并检查是否成功
    $database = $windowsInstaller.OpenDatabase($msiFilePath, 0)
    if (-not $database) {
        throw "无法打开MSI文件: $msiFilePath"
    }

    $query = 'SELECT Value FROM Property WHERE Property = ''ProductCode'''
    $view = $database.OpenView($query)
    $view.Execute()
    $record = $view.Fetch()

    if ($record) {
        $productGUID = $record.StringData(1)
        Write-Output "Product GUID: $productGUID"
    } else {
        Write-Output "MSI文件中未找到ProductGUID"
    }
}
catch {
    Write-Error "执行出错: $_"
}
finally {
    # 关闭视图并释放COM对象
    if ($view) { $view.Close() }
    if ($windowsInstaller) { 
        [System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null
    }
}

4. 检查Windows Installer服务状态

确保远程主机的Windows Installer服务(msiserver)处于运行状态,可通过Ansible任务验证:

- name: Check Windows Installer service status
  ansible.windows.win_service:
    name: msiserver
    state: started
  tags:
    - read_msi

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:07:08