通过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
相关产品推荐
相关产品推荐

