如何知道使用的 dll 是否需以 32 位元模式執行

最近因為年度計畫預計做些 Windows server OS 的升級作業,將大部份 OS 升級為 Windows Server 2016,也順便整理 server 上的 application,發現仍有不少 application 執行在 32 位模式下,過去主要的原因是 Oracle.DataAccess.dll,原以為只要搞定 Oracle.DataAccess.dll 就可以,想不到後續又遇到其他參考的 dll 需要執行在 32 bit 模式下,所以找了幾個方式來試著不需要反覆部署至 IIS 上進行測試即可得知特定的 dll 是否需要執行在 32 bit 的相容執行環境

網路上分享的方法有很多種,今天會以本次遇到問題的 dll 中的 Oracle.DataAccess.dllSystem.Data.dll當做範例來進行測試,立馬來看看哪個方式比較方便吧

使用 dumpbin:無法識別是否需要 32 位元模式

曾經在之前筆記 如何看程式是 32 bit 還是 64 bit 紀錄到,詳細的使用方式可以參考原文 如何看程式是 32 bit 還是 64 bit

  • 使用方式

    dumpbin.exe /headers {檔案}
    
  • 實際使用

    • System.Data.dll

      • 需要 32 位元模式

        $ "G:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\dumpbin.exe" /headers D:\Test\System.Data.dll
        Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
        Copyright (C) Microsoft Corporation.  All rights reserved.
        
        
        Dump of file D:\Test\System.Data.dll
        
        PE signature found
        
        File Type: DLL
        
        FILE HEADER VALUES
                    14C machine (x86)
                    5 number of sections
                471EBF27 time date stamp Wed Oct 24 11:42:31 2007
                    0 file pointer to symbol table
                    0 number of symbols
                    E0 size of optional header
                    2102 characteristics
                        Executable
                        32 bit word machine
                        DLL
        
        OPTIONAL HEADER VALUES
                    10B magic # (PE32)
                    8.00 linker version
                2A4800 size of code
                40800 size of initialized data
                    0 size of uninitialized data
                2A4630 entry point (65114630)
                    1000 base of code
                2A6000 base of data
                64E70000 image base (64E70000 to 6515BFFF)
                    1000 section alignment
                    200 file alignment
                    5.00 operating system version
                    8.00 image version
                    4.10 subsystem version
                    0 Win32 version
                2EC000 size of image
                    400 size of headers
                2EDF46 checksum
                    3 subsystem (Windows CUI)
                    0 DLL characteristics
                100000 size of stack reserve
                    1000 size of stack commit
                100000 size of heap reserve
                    1000 size of heap commit
                    0 loader flags
                    10 number of directories
                2A5580 [     1A2] RVA [size] of Export Directory
                2A478C [      B4] RVA [size] of Import Directory
                2AE000 [   35F40] RVA [size] of Resource Directory
                    0 [       0] RVA [size] of Exception Directory
                    0 [       0] RVA [size] of Certificates Directory
                2E4000 [    4BCC] RVA [size] of Base Relocation Directory
                    1330 [      1C] RVA [size] of Debug Directory
                    0 [       0] RVA [size] of Architecture Directory
                    0 [       0] RVA [size] of Global Pointer Directory
                    0 [       0] RVA [size] of Thread Storage Directory
                116D0 [      40] RVA [size] of Load Configuration Directory
                    0 [       0] RVA [size] of Bound Import Directory
                    1000 [     2D8] RVA [size] of Import Address Table Directory
                    0 [       0] RVA [size] of Delay Import Directory
                110C4 [      48] RVA [size] of COM Descriptor Directory
                    0 [       0] RVA [size] of Reserved Directory
        

        1dumpbinsystemdata

      • 不需 32 位元模式

        Dump of file D:\Test\System.Data_ok.dll
        
        PE signature found
        
        File Type: DLL
        
        FILE HEADER VALUES
                    14C machine (x86)
                    3 number of sections
                4BA1E072 time date stamp Thu Mar 18 16:12:34 2010
                    0 file pointer to symbol table
                    0 number of symbols
                    E0 size of optional header
                    2022 characteristics
                        Executable
                        Application can handle large (>2GB) addresses
                        DLL
        
        OPTIONAL HEADER VALUES
                    10B magic # (PE32)
                10.00 linker version
                142600 size of code
                    800 size of initialized data
                    0 size of uninitialized data
                142A7A entry point (615B2A7A)
                    2000 base of code
                146000 base of data
                61470000 image base (61470000 to 615B9FFF)
                    2000 section alignment
                    200 file alignment
                    4.00 operating system version
                    0.00 image version
                    4.00 subsystem version
                    0 Win32 version
                14A000 size of image
                    200 size of headers
                14ED98 checksum
                    3 subsystem (Windows CUI)
                    140 DLL characteristics
                        Dynamic base
                        NX compatible
                100000 size of stack reserve
                    1000 size of stack commit
                100000 size of heap reserve
                    1000 size of heap commit
                    0 loader flags
                    10 number of directories
                    0 [       0] RVA [size] of Export Directory
                142A28 [      4F] RVA [size] of Import Directory
                146000 [     434] RVA [size] of Resource Directory
                    0 [       0] RVA [size] of Exception Directory
                143000 [    1758] RVA [size] of Certificates Directory
                148000 [       C] RVA [size] of Base Relocation Directory
                    0 [       0] RVA [size] of Debug Directory
                    0 [       0] RVA [size] of Architecture Directory
                    0 [       0] RVA [size] of Global Pointer Directory
                    0 [       0] RVA [size] of Thread Storage Directory
                    0 [       0] RVA [size] of Load Configuration Directory
                    0 [       0] RVA [size] of Bound Import Directory
                    2000 [       8] RVA [size] of Import Address Table Directory
                    0 [       0] RVA [size] of Delay Import Directory
                    2008 [      48] RVA [size] of COM Descriptor Directory
                    0 [       0] RVA [size] of Reserved Directory
        

        2dumpbinsystemdata32

    • Oracle.DataAccess.dll

      • 需要 32 位元

        $ "G:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\dumpbin.exe" /headers D:\Test\Oracle.DataAccess.dll
        Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
        Copyright (C) Microsoft Corporation.  All rights reserved.
        
        
        Dump of file D:\Test\Oracle.DataAccess.dll
        
        PE signature found
        
        File Type: DLL
        
        FILE HEADER VALUES
                    14C machine (x86)
                    3 number of sections
                48B315B4 time date stamp Tue Aug 26 04:27:32 2008
                    0 file pointer to symbol table
                    0 number of symbols
                    E0 size of optional header
                    210E characteristics
                        Executable
                        Line numbers stripped
                        Symbols stripped
                        32 bit word machine
                        DLL
        
        OPTIONAL HEADER VALUES
                    10B magic # (PE32)
                    8.00 linker version
                DE000 size of code
                    2000 size of initialized data
                    0 size of uninitialized data
                DFD1E entry point (110DFD1E)
                    2000 base of code
                E0000 base of data
                11000000 image base (11000000 to 110E3FFF)
                    2000 section alignment
                    1000 file alignment
                    4.00 operating system version
                    0.00 image version
                    4.00 subsystem version
                    0 Win32 version
                E4000 size of image
                    1000 size of headers
                E5C54 checksum
                    3 subsystem (Windows CUI)
                    540 DLL characteristics
                        Dynamic base
                        NX compatible
                        No structured exception handler
                100000 size of stack reserve
                    1000 size of stack commit
                100000 size of heap reserve
                    1000 size of heap commit
                    0 loader flags
                    10 number of directories
                    0 [       0] RVA [size] of Export Directory
                DFCC4 [      57] RVA [size] of Import Directory
                E0000 [     460] RVA [size] of Resource Directory
                    0 [       0] RVA [size] of Exception Directory
                    0 [       0] RVA [size] of Certificates Directory
                E2000 [       C] RVA [size] of Base Relocation Directory
                    0 [       0] RVA [size] of Debug Directory
                    0 [       0] RVA [size] of Architecture Directory
                    0 [       0] RVA [size] of Global Pointer Directory
                    0 [       0] RVA [size] of Thread Storage Directory
                    0 [       0] RVA [size] of Load Configuration Directory
                    0 [       0] RVA [size] of Bound Import Directory
                    2000 [       8] RVA [size] of Import Address Table Directory
                    0 [       0] RVA [size] of Delay Import Directory
                    2008 [      48] RVA [size] of COM Descriptor Directory
                    0 [       0] RVA [size] of Reserved Directory
        

        3dumpbinoracle

      • 不需要 32 位元

        $ "G:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\dumpbin.exe" /headers D:\Test\Oracle.DataAccess_ok.dll
        Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
        Copyright (C) Microsoft Corporation.  All rights reserved.
        
        
        Dump of file D:\Test\Oracle.DataAccess_ok.dll
        
        PE signature found
        
        File Type: DLL
        
        FILE HEADER VALUES
                    8664 machine (x64)
                    2 number of sections
                4B9A20B6 time date stamp Fri Mar 12 19:08:38 2010
                    0 file pointer to symbol table
                    0 number of symbols
                    F0 size of optional header
                    212E characteristics
                        Executable
                        Line numbers stripped
                        Symbols stripped
                        Application can handle large (>2GB) addresses
                        32 bit word machine
                        DLL
        
        OPTIONAL HEADER VALUES
                    20B magic # (PE32+)
                    8.00 linker version
                F6000 size of code
                    1000 size of initialized data
                    0 size of uninitialized data
                    0 entry point
                    2000 base of code
                11000000 image base (0000000011000000 to 00000000110F9FFF)
                    2000 section alignment
                    1000 file alignment
                    4.00 operating system version
                    0.00 image version
                    4.00 subsystem version
                    0 Win32 version
                FA000 size of image
                    1000 size of headers
                1036BB checksum
                    3 subsystem (Windows CUI)
                    540 DLL characteristics
                        Dynamic base
                        NX compatible
                        No structured exception handler
                400000 size of stack reserve
                    4000 size of stack commit
                100000 size of heap reserve
                    2000 size of heap commit
                    0 loader flags
                    10 number of directories
                    0 [       0] RVA [size] of Export Directory
                    0 [       0] RVA [size] of Import Directory
                F8000 [     460] RVA [size] of Resource Directory
                    0 [       0] RVA [size] of Exception Directory
                    0 [       0] RVA [size] of Certificates Directory
                    0 [       0] RVA [size] of Base Relocation Directory
                    0 [       0] RVA [size] of Debug Directory
                    0 [       0] RVA [size] of Architecture Directory
                    0 [       0] RVA [size] of Global Pointer Directory
                    0 [       0] RVA [size] of Thread Storage Directory
                    0 [       0] RVA [size] of Load Configuration Directory
                    0 [       0] RVA [size] of Bound Import Directory
                    0 [       0] RVA [size] of Import Address Table Directory
                    0 [       0] RVA [size] of Delay Import Directory
                    2000 [      48] RVA [size] of COM Descriptor Directory
                    0 [       0] RVA [size] of Reserved Directory
        

        4dumpbinoracle

使用 CorFlags:個人測試下不一定可以識別是否需要 32 位元模式

CorFlags.exe 是 .net framework 的內建工具

  • 判斷基準

    platformPE32BITREQ
    Any CPUPE320
    x86PE321
    x64PE32+0
  • 實際使用

    • System.Data.dll

      • 需要 32 位元模式

        $ "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools\CorFlags.exe" d:\TEST\System.Data.dll
        Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  4.7.2558.0
        Copyright (c) Microsoft Corporation.  All rights reserved.
        
        Version   : v2.0.50727
        CLR Header: 2.5
        PE        : PE32
        CorFlags  : 0x18
        ILONLY    : 0
        32BITREQ  : 0
        32BITPREF : 0
        Signed    : 1 
        

        5corflagssystemdata

      • 不需要 32 位元模式

        $ "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools\CorFlags.exe" d:\TEST\System.Data_ok.dll
        Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  4.7.2558.0
        Copyright (c) Microsoft Corporation.  All rights reserved.
        
        Version   : v4.0.30319
        CLR Header: 2.5
        PE        : PE32
        CorFlags  : 0x9
        ILONLY    : 1
        32BITREQ  : 0
        32BITPREF : 0
        Signed    : 1
        

        6corflagsystemdata

    • Oracle.DataAccess.dll

      • 需要 32 位元模式

        $ "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools\CorFlags.exe" d:\TEST\Oracle.DataAccess.dll
        Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  4.7.2558.0
        Copyright (c) Microsoft Corporation.  All rights reserved.
        
        Version   : v2.0.50727
        CLR Header: 2.5
        PE        : PE32
        CorFlags  : 0xb
        ILONLY    : 1
        32BITREQ  : 1
        32BITPREF : 0
        Signed    : 1
        

        7corflagoracle

      • 不需要 32 位元模式

        $ "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools\CorFlags.exe" d:\TEST\Oracle.DataAccess_ok.dll
        Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  4.7.2558.0
        Copyright (c) Microsoft Corporation.  All rights reserved.
        
        Version   : v2.0.50727
        CLR Header: 2.5
        PE        : PE32+
        CorFlags  : 0x9
        ILONLY    : 1
        32BITREQ  : 0
        32BITPREF : 0
        Signed    : 1
        

        8corflagoracle

使用 powershell:勉強可識別是否需要 32 位元模式

  • ProcessorArchitecture

    ProcessorArchitecture說明
    Amd64僅 64-bit AMD 處理器適用
    ArmARM 處理器適用
    IA64僅 64-bit Intel 處理器適用.
    MSIL不限處理器
    None無法辨識處理器
    X8632-bit Intel 處理器, 或是 64-bit 平台上 Windows on Windows 環境(WOW64).
  • 實際使用

    • System.Data.dll

      • 需要 32 位元模式

        PS C:\Users\yowko.tsai> $dllpath="d:\TEST\System.Data.dll"
        
        [reflection.assemblyname]::GetAssemblyName($dllpath) | fl
        
        
        Name                  : System.Data
        Version               : 2.0.0.0
        CultureInfo           : 
        CultureName           : 
        CodeBase              : file:///d:/TEST/System.Data.dll
        EscapedCodeBase       : file:///d:/TEST/System.Data.dll
        ProcessorArchitecture : X86
        ContentType           : Default
        Flags                 : PublicKey
        HashAlgorithm         : SHA1
        VersionCompatibility  : SameMachine
        KeyPair               : 
        FullName              : System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
        

        9pssystemdata

      • 不需要 32 位元模式

        PS C:\Users\yowko.tsai> $dllpath="d:\TEST\System.Data_ok.dll"
        
        [reflection.assemblyname]::GetAssemblyName($dllpath) | fl
        
        
        Name                  : System.Data
        Version               : 4.0.0.0
        CultureInfo           : 
        CultureName           : 
        CodeBase              : file:///d:/TEST/System.Data_ok.dll
        EscapedCodeBase       : file:///d:/TEST/System.Data_ok.dll
        ProcessorArchitecture : None
        ContentType           : Default
        Flags                 : PublicKey
        HashAlgorithm         : SHA1
        VersionCompatibility  : SameMachine
        KeyPair               : 
        FullName              : System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
        
        

        10pssystemdata

    • Oracle.DataAccess.dll

      • 需要 32 位元模式

        PS C:\Users\yowko.tsai> $dllpath="d:\TEST\Oracle.DataAccess.dll"
        
        [reflection.assemblyname]::GetAssemblyName($dllpath) | fl
        
        
        Name                  : Oracle.DataAccess
        Version               : 2.111.7.0
        CultureInfo           : 
        CultureName           : 
        CodeBase              : file:///d:/TEST/Oracle.DataAccess.dll
        EscapedCodeBase       : file:///d:/TEST/Oracle.DataAccess.dll
        ProcessorArchitecture : X86
        ContentType           : Default
        Flags                 : PublicKey
        HashAlgorithm         : SHA1
        VersionCompatibility  : SameMachine
        KeyPair               : 
        FullName              : Oracle.DataAccess, Version=2.111.7.0, Culture=neutral, PublicKeyToken=89b483f429c47342
        

        11psoracle

      • 不需要 32 位元模式

        PS C:\Users\yowko.tsai> $dllpath="d:\TEST\Oracle.DataAccess_ok.dll"
        
        [reflection.assemblyname]::GetAssemblyName($dllpath) | fl
        
        
        Name                  : Oracle.DataAccess
        Version               : 2.112.1.0
        CultureInfo           : 
        CultureName           : 
        CodeBase              : file:///d:/TEST/Oracle.DataAccess_ok.dll
        EscapedCodeBase       : file:///d:/TEST/Oracle.DataAccess_ok.dll
        ProcessorArchitecture : Amd64
        ContentType           : Default
        Flags                 : PublicKey
        HashAlgorithm         : SHA1
        VersionCompatibility  : SameMachine
        KeyPair               : 
        FullName              : Oracle.DataAccess, Version=2.112.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342
        

        12psoracle

使用 c#:可識別是否需要 32 位元模式

  • 實際使用

    • System.Data.dll

      • 需要 32 位元模式

        string dllpath = @"D:\Test\System.Data.dll";
        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(dllpath);
        assembly.ManifestModule.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
        peKind.Dump();
        

        13cssystemdata

      • 不需要 32 位元模式

        string dllpath = @"D:\Test\System.Data_ok.dll";
        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(dllpath);
        assembly.ManifestModule.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
        peKind.Dump();
        

        14cssystemdata

    • Oracle.DataAccess.dll

      • 需要 32 位元模式

        string dllpath = @"D:\Test\Oracle.DataAccess.dll";
        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(dllpath);
        assembly.ManifestModule.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
        peKind.Dump();
        

        15csoracle

      • 不需要 32 位元模式

        string dllpath = @"D:\Test\Oracle.DataAccess_ok.dll";
        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(dllpath);
        assembly.ManifestModule.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
        peKind.Dump();
        

        16csoracle

心得

方法乍看之下有好幾個,但實際使用上可以正確判讀出是否需要 32 bit 模式的並不多,嚴格說起來只有 PowerShell 跟 c# 的方法可以滿足要求,CorFlag 實際使用上有的 dll 可以正確判讀有的則不行,而 c# 與 PowerShell 相比,PowerShell 的訊息仍然相對模糊,c# 整體的訊息非常直覺,但 PowerShell 不用編譯的優點則是 C# 望塵莫及的

透過將幾個方式測試一輪順便紀錄,到時有需要就視情況取用即可,雖然花了一些時間,但日後再次用到時就划算了(應該)

參考資訊

  1. 如何看程式是 32 bit 還是 64 bit
  2. Check whether a .NET dll is built for Any CPU, x86, or x64
  3. ProcessorArchitecture 列舉
  4. How to determine if a .NET assembly was built for x86 or x64?
  5. PortableExecutableKinds 列舉