2009-09-02 5 views
15

DLLファイルがWin32 DLLであるか、CLRアセンブリであるかを確認する最適な方法は何ですか?現時点で私はこのコードを使用していますDLLファイルがC言語でCLRアセンブリであるかどうかを確認する最良の方法

try 
    { 
     this.currentWorkingDirectory = Path.GetDirectoryName(assemblyPath); 

     //Try to load the assembly. 
     assembly = Assembly.LoadFile(assemblyPath); 

     return assembly != null; 
    } 
    catch (FileLoadException ex) 
    { 
     exception = ex; 
    } 
    catch (BadImageFormatException ex) 
    { 
     exception = ex; 
    } 
    catch (ArgumentException ex) 
    { 
     exception = ex; 
    } 
    catch (Exception ex) 
    { 
     exception = ex; 
    } 

    if (exception is BadImageFormatException) 
    { 
     return false; 
    } 

しかし、私はそれらの例外(時間)を望んでいないので、ロード前にチェックしたいと思います。

良い方法がありますか?

答えて

17

は、PEヘッダをチェックする:

DOSヘッダが0x0に始まり、(通常は0x80)4 バイトであるPE シグネチャへのポインタを含む0x3cの でDWORD、次の20バイトでありますCOFF ヘッダ、次いでPEヘッダ は0x9で(存在する。PEヘッダは224バイト あり、= 0xFのPEヘッダーに96 バイトのデータディレクトリを(含んでいる。0x16で 15エントリが(CLRヘッダであります 記述子(COMとも呼ばれる記述子ですが、これにはCOMとは何も関係しない はありません)。 が空の場合(0x168 から0x16fまでの8バイトの0)、ファイルは.NET アセンブリではありません。 がCOM DLLであるかどうか確認する場合は、 を参照して、GetClassObjectをエクスポートするかどうかを確認する必要があります。

Ref.

UPDATEPortableExecutableKinds列挙

使用Module.GetPEKind方法とチェック:そこより '.NET' これを達成する方法がある

NotAPortableExecutableImageがファイルは移植可能な実行可能ファイルではありません (PE)ファイル形式。

ILOnlyは、実行は、Microsoft中間言語 (MSIL)が含まれ、したがって、32ビットまたは64ビットプラットフォームに に関して中性です。

Required32Bitは、実行可能ファイルは、32ビットプラットフォーム上で、またはWindows上の 32ビットのWindows(WOW) 環境で64ビットプラットフォーム上で実行することができます。

PE32Plus実行ファイルには、64ビットプラットフォームが必要です。

Unmanaged32Bit実行可能ファイルには、純粋なアンマネージコードが含まれています。

+8

。このソリューションは素晴らしいようですが、Assembly.LoadFile(GetPEKindを呼び出す前に非CLRのDLLに対してBadImageFormatExceptionをスローする)を呼び出さずにModuleインスタンスを取得するにはどうすればよいですか? –

+1

@Simon:あなたにとって興味があるのなら、もちろん答えを書いてコードを追加するのはどうですか? –

+2

@Mitch:おそらく、ダウンボートは少し面白かったです。私は元に戻そうとしましたが、タイムアウトが経過しました。ごめんなさい。私の答えのいくつかをdownvoteに自由に感じて:)。私はこれを働かせようとしました。 Paulsの質問は有効であると私には思われましたが。 Module.GetPEKindはインスタンスです。したがって、Moduleを取得するには、アセンブリAssembly.Loadを呼び出す必要があります。例外をスローします。質問には「例外なし」と明記されているので、この回答は不完全であるか間違っているように見えます。 – Simon

2

以前は同じ問題に直面していましたが、代替方法は手動でPEヘッダーlike thisを読み取るためです。私のシナリオでは過度のもののように思えましたが、それはあなたにとって役に立つかもしれません。

0

コードでこれを行う必要があるのか​​、システムで見ているファイルが.NETアセンブリであるのかを個人的に知る必要があるかどうかは指定していませんこれを行う独自のコード)。後者の場合は、Dependency Walkerを使用して、.NETランタイムエンジンであるMSCOREE.dllに依存するかどうかを確認できます。

+0

ありがとうございますが、これは反射の例外を避けるために必要です。 – schoetbi

-1

バイトが「MZ」は、その後(microsoft slow way)を決定するためにアセンブリ名を読み取ろうとしている場合は、ファイルからアセンブリの有効性を最初の2つのバイトを読み取ることができます。

public static bool isValidAssembly (string sFileName) 
    { 
     try 
     { 
      using (FileStream fs = File.OpenRead(sFileName)) 
      { 
       if ((fs.ReadByte() != 'M') || (fs.ReadByte() != 'Z')) 
       { 
        fs.Close(); 
        return false; 
       } 
       fs.Close(); 
      } 

      // http://msdn.microsoft.com/en-us/library/ms173100.aspx 
      object foo = SR.AssemblyName.GetAssemblyName(sFileName); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 
5

アセンブリは、例えばAssembly.LoadFile(dotNetDllorExe)をロードされると任意の例外をスローしない場合は、有効な.NETアセンブリです。そうでなければ "BadImageFormatException"をスローします。

ファイルをロードして例外がスローされたかどうかをチェックすることによって、ファイルが天気かどうかをチェックする考え方あまりにもきれいではないようです。すべての例外が例外的に使用されるはずです。


.NETアセンブリは通常のWin32 PEファイルで、オペレーティングシステムは.NETアセンブリとWin32実行可能バイナリを区別しません。通常のPEファイルと同じです。では、CLRをロードするために、DLLまたはEXEがマネージアセンブリの場合、システムはどのように動作しますか?

ファイルヘッダーを検証して、管理対象アセンブリであるかどうかを確認します。 ECMA Specification Partition II - .NET SDKと共に出荷されるメタデータでは、PEフォーマットに別のCLIヘッダーがあることがわかります。 PEオプションヘッダーの15番目のデータディレクトリはです。したがって、単純に言えば、このデータディレクトリに値がある場合、これは有効な.NETアセンブリであることを意味します。それ以外の場合はそうではありません。

internal static class PortableExecutableHelper 
{ 
    internal static bool IsDotNetAssembly(string peFile) 
    { 
     uint peHeader; 
     uint peHeaderSignature; 
     ushort machine; 
     ushort sections; 
     uint timestamp; 
     uint pSymbolTable; 
     uint noOfSymbol; 
     ushort optionalHeaderSize; 
     ushort characteristics; 
     ushort dataDictionaryStart; 
     uint[] dataDictionaryRVA = new uint[16]; 
     uint[] dataDictionarySize = new uint[16]; 


     Stream fs = new FileStream(peFile, FileMode.Open, FileAccess.Read); 
     BinaryReader reader = new BinaryReader(fs); 

     //PE Header starts @ 0x3C (60). Its a 4 byte header. 
     fs.Position = 0x3C; 

     peHeader = reader.ReadUInt32(); 

     //Moving to PE Header start location... 
     fs.Position = peHeader; 
     peHeaderSignature = reader.ReadUInt32(); 

     //We can also show all these value, but we will be  
     //limiting to the CLI header test. 

     machine = reader.ReadUInt16(); 
     sections = reader.ReadUInt16(); 
     timestamp = reader.ReadUInt32(); 
     pSymbolTable = reader.ReadUInt32(); 
     noOfSymbol = reader.ReadUInt32(); 
     optionalHeaderSize = reader.ReadUInt16(); 
     characteristics = reader.ReadUInt16(); 

     /* 
      Now we are at the end of the PE Header and from here, the 
         PE Optional Headers starts... 
       To go directly to the datadictionary, we'll increase the  
       stream’s current position to with 96 (0x60). 96 because, 
         28 for Standard fields 
         68 for NT-specific fields 
      From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total, 
      doing simple maths 128/16 = 8. 
      So each directory is of 8 bytes. 
         In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size. 

      btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :) 
    */ 
     dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60); 
     fs.Position = dataDictionaryStart; 
     for (int i = 0; i < 15; i++) 
     { 
      dataDictionaryRVA[i] = reader.ReadUInt32(); 
      dataDictionarySize[i] = reader.ReadUInt32(); 
     } 
     if (dataDictionaryRVA[14] == 0) 
     { 
      Console.WriteLine("This is NOT a valid CLR File!!"); 
      return false; 
     } 
     else 
     { 
      Console.WriteLine("This is a valid CLR File.."); 
      return true; 
     } 
     fs.Close(); 
    } 
} 

ECMA Ref 、あなたが好きなものを使用することができBlog Ref

0

 AssemblyName assemblyName = null; 

     try 
     { 
      assemblyName = AssemblyName.GetAssemblyName(filename); 
     } 
     catch (System.IO.FileNotFoundException ex) 
     { 
      throw new Exception("File not found!", ex); 
     } 
     catch (System.BadImageFormatException ex) 
     { 
      throw new Exception("File is not an .Net Assembly.", ex); 
     } 

もチェックしてみて下さい:私はOPに似た何かをしようとしている https://msdn.microsoft.com/en-us/library/ms173100.aspx

関連する問題