How to access the 64-bit registry from a 32-bit Powershell instance?

后端 未结 8 1201
北荒
北荒 2020-12-06 09:54

If you launch a 32-bit instance of Powershell (%SystemRoot%\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe), then the registry provider only sees the limited 32-bit part

8条回答
  •  萌比男神i
    2020-12-06 10:34

    To extend Milan Gardian's answer, use this function for small code blocks:

    function RunAs-64Bit ([ScriptBlock]$scriptblock)
    {
        [string]$code = '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; } } }'
        [string]$exeName = $env:temp + '\' + [System.IO.Path]::GetRandomFileName() + '.exe';
        $params = New-Object 'System.CodeDom.Compiler.CompilerParameters'; 
        @('mscorlib.dll',  'System.dll', ([System.Reflection.Assembly]::GetAssembly([PSObject]).Location)) | %{ $params.ReferencedAssemblies.Add( $_ ) } | Out-Null
        $params.GenerateExecutable      = $true
        $params.GenerateInMemory        = $false;
        $params.CompilerOptions         = '/optimize';
        $params.OutputAssembly          = $exeName;
        $params.TreatWarningsAsErrors   = $false;
        $params.WarningLevel            = 4;
    
        $csprovider = New-Object 'Microsoft.CSharp.CSharpCodeProvider'; #disposable
        try {
            $compileResults = $csprovider.CompileAssemblyFromSource($params, $code)
            $errors = $compileResults.Errors | ?{ -not $_.IsWarning }
            if ($errors.Count -gt 0) 
            {
                Write-Host -f red 'Compiler errors are found.'
                foreach ($output in $compileResults.Output) { Write-Host -$output }
                foreach ($err in $errors) { Write-Host -f red $('Compile Error: ' + $err); }            
            }
            else 
            {
                $compileResults.Errors | %{ Abr-Write-UtilLog 'Util Get assembly from code' $('Compile Warning: ' + $_); }            
                $assembly = $compileResults.CompiledAssembly
                $commandParam = '-encodedCommand  ' + [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($scriptblock));
                &$exeName $commandParam
            }
            Remove-Item -force $exeName -ErrorAction 'SilentlyContinue';
        } finally{
            $csprovider.Dispose();
            Remove-Variable 'csprovider';
        }
    }
    

    Now use this function to run any scriptblock (as long as it is not too big) in 64-bit mode when 64-bit mode is available

提交回复
热议问题