在x86上下文中运行时,PowerShell返回已安装软件的错误结果

时间:2018-12-08 21:22:58

标签: powershell

我编写了以下脚本来检查应用程序名称并回显一些属性(如果已安装):

$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上下文中运行时返回准确的结果?

2 个答案:

答案 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