it-swarm-ja.com

.NETアセンブリがx86またはx64向けにビルドされたかどうかを判断する方法は?

.NETアセンブリの任意のリストがあります。

各DLLが(x64または任意のCPUとは対照的に)x86用にビルドされているかどうかをプログラムで確認する必要があります。これは可能ですか?

301

System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)を見てください

返されたAssemblyNameインスタンスからアセンブリメタデータを調べることができます。

PowerShellの使用:

 [36] C:\> [reflection.assemblyname] :: GetAssemblyName( "$ {pwd}\Microsoft.GLEE.dll")| fl 
 
名前:Microsoft.GLEE 
バージョン:1.0.0.0 
 CultureInfo:
 CodeBase:file:/// C:/ projects/powershell/BuildAnalyzer /...
 EscapedCodeBase:file:/// C:/ projects/powershell/BuildAnalyzer/... 
ProcessorArchitecture:MSIL
 Flags:PublicKey 
 HashAlgorithm:SHA1 
 VersionCompatibility:SameMachine 
 KeyPair:
 FullName:Microsoft.GLEE、Version = 1.0.0.0、Culture =いや... 

ここで、 ProcessorArchitecture はターゲットプラットフォームを識別します。

  • AMD64:x64アーキテクチャに基づく64ビットプロセッサ。
  • Arm:ARMプロセッサー。
  • IA64:64ビットIntel Itaniumプロセッサのみ。
  • MSIL:プロセッサおよびワードごとのビットに関してニュートラル。
  • X86:64ビットプラットフォーム(WOW64)上のネイティブまたはWindows on Windows環境の32ビットIntelプロセッサ。
  • None:プロセッサとワードごとのビットの未知または未指定の組み合わせ。

この例ではPowerShellを使用してメソッドを呼び出しています。

256
x0n

CorFlagsCLI ツール(たとえば、C:\ Program Files\Microsoft SDKs\Windows\v7.0\Bin\CorFlags.exe)を使用して決定できますアセンブリのステータス。出力に基づいて、バイナリアセットとしてアセンブリを開くと、32BITフラグが1(x86)に設定されているかどうかを判断するためにどこを探す必要があるかを判断できます)または0(任意のCPUまたはx64PEに応じて:

Option    | PE    | 32BIT
----------|-------|---------
x86       | PE32  | 1
Any CPU   | PE32  | 0
x64       | PE32+ | 0

ブログの投稿。NETでのx64開発にはcorflagsに関する情報があります。

さらに良いことに、 Module.GetPEKindを使用 を使用して、アセンブリがPortableExecutableKindsPE32Plus(64ビット)、Required32Bit(32ビットおよびWOW)、またはILOnly(任意のCPU)が他の属性と一緒であるかどうかを判断できます。

216
cfeduke

明確にするために、CorFlags.exeは 。NET Framework SDK の一部です。私のマシンには開発ツールがあり、DLLが32ビットのみかどうかを判断する最も簡単な方法は次のとおりです。

  1. Visual Studioコマンドプロンプトを開きます(Windowsの場合:メニュースタート/プログラム/ Microsoft Visual Studio/Visual Studioツール/ Visual Studio 2008コマンドプロンプト)

  2. 問題のDLLを含むディレクトリへのCD

  3. 次のようなcorflagsを実行します:corflags MyAssembly.dll

次のような出力が得られます。

    Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 3
ILONLY    : 1
32BIT     : 1
Signed    : 0

コメントによると、上記のフラグは次のように読み取られます。

  • 任意のCPU:PE = PE32および32BIT = 0
  • x86:PE = PE32および32BIT = 1
  • 64ビット:PE = PE32 +および32BIT = 0
135
JoshL

自分で書いてみてはどうですか? PEアーキテクチャのコアは、Windows 95で実装されて以来、大幅に変更されていません。C#の例を次に示します。

    public static ushort GetPEArchitecture(string pFilePath)
    {
        ushort architecture = 0;
        try
        {
            using (System.IO.FileStream fStream = new System.IO.FileStream(pFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                using (System.IO.BinaryReader bReader = new System.IO.BinaryReader(fStream))
                {
                    if (bReader.ReadUInt16() == 23117) //check the MZ signature
                    {
                        fStream.Seek(0x3A, System.IO.SeekOrigin.Current); //seek to e_lfanew.
                        fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin); //seek to the start of the NT header.
                        if (bReader.ReadUInt32() == 17744) //check the PE\0\0 signature.
                        {
                            fStream.Seek(20, System.IO.SeekOrigin.Current); //seek past the file header,
                            architecture = bReader.ReadUInt16(); //read the magic number of the optional header.
                        }
                    }
                }
            }
        }
        catch (Exception) { /* TODO: Any exception handling you want to do, personally I just take 0 as a sign of failure */}
        //if architecture returns 0, there has been an error.
        return architecture;
    }
}

現在の定数は次のとおりです。

0x10B - PE32  format.
0x20B - PE32+ format.

しかし、このメソッドを使用すると、新しい定数の可能性が考慮され、適切なように戻り値を検証するだけです。

18
Jason

CorFlagsReaderを使用してみてください CodePlexのこのプロジェクトから 。他のアセンブリへの参照はなく、そのまま使用できます。

9
Ludwo
[TestMethod]
public void EnsureKWLLibrariesAreAll64Bit()
{
    var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(x => x.FullName.StartsWith("YourCommonProjectName")).ToArray();
    foreach (var Assembly in assemblies)
    {
        var myAssemblyName = AssemblyName.GetAssemblyName(Assembly.FullName.Split(',')[0] + ".dll");
        Assert.AreEqual(ProcessorArchitecture.MSIL, myAssemblyName.ProcessorArchitecture);
    }
}
6
Morgan Mellor

JetBriansのDotPeekを使用すると、msil(anycpu)、x86、x64をすばやく簡単に確認できます dotPeek

以下は、現在の作業ディレクトリとすべてのサブディレクトリ内のすべてのdllsおよびexesに対してcorflags.exeを実行し、結果を解析してそれぞれのターゲットアーキテクチャを表示するバッチファイルです。

使用されるcorflags.exeのバージョンに応じて、出力の行項目には32BITor32BITREQ(および32BITPREF)が含まれます。これらの2つのうちどちらが出力に含まれるかは、Any CPUx86を区別するためにチェックする必要がある重要な項目です。古いバージョンのcorflags.exe(Windows SDK v8.0Aより前)を使用している場合、他のユーザーが過去の回答で示したように、32BIT行項目のみが出力に表示されます。それ以外の場合は、32BITREQおよび32BITPREFで置き換えます。

これは、corflags.exe%PATH%にあることを前提としています。これを確実にする最も簡単な方法は、Developer Command Promptを使用することです。または、 デフォルトの場所 からコピーすることもできます。

以下のバッチファイルがアンマネージdllまたはexeに対して実行される場合、x86からの実際の出力は次のようなエラーメッセージになるため、誤ってCorflags.exeと表示されます。

corflags:エラーCF008:指定されたファイルには有効なマネージヘッダーがありません

@echo off

echo.
echo Target architecture for all exes and dlls:
echo.

REM For each exe and dll in this directory and all subdirectories...
for %%a in (.exe, .dll) do forfiles /s /m *%%a /c "cmd /c echo @relpath" > testfiles.txt

for /f %%b in (testfiles.txt) do (
    REM Dump corflags results to a text file
    corflags /nologo %%b > corflagsdeets.txt

   REM Parse the corflags results to look for key markers   
   findstr /C:"PE32+">nul .\corflagsdeets.txt && (      
      REM `PE32+` indicates x64
        echo %%~b = x64
    ) || (
      REM pre-v8 Windows SDK listed only "32BIT" line item, 
      REM newer versions list "32BITREQ" and "32BITPREF" line items
        findstr /C:"32BITREQ  : 0">nul /C:"32BIT     : 0" .\corflagsdeets.txt && (
            REM `PE32` and NOT 32bit required indicates Any CPU
            echo %%~b = Any CPU
        ) || (
            REM `PE32` and 32bit required indicates x86
            echo %%~b = x86
        )
    )

    del corflagsdeets.txt
)

del testfiles.txt
echo.
4
Eric Lease

もう1つの方法は、DLLのVisual Studioツールからdumpbinを使用し、適切な出力を探すことです。

dumpbin.exe /HEADERS <your dll path>
    FILE HEADER VALUE
                 14C machine (x86)
                   4 number of sections
            5885AC36 time date stamp Mon Jan 23 12:39:42 2017
                   0 file pointer to symbol table
                   0 number of symbols
                  E0 size of optional header
                2102 characteristics
                       Executable
                       32 bit Word machine
                       DLL

注:上記のo/pは32ビットdll用です

Dumpbin.exeのもう1つの便利なオプションは/ EXPORTSです。dllによって公開された機能が表示されます

dumpbin.exe /EXPORTS <PATH OF THE DLL>
2
Ayush joshi

利用可能なすべての情報を表示するために、Windowsエクスプローラーでアセンブリのコンテキストメニューエントリを追加する非常に便利なツールを複製しました。

ここからダウンロード: https://github.com/tebjan/AssemblyInformation/releases

enter image description here

2
thalm

cfedukeは、GetPEKindを呼び出す可能性を指摘しています。 PowerShellからこれを行うのは興味深い可能性があります。

たとえば、使用できるコマンドレットのコードは次のとおりです。 https://stackoverflow.com/a/16181743/64257

または、 https://stackoverflow.com/a/4719567/64257 で、「 PowerShell Community Extensions にはGet-PEHeaderコマンドレットもあり、実行可能イメージのテストに使用されます。」

1
Chris

.NETアセンブリのターゲットプラットフォームを確認する別の方法は、 。NET Reflector ...でアセンブリを検査することです。

@#〜#€〜!新しいバージョンが無料ではないことに気づきました!そのため、修正版です。無料版の.NETリフレクターがあれば、それを使用してターゲットプラットフォームを確認できます。

1
juanjo.arana

あなたのためのより高度なアプリケーションはここにあります: CodePlex-ApiChange

例:

C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\winhlp32.exe
File Name; Type; Size; Processor; IL Only; Signed
winhlp32.exe; Unmanaged; 296960; X86

C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\HelpPane.exe
File Name; Type; Size; Processor; IL Only; Signed
HelpPane.exe; Unmanaged; 733696; AMD64
1

より一般的な方法-ファイル構造を使用して、ビット数と画像タイプを決定します。

public static CompilationMode GetCompilationMode(this FileInfo info)
{
    if (!info.Exists) throw new ArgumentException($"{info.FullName} does not exist");

    var intPtr = IntPtr.Zero;
    try
    {
        uint unmanagedBufferSize = 4096;
        intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize);

        using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read))
        {
            var bytes = new byte[unmanagedBufferSize];
            stream.Read(bytes, 0, bytes.Length);
            Marshal.Copy(bytes, 0, intPtr, bytes.Length);
        }

        //Check DOS header magic number
        if (Marshal.ReadInt16(intPtr) != 0x5a4d) return CompilationMode.Invalid;

        // This will get the address for the WinNT header  
        var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60);

        // Check WinNT header signature
        var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset);
        if (signature != 0x4550) return CompilationMode.Invalid;

        //Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER
        var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24);

        var result = CompilationMode.Invalid;
        uint clrHeaderSize;
        if (magic == 0x10b)
        {
            clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4);
            result |= CompilationMode.Bit32;
        }
        else if (magic == 0x20b)
        {
            clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4);
            result |= CompilationMode.Bit64;
        }
        else return CompilationMode.Invalid;

        result |= clrHeaderSize != 0
            ? CompilationMode.CLR
            : CompilationMode.Native;

        return result;
    }
    finally
    {
        if (intPtr != IntPtr.Zero) Marshal.FreeHGlobal(intPtr);
    }
}

コンパイルモードの列挙

[Flags]
public enum CompilationMode
{
    Invalid = 0,
    Native = 0x1,
    CLR = Native << 1,
    Bit32 = CLR << 1,
    Bit64 = Bit32 << 1
}

GitHub に説明があるソースコード

0
BlackGad