我正在使用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 进程正在调用 powershell 的32位版本。
我用这个简单的脚本验证了它,该脚本检查运行的进程是32位还是64位:
powershell [System.Environment]::Is64BitProcess
对于64位进程将返回True
,对于32位进程将返回False
。
手动检查此命令是否有效:
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe [System.Environment]::Is64BitProcess
返回False
,因为它是Powershell的32位版本(是的,由于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
我想念什么?
答案 0 :(得分:0)
您缺少的是Windows透明地从32位进程redirects file system calls到C:\Windows\System32
到C:\Windows\SysWOW64
:)
有一个简单的解决方案-如果32位进程尝试从C:\Windows\sysnative
获取文件系统资源,则Windows将不会重定向到SysWOW64
。
从PowerShell上,figure out基本上很容易受到所有SysWOW64重定向的影响,这很容易:
$IsSysWOW64Process = [Environment]::Is64BitOperatingSystem -and -not [Environment]::Is64BitProcess
但是,在python中,我无法找到执行此操作的方法,因此我怀疑您最好的选择是通过kernel32!IsWow64Process2()
致电ctypes
:
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)