我编写了以下脚本来检查应用程序名称并回显一些属性(如果已安装):
$input = "Microsoft Office Professional"
$appName = "*" + $input + "*"
$responseX64 = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -like $appName} | Select-Object @{Expression={$_.DisplayName + "|" + $_.DisplayVersion +"|x64"}} | Sort-Object -Unique | ft -HideTableHeaders
$responseX86 = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -like $appName} | Select-Object @{Expression={$_.DisplayName + "|" + $_.DisplayVersion +"|x86"}} | Sort-Object -Unique | ft -HideTableHeaders
If (([string]::IsNullOrEmpty($responseX64)) -and ([string]::IsNullOrEmpty($responseX86)))
{
Write-Output "No matches found."
exit
}
else
{
Write-Output $responseX64
Write-Output $responseX86
}
为了完整性,我同时检查了x86和x64卸载注册表项。当我在x64 PowerShell会话中运行它并按预期正确返回我具有Microsoft Office的一个x86安装时,它可以按预期工作:
Microsoft Office Professional Plus 2016 | 16.0.4266.1001 | x86
但是,当我在PowerShell的x86会话中在同一台计算机上运行它(因为它将由我的x86管理代理运行)时,我得到以下返回:
Microsoft Office Professional Plus 2016 | 16.0.4266.1001 | x64
Microsoft Office Professional Plus 2016 | 16.0.4266.1001 | x86
我已经仔细检查了HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall下的注册表项,以确保其中没有Office的x64工件,但没有任何东西。我如何修改此脚本,以便在x86上下文中运行时返回准确的结果?
答案 0 :(得分:3)
您的问题是对于32位进程,以下关键路径指向相同位置,即32位应用程序的注册表视图:>
# To both 64- and 32-bit processes: The registry view for 32-bit applications.
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
# To 32-bit processes: same as above
# To 64-bit processes: the 64-bit view of the registry.
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
换句话说:您的代码在32位进程中运行时,两次执行相同的事情 。
仅使用注册表键路径将不允许32位进程查看64位注册表。
但是,有解决方法:
通过目录$env:WinDir\SysNative
将PowerShell的64位实例作为外部进程调用-参见下文。
直接使用.NET类型,如sources所示。
使用 script块 { ... }
从(32位)PowerShell调用64位PowerShell会自动序列化CLIXML格式的64位实例的输出对象,这将使调用实例自动用合理的保真度反序列化它们 [1] ,这样您的原始过滤命令应该可以工作:
# Works only in a 32-bit process.
& $env:WINDIR\SysNative\WindowsPowerShell\v1.0\powershell.exe {
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
} |
Where-Object {$_.DisplayName -like $appName} |
Select-Object @{Expression={$_.DisplayName + "|" + $_.DisplayVersion +"|x64"}} |
Sort-Object -Unique
要确定您的脚本是否正在32位进程中运行,请使用以下命令:
$is32Bit = ${env:ProgramFiles(x86)} -eq ${env:ProgramFiles} -or
-not ${env:ProgramFiles(x86)}
-or -not ${env:ProgramFiles(x86)}
部分检测运行情况
在纯32位Windows版本上,但是请注意,显然那里不存在64位定义。
[1]除一些众所周知的类型外,输入对象被反序列化为具有静态属性(反映原始对象的属性值)的[PSCustomObject]
实例。
答案 1 :(得分:2)
要添加到@ mklement0的正确答案,也许一个小的测试功能可以帮助确定Windows的位数,而不是当前的PowerShell进程的位数:
function Get-Architecture {
# What architecture does Windows use
$windowsBitness = switch ([Environment]::Is64BitOperatingSystem) { # needs .NET 4
$true { 64; break }
$false { 32; break }
default {
(Get-WmiObject -Class Win32_OperatingSystem).OSArchitecture -replace '\D+', ''
# Or do any of these:
# ((Get-WmiObject -Class Win32_ComputerSystem).SystemType -replace '\D+', '') -replace '86', '32'
# (Get-WmiObject -Class Win32_Processor).AddressWidth # slow...
}
}
# What architecture does this PowerShell process use
$processBitness = [IntPtr]::Size * 8
# Or do any of these:
# $processBitness = ($env:PROCESSOR_ARCHITECTURE -replace '\D+]', '') -replace '86', '32'
# $processBitness = if ([Environment]::Is64BitProcess) { 64 } else { 32 }
# Return the info as object
return New-Object -TypeName PSObject -Property @{
'ProcessArchitecture' = "{0}-bit" -f $processBitness
'WindowsArchitecture' = "{0}-bit" -f $windowsBitness
}
}
可能的回报是:
在64位Windows上的64位PowerShell
ProcessArchitecture WindowsArchitecture
------------------- -------------------
64-bit 64-bit
64位Windows上的32位PowerShell
ProcessArchitecture WindowsArchitecture
------------------- -------------------
32-bit 64-bit
32位Windows上的32位PowerShell
ProcessArchitecture WindowsArchitecture
------------------- -------------------
32-bit 32-bit