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

StackOverflow https://stackoverflow.com/questions/270531

質問

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

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

役に立ちましたか?

解決

System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

を見てください。

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

PowerShell の使用:

[36] C:\> [reflection.assemblyname]::GetAssemblyName("${pwd}\Microsoft.GLEE.dll") | fl

Name                  : Microsoft.GLEE
Version               : 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=neut... 

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

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

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

他のヒント

CorFlags CLI ツール(C:\ Program Files \ Microsoft SDKs \ Windows \ v7など) .0 \ Bin \ CorFlags.exe)、出力に基づいてアセンブリの状態を判断し、バイナリ資産としてアセンブリを開くと、32BITフラグが1に設定されているかどうかを判断する必要がある場所を判断できるはずです。 ( x86 )または0(任意のCPU または x64 PE に応じて):

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

ブログ投稿 。NETによるx64開発 には、 corflags に関するいくつかの情報があります。

さらに良いのは、 Module.GetPEKind を使用して、アセンブリが PortableExecutableKinds PE32Plus (64ビット)、 Required32Bit (32ビットおよびWOW)、または ILOnly (任意のCPU)と他の属性。

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

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

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

  3. 次のように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

あなたはあなた自身を書いてどうですか? 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.

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

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

[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);
    }
}

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

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

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

以下のバッチファイルがアンマネージ 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.
JetBriansの

DotPeekは、msil(anycpu)、x86、x64をすばやく簡単に確認する方法を提供します dotPeek

もう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>

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

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

ここに画像の説明を入力してください

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

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

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

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

別の方法として、 https://stackoverflow.com/a/4719567/64257 には、&quot;があるまた、実行可能イメージのテストに使用できる PowerShell Community Extensions のGet-PEHeaderコマンドレット。

ここで見つけることができるより高度なアプリケーション: 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

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

public static CompilationMode GetCompilationMode(this FileInfo info)
{
    if (!info.Exists) throw new ArgumentException(
[Flags]
public enum CompilationMode
{
    Invalid = 0,
    Native = 0x1,
    CLR = Native << 1,
    Bit32 = CLR << 1,
    Bit64 = Bit32 << 1
}
quot;{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); } }

コンパイルモードの列挙

<*>

GitHub

に説明があるソースコード
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top