我一直遇到一个InvokeMember,有5个参数错误,但我认为这与我的路径有关。我想在脚本文件夹所在的任何位置的任何计算机上运行此程序。
$ScriptDir = Split-Path $MyInvocation.MyCommand.Path
$ScriptName = $MyInvocation.MyCommand.Name
Function Get-MsiDBVersion {
param (
[string] $fn
)
try {
$FullPath = (Resolve-Path $fn).Path
$windowsInstaller = New-Object -com WindowsInstaller.Installer
$database = $windowsInstaller.GetType().InvokeMember(
"OpenDatabase","InvokeMethod", $Null,
$windowsInstaller, @($Fullpath, 0)
)
$q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
$View = $database.GetType().InvokeMember(
"OpenView", "InvokeMethod", $Null, $database, ($q)
)
$View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null) | Out-Null
$record = $View.GetType().InvokeMember(
"Fetch", "InvokeMethod", $Null, $View, $Null
)
$productVersion = $record.GetType().InvokeMember(
"StringData", "GetProperty", $Null, $record, 1
)
$View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null) | Out-Null
return $productVersion
} catch {
throw "Failed to get MSI file version the error was: {0}." -f $_
}
}
$Program = @{
Installer = "$ScriptDirProgram.exe"
Version = (get-item "$ScriptDirProgram.exe").VersionInfo.FileVersion.TrimEnd()
Arguments = "/SILENT /ALLUSERS /NORESTART"
Exe = "C:Program Files (x86)Program.exe"
ExeVersion = (Get-ChildItem $RegUninstall32 -ErrorAction SilentlyContinue | where name -like "*program*" | Get-ItemProperty ).DisplayVersion
}
-
您需要将
.msi
文件的完整文件系统本机路径传递给WindowsInstaller.Installer
COM对象(Windows Installer COM Automation接口,因为PowerShell的当前目录(位置(通常与其他进程内环境(即.NET和COM使用的非托管进程(不同。-
虽然
$FullPath = (Resolve-Path $fn).Path
是从潜在的相对路径中获取完整路径的尝试,但它并不健壮,因为解析的路径可能基于仅限PowerShell的驱动器(使用New-PSDrive
创建(,而外界对此一无所知。 -
相反,使用
Convert-Path
-LiteralPath $fn
,它返回文件系统本机路径,这是所有环境都知道的。 -
在任何一种情况下,解析都基于当前位置,如
$PWD
/Get-Location
所示。
-
-
不需要通过
.GetType().InvokeMember()
使用反射来调用方法和访问Windows Installer COM对象公开的类型实例的属性-只需像往常一样直接调用/访问即可。(事实上,我无法让你的基于反射的代码工作。(
因此,以下内容应该有效:
Function Get-MsiDBVersion {
param (
[string] $LiteralPath
)
try {
# Convert to a full, native path.
$fullPath = Convert-Path -ErrorAction Stop -LiteralPath $LiteralPath
$windowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$database = $windowsInstaller.Opendatabase($fullPath, 0)
$q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
$view = $database.OpenView($q)
$null = $View.Execute()
$record = $View.Fetch()
$productVersion = $record.StringData(1)
$null = $View.Close()
return $productVersion
}
catch {
throw "Failed to get MSI file version; the error was: {0}." -f $_
}
}
我目前不确定你的目标是什么,但如果你想接收有关MSIpackage的信息,你可以这样做:
Get-CimInstance -query "select * from win32_product"
您的查询不起作用-您的代码:
$q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
语法必须是:
"Select [Property] from [class] where [property] = [propertyvalue]"
例如:
get-ciminstance -query "select version,installState,Description,version,IdentifyingNumber from win32_product where Name = 'Blender'"
输出:
Name : Blender
Version : 2.82.1
InstallState : 5
Caption :
Description : Blender
IdentifyingNumber : {EDFAE2A8-E73B-4CD1-9648-46A7E4434BDA}