确定可执行文件(或库)是 32 位还是 64 位(在 Windows 上)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1345632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:03:30  来源:igfitidea点击:

Determine if an executable (or library) is 32 -or 64-bits (on Windows)

pythonwindowsdll64-bitexecutable

提问by pkit

I am trying to find out if a given executable (or library) is compiled for 32-bits or 64-bits from Python. I am running Vista 64-bits and would like to determine if a certain application in a directory is compiled for 32-bits or 64-bits.

我试图找出给定的可执行文件(或库)是否是从 Python 为 32 位或 64 位编译的。我正在运行 Vista 64 位,并想确定目录中的某个应用程序是为 32 位还是 64 位编译的。

Is there a simple way to do this using only the standard Python libraries (currently using 2.5.4)?

是否有一种仅使用标准 Python 库(当前使用 2.5.4)来执行此操作的简单方法?

回答by Martin B

The Windows API for this is GetBinaryType. You can call this from Python using pywin32:

为此,Windows API 是GetBinaryType. 您可以使用pywin32从 Python 调用它:

import win32file
type=GetBinaryType("myfile.exe")
if type==win32file.SCS_32BIT_BINARY:
    print "32 bit"
# And so on

If you want to do this without pywin32, you'll have to read the PE headeryourself. Here's an examplein C#, and here's a quick port to Python:

如果您想在没有 pywin32 的情况下执行此操作,则必须自己阅读PE 标头。这是C# 中的示例,这里是 Python 的快速移植:

import struct

IMAGE_FILE_MACHINE_I386=332
IMAGE_FILE_MACHINE_IA64=512
IMAGE_FILE_MACHINE_AMD64=34404

f=open("c:\windows\explorer.exe", "rb")

s=f.read(2)
if s!="MZ":
    print "Not an EXE file"
else:
    f.seek(60)
    s=f.read(4)
    header_offset=struct.unpack("<L", s)[0]
    f.seek(header_offset+4)
    s=f.read(2)
    machine=struct.unpack("<H", s)[0]

    if machine==IMAGE_FILE_MACHINE_I386:
        print "IA-32 (32-bit x86)"
    elif machine==IMAGE_FILE_MACHINE_IA64:
        print "IA-64 (Itanium)"
    elif machine==IMAGE_FILE_MACHINE_AMD64:
        print "AMD64 (64-bit x86)"
    else:
        print "Unknown architecture"

f.close()

回答by Jason R. Coombs

If you're running Python 2.5 or later on Windows, you could also use the Windows API without pywin32 by using ctypes.

如果您在 Windows 上运行 Python 2.5 或更高版本,您还可以通过使用 ctypes 来使用不带 pywin32 的 Windows API。

from ctypes import windll, POINTER
from ctypes.wintypes import LPWSTR, DWORD, BOOL

SCS_32BIT_BINARY = 0 # A 32-bit Windows-based application
SCS_64BIT_BINARY = 6 # A 64-bit Windows-based application
SCS_DOS_BINARY = 1 # An MS-DOS-based application
SCS_OS216_BINARY = 5 # A 16-bit OS/2-based application
SCS_PIF_BINARY = 3 # A PIF file that executes an MS-DOS-based application
SCS_POSIX_BINARY = 4 # A POSIX-based application
SCS_WOW_BINARY = 2 # A 16-bit Windows-based application

_GetBinaryType = windll.kernel32.GetBinaryTypeW
_GetBinaryType.argtypes = (LPWSTR, POINTER(DWORD))
_GetBinaryType.restype = BOOL

def GetBinaryType(filepath):
    res = DWORD()
    handle_nonzero_success(_GetBinaryType(filepath, res))
    return res

Then use GetBinaryType just like you would with win32file.GetBinaryType.

然后像使用 win32file.GetBinaryType 一样使用 GetBinaryType。

Note, you would have to implement handle_nonzero_success, which basically throws an exception if the return value is 0.

请注意,您必须实现 handle_nonzero_success,如果返回值为 0,它基本上会引发异常。

回答by thesis

I was able to use Martin B's answer successfully in a Python 3.5 program after making this adjustment:

进行此调整后,我能够在 Python 3.5 程序中成功使用 Martin B 的答案:

s=f.read(2).decode(encoding="utf-8", errors="strict")

Originally it worked just fine with my program in Python 2.7, but after making other necessary changes, I discovered I was getting b'MZ', and decoding it appears to fix this.

最初它在我的 Python 2.7 程序中运行得很好,但在进行其他必要的更改后,我发现我得到了 b'MZ',并且解码它似乎可以解决这个问题。

回答by Ross Boylan

  1. Using Python 3.7, 32 bit on 64 bit Win 7, the first code fragment in the top answer doesn't run for me. It fails because GetBinaryType is an unknown symbol. Solution is to use win32file.GetBinaryType.
  2. Also running it on a .pyd file doesn't work, even if it is renamed to a .dll. See next:

    import shutil
    
    import win32file
    from pathlib import Path
    
    myDir = Path("C:\Users\rdboylan\AppData\Roaming\Python\Python37\site-packages\pythonwin")
    for fn in ("Pythonwin.exe", "win32ui.pyd"):
        print(fn, end=": ")
        myf = myDir / fn
        if myf.suffix == ".pyd":
            mytemp = myf.with_suffix(".dll")
            if mytemp.exists():
                raise "Can not create temporary dll since {} exists".format(mytemp)
            shutil.copyfile(myf, mytemp)
            type = win32file.GetBinaryType(str(mytemp))
            mytemp.unlink()
        else:
            type=win32file.GetBinaryType(str(myf))
        if type==win32file.SCS_32BIT_BINARY:
            print("32 bit")
        else:
            print("Something else")
        # And so on 
    

    Results in

    Pythonwin.exe: 32 bit
    win32ui.pyd: Traceback (most recent call last):
      File "C:/Users/rdboylan/Documents/Wk devel/bitness.py", line 14, in <module>
        type = win32file.GetBinaryType(str(mytemp))
    pywintypes.error: (193, 'GetBinaryType', '%1 is not a valid Win32 application.')
    
  1. 在 64 位 Win 7 上使用 32 位 Python 3.7,顶部答案中的第一个代码片段不适合我。它失败是因为 GetBinaryType 是一个未知符号。解决方法是使用win32file.GetBinaryType.
  2. 在 .pyd 文件上运行它也不起作用,即使它被重命名为 .dll。见下:

    import shutil
    
    import win32file
    from pathlib import Path
    
    myDir = Path("C:\Users\rdboylan\AppData\Roaming\Python\Python37\site-packages\pythonwin")
    for fn in ("Pythonwin.exe", "win32ui.pyd"):
        print(fn, end=": ")
        myf = myDir / fn
        if myf.suffix == ".pyd":
            mytemp = myf.with_suffix(".dll")
            if mytemp.exists():
                raise "Can not create temporary dll since {} exists".format(mytemp)
            shutil.copyfile(myf, mytemp)
            type = win32file.GetBinaryType(str(mytemp))
            mytemp.unlink()
        else:
            type=win32file.GetBinaryType(str(myf))
        if type==win32file.SCS_32BIT_BINARY:
            print("32 bit")
        else:
            print("Something else")
        # And so on 
    

    结果是

    Pythonwin.exe: 32 bit
    win32ui.pyd: Traceback (most recent call last):
      File "C:/Users/rdboylan/Documents/Wk devel/bitness.py", line 14, in <module>
        type = win32file.GetBinaryType(str(mytemp))
    pywintypes.error: (193, 'GetBinaryType', '%1 is not a valid Win32 application.')