如何从32位Powershell实例访问64位注册表?

Ric*_*erg 16 registry powershell 64-bit

如果您启动32位Powershell实例(%SystemRoot%\ syswow64\WindowsPowerShell\v1.0\powershell.exe),则注册表提供程序只能看到注册表的有限32位部分.

**32-bit console**
PS> (dir HKLM:\SOFTWARE | measure).count - (dir HKLM:\SOFTWARE\wow6432node | measure).count

0

**64-bit console**
PS> (dir HKLM:\SOFTWARE | measure).count - (dir HKLM:\SOFTWARE\wow6432node | measure).count

-5
Run Code Online (Sandbox Code Playgroud)

有没有办法强制提供程序进入64位模式?我可以下载到[Microsoft.Win32] .Net API,或者WMI,但我不愿意.我正在使用Powershell v2 CTP3,如果它扩大了可能性.

小智 23

使用.NET API,您可以读取64位值,如下所示:

$key = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Registry64)
$subKey =  $key.OpenSubKey("SOFTWARE\Microsoft\.NETFramework")
$root = $subKey.GetValue("InstallRoot")
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仅适用于 .NET 4.0+。 (2认同)
  • 主要的缺点是你不能再利用 `Get-Item` 或 `Get-ChildItem`,但至少它可以正常工作。 (2认同)

Mil*_*ian 8

当Powershell作为32位进程运行时,我不知道将其"切换"到64位模式的机制.64位系统中虚拟化支持的全部要点是让32位进程相信它们生活在32位操作系统中...

但是,我说我过去使用了以下技术,它对我来说非常好用(以下代码在带有Powershell v1的Vista SP1 x64上进行了测试).该技术依赖于.NET的"任何CPU"可执行文件即使在从32位进程调用时也将作为64位进程运行的事实.我们将要执行的步骤:

  1. 编译一个简短的C#程序,它将启动powershell(即一个非常简单的"fork"实现:-))
  2. 运行已编译的C#程序
  3. 编译好的C#程序将启动Powershell,但由于它是"任何CPU",它将作为64位进程运行,因此它将启动64位Powershell(注意,因为这只是一个概念验证,我希望PowerShell在你的'路径')
  4. 新的64位Powershell将运行我们选择的命令行开关

这是上面的操作截图(注意过程的位置): 进程树http://img3.imageshack.us/img3/3248/powershellfork.png

以下程序要求列出的所有文件都驻留在同一目录中.我建议创建一个测试目录,例如C:\ Temp\PowershellTest,并存储所有文件).

该程序的入口点将是一个简单的命令行:

# file "test.ps1"
$basePath = Split-Path -resolve $myInvocation.MyCommand.Path
$exe = Join-Path $basePath test.exe
&"$env:SystemRoot\Microsoft.NET\Framework\v3.5\csc.exe" /nologo /target:exe /out:$exe (Join-Path $basePath test.cs)
&$exe (Join-Path $basePath visibility.ps1)
Run Code Online (Sandbox Code Playgroud)

它运行csc(32位,但无关紧要:-))然后运行csc编译器的结果,传递一个参数,(完整路径)visibility.ps1(这是我们想要在64位Powershell中运行的命令行开关).

C#代码也非常简单:

// file "test.cs"
using System.Diagnostics;
static class Program {
    static int Main(string[] args) {
        ProcessStartInfo i = new ProcessStartInfo("powershell", args[0]);
        i.UseShellExecute = false;
        using(Process p = Process.Start(i)) {
            p.WaitForExit();
            return p.ExitCode;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,你的"可见性"脚本:

# file "visibility.ps1"
(dir HKLM:\SOFTWARE).count - (dir HKLM:\SOFTWARE\wow6432node).count
Run Code Online (Sandbox Code Playgroud)

从32位Powershell运行入口脚本现在可以产生所需的结果(只是为了表明我没有作弊我首先直接运行可见性脚本,然后使用我们的fork技术):

程序运行http://img3.imageshack.us/img3/2766/powershellrunc.png


ggz*_*ggz 7

如果环境变量 PROCESSOR_ARCHITEW6432 存在并且值为 AMD64,那么您正在 64 位计算机上运行 32 位。您必须在虚拟 64 位路径 %windir%\sysnative 中运行 powershell。

if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
    write-warning "changing from 32bit to 64bit PowerShell..."
    $powershell=$PSHOME.tolower().replace("syswow64","sysnative").replace("system32","sysnative")

    if ($myInvocation.Line) {
        &"$powershell\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
    } else {
        &"$powershell\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args
    }

    exit $lastexitcode
}
Run Code Online (Sandbox Code Playgroud)


Sta*_*ing 6

我相信内置的cmdlet Start-Job将允许您从32位实例检查64位注册表.

如果没有,Invoke-Command用于循环回本地机器.64位计算机将具有两个端点(64位和32位),64位端点将是默认端点.

创建注册表值并确保它位于64位路径而不是32位的示例.

Invoke-Command -scriptblock {
    New-ItemProperty -Path HKLM:\SOFTWARE\Acme 
                     -Name NameofNewReg 
                     -PropertyType String -Value "1"
    } -computername .
Run Code Online (Sandbox Code Playgroud)