.NETアセンブリがx86またはx64用にビルドされているかどうかを確認するにはどうすればよいですか?


327

.NETアセンブリの任意のリストを持っています。

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



2
これをチェックアウトすることもできます:check-if-unmanaged-dll-is-32-bit-or-64-bit
マット

2
.NET 4.5に対応する新しいバージョンのCorFlagsでは、「32BIT」は「32BITREQ」「32BITPREF」に置き換えられました。
Peter Mortensen 2015年

回答:


281

見る 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 / ...
プロセッサアーキテクチャ:MSIL
フラグ: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:32ビットIntelプロセッサ(ネイティブまたは64ビットプラットフォーム(WOW64)上のWindows on Windows環境)。
  • なし:不明な、または指定されていないプロセッサーとワードあたりのビット数の組み合わせ。

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


60
愚かな質問を許してください-しかし、これで何がx86だとわかりますか?
ジョージマウアー

53
ProcessorArchitectureフィールドは列挙型です。上記の例では、MSILに設定されています。これは、「プロセッサーとワードあたりのビット数に関して中立」を意味します。その他の値には、X86、IA64、Amd64が含まれます。詳細については、msdn.microsoft.com / en-us / library /…を参照してください
Brian Gillespie、

4
[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")プロセスの現在のディレクトリが現在のプロバイダーと同じではない場合があるので試してみてください(ここにDLLがあると思います)
x0n

2
DLLをインターネットからダウンロードした場合、DLLを「ブロック解除」するのを忘れることに注意する必要があります。unblock-fileを使用するか、エクスプローラーから右クリック/プロパティ/ブロックを解除します。現在のセッションで一度失敗した場合は、シェルを再起動してブロック解除状態を認識する必要があります(インターネットエクスプローラーのせいです-はい、本当に。)
x0n

1
ASP.NET MVCコードにはコメントがあります。// DevDiv 216459: This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in medium trust. However, Assembly.FullName *is* accessible in medium trust.残念ながら、GetName instance method; を使用せずにProcessorArchitectureを読み取る方法はありません。を使用するAssemblyName constructorと、フィールドは常にに設定されNoneます。
metadings 2014

221

あなたは使用することができますCorFlags CLIのアセンブリの状態を判断するために、その出力に基づいて、Aからアセンブリを開く:ツール(の\ Program Files \ MicrosoftのSDK \ Windowsの\ v7.0の\ビン\ CorFlags.exeを例えば、C)を32BITフラグが1(x86)または0(すべてのCPUまたはx64に応じてPE)に設定されているかどうかを判断するために探す必要がある場所を判断できるバイナリアセット:

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

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

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


1
更新を確認した後、GetPEKindを使用するのが適切な方法のようです。あなたの答えをマークしました。
ユダガブリエルヒマンゴ08年

9
32ビットアセンブリをチェックすると、64ビットプロセスでGetPEKindが失敗する
jjxtra

2
32ビットプロセスからGetPEKindを呼び出す必要があります
Ludwo '18

2
VS 2008、VS 2010、VS 2012およびVS 2013をインストールします。C:\ Program Files(x86)\ Microsoft SDKs \ Windows \のサブフォルダーにCorFlags.exeの8つのファイルがあります。私はどちらを使うべきですか?
キケネット2014年

5
この回答で指摘されているように、.NET 4.5では、32BITフラグの代わりに32BITREQと32BITPREFがあります。PE32 / 0/0およびPE32 / 0/1は、それぞれAnyCPUおよびAnyCPU 32ビット優先です。
Angularsen、2015年

141

明確にするために、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

12
その間、これは変わったようです。corflags は、単一の値ではなくを表示するように32BITREQなりました。32BITPREF32BIT
またはMapper

1
Microsoft .NET 4.5では、新しいオプションであるAny CPU 32-bit Preferredが導入されました。ここでは詳細です。
RBT 2017

「Visual Studioコマンドプロンプト」は、現在「Visual Studio 2019 Developer Command Prompt」と呼ばれています。
Uwe Keim

22

自分で書いてみませんか?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.

ただし、このメソッドを使用すると、新しい定数の可能性が可能になります。必要に応じて戻り値を検証してください。


1
興味深い、説明付きのコードに感謝します。Module.GetPEKindがおそらく最も簡単なパスです。しかし、これは学習のために役立ちます。ありがとう。
ユダガブリエルヒマンゴ2012年

3
非常に興味深いですが、アプリケーションをAny CPUでコンパイルすると、結果は0x10Bになります。アプリケーションがx64システムで実行されているため、これは誤りです。チェックする他のフラグはありますか?
サミュエル

GetPEArchitectureは、.net 3.5、4.0、4.5および4.5.1を使用してコンパイルされたアセンブリで機能しますか?とにかく、32ビットアセンブリをチェックすると、64ビットプロセスでModule.GetPEKindが失敗します。
キケネット2014年

9

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


1
これが最も正確で有用な答えです。
Kirill Osenkov 2013年

この記事の執筆時点でもリンクは機能していますが、CodePlexがシャットダウンされようとしているため、手遅れになる前に適切なアクションを実行することをお勧めします。
Peter Mortensen 2017年


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

このおかげで、アプリケーションの1つをx86としてビルドする必要があります。ユニットテストを追加すると、ビルドサーバーのビルドライブラリが32ビットになり、これらのミスの発生を回避できます:)
Mido

5

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

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

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

以下のバッチファイルをアンマネージドdllまたはに対して実行すると、からの実際の出力は次のようなエラーメッセージになるため、exe誤ってとして表示されます。x86Corflags.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.

2

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

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

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での説明付きのソースコード



1

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

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


9
使用ILSpyは、それが反射板とほとんど同じことを行い、基本的なオープンソースのアプリだ
バイナリ心配性

1

cfedukeは、GetPEKindを呼び出す可能性を指摘しています。PowerShellからこれを実行することは、潜在的に興味深いことです。

たとえば、次のコードは、使用可能なコマンドレットのコードです。https//stackoverflow.com/a/16181743/64257

または、https: //stackoverflow.com/a/4719567/64257で、「実行可能なイメージのテストに使用できるPowerShellコミュニティ拡張機能のGet-PEHeaderコマンドレットもあります」と記載されています。


1

そのためのより高度なアプリケーションは、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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.