cashiba 发表于 2024-11-22 10:59:21

判断dll或exe文件是32位还是64位的函数[已解决]

本帖最后由 cashiba 于 2024-11-25 23:59 编辑

Func FileCheckBit($file)
      Local $b = ""
      Local $f = StringLeft($file, StringInStr($file, "", 0, -1)) & "bitchk"
      If FileCopy($file, $f, 9) Then
                Local $h = FileOpen($f, 16)
                If $h <> -1 Then
                        Local $s = FileRead($h)
                        If StringInStr($s, "504500004C") Then
                              $b = "x86"
                        ElseIf StringInStr($s, "5045000064") Then
                              $b = "x64"
                        EndIf
                EndIf
                FileDelete($f)
      EndIf
      Return $b
EndFunc
有时某些dll或exe文件不知道是32位或64位的,跟系统不一致会导致出错或没反应,需要提前判断一下
搜了一下没找到类似的主题或函数(可能检索词没选好),有的话请给个链接
用这个来检测某些dll文件或exe文件是64位还是32位,简单测了一下sqlite3.dll可行。
原理参照:https://www.cnblogs.com/God4/articles/11721559.html之第三个方法
感觉上面的写法还不太严谨, 比喻说32位或64位系统都可用的dll或exe。
期待高手完善或创新....

afan 发表于 2024-11-22 12:52:14

试试 _WinAPI_GetBinaryType

chishingchan 发表于 2024-11-22 19:30:31

早前我自己写的。大家讨论,共同进步!
Func _UPX($File)        ;获取文件架构,压缩状态,版本日期
        Local $PE_Header, $Return, $Bit, $UPX0
        $ADODB_Stream = ObjCreate("ADODB.Stream")                                                                        ;创建流对象
        $ADODB_Stream.Type = 1                                                                                                                ;数据类型
        $ADODB_Stream.Open                                                                                                                        ;打开流
        $ADODB_Stream.LoadFromFile($File)                                                                                        ;以流方式加载文件
        $ADODB_Stream.Position = 0x3C                                                                                                ;PE..
        $PE_Header = $ADODB_Stream.Read(4)                                                                                        ;=0xF0970000
        $ADODB_Stream.Position = _H2L($PE_Header) + 0x14                                                        ;0x000097F0 + 0x00000014 = 0x00009804
        $Bit = StringTrimRight($ADODB_Stream.Read(2), 2)                                                        ;=0xE000=0xE0
        If $File <> $setup_exe Then
                If $Bit = 0xE0 Then                                                                                                                        ;如果等于 0xE0
                        ;$Bit = "X86"                                                                                                                                ;是32位程序
                        $ADODB_Stream.Position = _H2L($PE_Header) + 0xF8                                                        ;32位 UPX0 的地址偏移量
                        $UPX0 = BinaryToString($ADODB_Stream.Read(4))                                                                ;读取4个字节并转换为字符串
                Else                                                                                                                                                ;如果不等于 0xE0
                        ;$Bit = "X64"                                                                                                                                ;是64位程序
                        $ADODB_Stream.Position = _H2L($PE_Header) + 0x108                                                        ;64位 UPX0 的地址偏移量
                        $UPX0 = BinaryToString($ADODB_Stream.Read(4))                                                                ;读取4个字节并转换为字符串
                EndIf
                $ADODB_Stream.Close                                                                                                                        ;关闭流
                If $UPX0 = "UPX0" Then
                        $UPX = True
                Else
                        $UPX = False
                EndIf
                Return $UPX
        EndIf
EndFunc

chishingchan 发表于 2024-11-22 19:33:18

补充:主要是针对 SnapShot 备份还原软件

cashiba 发表于 2024-11-22 20:00:20

afan 发表于 2024-11-22 12:52
试试 _WinAPI_GetBinaryType

原来早就有现成的api原型函数了,A大博闻强识,啥都知道,强!
{:1_206:}

cashiba 发表于 2024-11-22 20:02:03

chishingchan 发表于 2024-11-22 19:33
补充:主要是针对 SnapShot 备份还原软件

#include <APIFilesConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Local $sText, $sPath = @MyDocumentsDir & '\'
While 1
    $sPath = FileOpenDialog(''选择文件', _WinAPI_PathRemoveFileSpec($sPath), '所有文件 (*.*)', 1 + 2)
    If $sPath Then
      If _WinAPI_GetBinaryType($sPath) Then
            Switch @extended
                Case $SCS_32BIT_BINARY
                  $sText = ' 32 位 Windows 应用程序.'
                Case $SCS_64BIT_BINARY
                  $sText = ' 64 位 Windows 应用程序.'
                Case $SCS_DOS_BINARY
                  $sText = ' MS-DOS 应用程序.'
                Case $SCS_OS216_BINARY
                  $sText = ' 16 位 OS/2 应用程序.'
                Case $SCS_PIF_BINARY
                  $sText = ' MS-DOS 应用程序的 PIF 文件.'
                Case $SCS_POSIX_BINARY
                  $sText = ' POSIX 应用程序.'
                Case $SCS_WOW_BINARY
                  $sText = ' 16 位 Windows 应用程序.'
                Case Else
                  $sText = ' 未知类型的可执行文件.'
            EndSwitch
      Else
            $sText = ' 不是可执行文件.'
      EndIf
      MsgBox(BitOR($MB_ICONINFORMATION, $MB_SYSTEMMODAL), '_WinAPI_GetBinaryType()', '"' & _WinAPI_PathStripPath($sPath) & '" 是 ' & $sText & ".")
    Else
      ExitLoop
    EndIf
WEnd

有这个API就太简单了,还很详细

cashiba 发表于 2024-11-22 20:08:03

chishingchan 发表于 2024-11-22 19:30
早前我自己写的。大家讨论,共同进步!

这个用了汇编方法?....厉害!
{:1_206:}

cashiba 发表于 2024-11-22 20:18:11

GetBinaryTypeW好像只针对可执行文件(exe),对dll没效果...

chishingchan 发表于 2024-11-22 20:28:29

cashiba 发表于 2024-11-22 20:08
这个用了汇编方法?....厉害!

补充一个函数:
Func _H2L($Binary)        ;十六进制字符串高低位转换
        Local $L2H
        For $i = 1 To StringLen(Hex($Binary)) Step 2
                $L2H = StringMid(Hex($Binary), $i, 2) & $L2H
        Next
        $L2H = "0x" & $L2H
        Return $L2H
EndFunc   ;==>_H2L

haijie1223 发表于 2024-11-23 11:03:32

凑个热闹

Func IsPEFile64($FilePath)
      Local $hFile = FileOpen($FilePath, 16)
      Local $Bin = FileRead($hFile, 1024)
      FileClose($hFile)
      Local $aBin
      For $i = 0 To UBound($aBin) - 1
                $aBin[$i] = Number(BinaryMid($Bin, $i + 1, 1))
      Next
      Local $Index = $aBin + $aBin * 256 + $aBin * 65536 + $aBin * 16777216
      If $aBin <> 77 Or $aBin <> 90 Or $aBin[$Index] <> 80 Or $aBin[$Index + 1] <> 69 Then Return 0
      If $aBin[$Index + 4] = 100 And $aBin[$Index + 5] = 134 Then Return 64
      Return 32
EndFunc   ;==>IsPEFile64
Local $FilePath = "D:\autoit3\AutoIt3_x64.exe" ; 替换为你的文件路径
Switch IsPEFile64($FilePath)
      Case 64
                ConsoleWrite("64位程序" & @CRLF)
      Case 32
                ConsoleWrite("32位程序" & @CRLF)
      Case Else
                ConsoleWrite("非可执行文件" & @CRLF)
EndSwitch

cashiba 发表于 2024-11-24 09:53:55

本帖最后由 cashiba 于 2024-11-24 09:55 编辑

haijie1223 发表于 2024-11-23 11:03
凑个热闹
------>IsPEFile('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32
-->FileCheckBit('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32

------>IsPEFile('C:\Program Files\Windows Media Player\setup_wm.exe'):
64
-->FileCheckBit('C:\Program Files\Windows Media Player\setup_wm.exe'):
64


------>IsPEFile('C:\Program Files (x86)\Windows Media Player\WMPDMCCore.dll'):
32
-->FileCheckBit('C:\Program Files (x86)\Windows Media Player\WMPDMCCore.dll'):


------>IsPEFile('C:\Program Files\Windows Media Player\WMPDMCCore.dll'):
64
-->FileCheckBit('C:\Program Files\Windows Media Player\WMPDMCCore.dll'):

拿一般系统中都有的程序文件左了测试如上。
发哥这个比较普适,优于_WinAPI_GetBinaryType

cashiba 发表于 2024-11-24 10:08:59

Func _UPX($file)
      Local $Bit = ""
      $ADODB_Stream = ObjCreate("ADODB.Stream")
      $ADODB_Stream.Type = 1
      $ADODB_Stream.Open
      $ADODB_Stream.LoadFromFile($file)
      $ADODB_Stream.Position = 0x3C
      $Bit = StringTrimRight($ADODB_Stream.Read(2), 2)
      If $Bit = 0xE0 Then
                $Bit = "64"
      Else
                $Bit = "32"
      EndIf
      $ADODB_Stream.Close
      Return $Bit
EndFunc   ;==>_UPXchishingchan 班主的代码改了一下(如上,不知道改得对不对)
再次测试了一下,结果如下:

------>IsPEFile('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32
---------->_UPX('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32
-->FileCheckBit('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32

------>IsPEFile('C:\Program Files\Windows Media Player\setup_wm.exe'):
64
---------->_UPX('C:\Program Files\Windows Media Player\setup_wm.exe'):
64
-->FileCheckBit('C:\Program Files\Windows Media Player\setup_wm.exe'):
64

------>IsPEFile('C:\Program Files (x86)\Windows Media Player\WMPDMCCore.dll'):
32
---------->_UPX('C:\Program Files (x86)\Windows Media Player\WMPDMCCore.dll'):
32
-->FileCheckBit('C:\Program Files (x86)\Windows Media Player\WMPDMCCore.dll'):

------>IsPEFile('C:\Program Files\Windows Media Player\WMPDMCCore.dll'):
64
---------->_UPX('C:\Program Files\Windows Media Player\WMPDMCCore.dll'):
32
-->FileCheckBit('C:\Program Files\Windows Media Player\WMPDMCCore.dll'):



chishingchan 发表于 2024-11-24 10:57:38

cashiba 发表于 2024-11-24 10:08
chishingchan 班主的代码改了一下(如上,不知道改得对不对)
再次测试了一下,结果如下:



連函數名稱也一并改了吧!

Func _Bit($file)
      Local $Bit = ""
      $ADODB_Stream = ObjCreate("ADODB.Stream")
      $ADODB_Stream.Type = 1
      $ADODB_Stream.Open
      $ADODB_Stream.LoadFromFile($file)
      $ADODB_Stream.Position = 0x3C
      $Bit = StringTrimRight($ADODB_Stream.Read(2), 2)
      If $Bit = 0xE0 Then
                $Bit = "64"
      Else
                $Bit = "32"
      EndIf
      $ADODB_Stream.Close
      Return $Bit
EndFunc   ;==>_Bit

chishingchan 发表于 2024-11-24 10:58:56

此方法是根據 PE 頭的特徵,使用流對象對其讀取進行判斷。

haijie1223 发表于 2024-11-24 12:43:22

cashiba 发表于 2024-11-24 09:53
------>IsPEFile('C:\Program Files (x86)\Windows Media Player\setup_wm.exe'):
32
-->FileCheckBit('C: ...
必须普适啊,这个如果不适用,我想那就没有适用的了吧
页: [1] 2
查看完整版本: 判断dll或exe文件是32位还是64位的函数[已解决]