【问题标题】:Running 64bit powershell from 32bit python从 32 位 python 运行 64 位 powershell
【发布时间】:2019-12-17 22:29:15
【问题描述】:

我正在使用 32 位 python 的 Windows Server 2012 R2 standard 机器上运行。
我正在尝试为 64 位系统运行 powershell 脚本,以检查注册表中是否存在密钥:

$path = "Registry::HKLM\Software\<folder>"
if (!(Test-Path $path)) 
   {
       write "$path does not exist!"
   }

通过 powershell 运行时,脚本运行良好。
当我从 python 运行它时,它找不到密钥:

from gevent.subprocess import call
call("powershell <script.ps1>, shell=True")

经过一番研究,发现32位的python进程调用的是32位版本的powershell
我用这个简单的脚本验证了它,它检查正在运行的进程是 32 位还是 64 位:

powershell [System.Environment]::Is64BitProcess

对于 64 位进程将返回 True,对于 32 位进程将返回 False
手动检查此命令是否有效:

C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe [System.Environment]::Is64BitProcess

返回 False,因为这是 32 位版本的 powershell(是的,由于 WOW64 文件夹,相当混乱)。

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe [System.Environment]::Is64BitProcess

返回True。 但运行:

from gevent.subprocess import call
call("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe [System.Environment]::Is64BitProcess", shell=True)

返回False
我错过了什么?

【问题讨论】:

标签: python powershell 32bit-64bit


【解决方案1】:

您缺少的是 Windows 透明地从 32 位进程 redirects file system callsC:\Windows\System32C:\Windows\SysWOW64 :)

对此有一个简单的解决方案 - 如果 32 位进程尝试从 C:\Windows\sysnative 获取文件系统资源,Windows 将不会重定向到 SysWOW64

从 PowerShell 可以很容易地figure out 您的进程是否会受到所有这些 SysWOW64 重定向的影响,基本上:

$IsSysWOW64Process = [Environment]::Is64BitOperatingSystem -and -not [Environment]::Is64BitProcess

然而,在 python 中,我还没有找到可靠的方法来做到这一点,所以我怀疑你最好的选择是通过ctypes 调用kernel32!IsWow64Process2()

from ctypes import windll,c_ushort,byref
import platform

def is_syswow64_process():
    if platform.architecture()[0] != '64bit':
        # 32-bit OS, no syswow64 handling
        return False

    # Ok, 64-bit OS, let's see if the process is 32-bit
    # Obtain process handle to self
    this_process = windll.kernel32.GetCurrentProcess()

    # Declare ref arguments 
    proc_type, platform_type = c_ushort(), c_ushort()

    # Query Windows for the information
    wow64_call = windll.kernel32.IsWow64Process2(this_process, byref(proc_type), byref(platform_type))

    if wow64_call == 0:
        # you'd probably want to call kernel32!GetLastError here
        raise Exception("Problem querying kernel32!IsWow64Process2")

    return proc_type.value == 0

现在您可以在需要时有条件地替换路径:

powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"

if is_syswow64_process():
    powershell = re.sub("(?i)syswow64|system32", "sysnative", powershell)

call("%s .\path\to\script.ps1" % powershell)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 2012-12-03
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    相关资源
    最近更新 更多