2012-02-09 13 views
4

環境:C#、.NET 4.0、および混合モード。Directory.EnumerateFilesとFile.ExistsはネイティブDLLファイルを無視しています

私はいくつかのサードパーティの依存関係を持つ複雑なアプリケーションを持っています。アプリケーションがクラッシュしたとの報告を受けたとき、アセンブリの依存関係を走査してすべての依存関係が存在することを確認するためにいくつかの健全性チェックを追加しました。残念ながら、これは私たちのアプリケーションが使用するネイティブDLLファイルの存在をチェックしません。私たちの意図した解決策は、すべてのDLL名を繰り返し処理し、少なくともその名前のファイルがサニティチェックとして存在することを確認することです。

問題

両方Directory.EnumerateFiles()とFile.Existsは()のいずれかのこれらのネイティブのDLLを参照することはできません。この問題を再現するコードは、「ファイルのリストを表示する方法」の教科書のように簡単です:

foreach(string file in 
     Directory.EnumerateFiles(Environment.CurrentDirectory, "*.dll")) 
{ 
    string entry = Path.GetFileName(file); 
    if (! RequiredFiles.Contains(entry)) 
    { 
     /* Do error handling */ 
    } 
} 

私は上のファイルを一覧表示されたディレクトリに見つめ、私は私が検出したいファイルを見ることができました。これらはシステムファイルとしては何らかの形でフラグが付けられません。しかし、フィルタのテキストを持っているかどうかにかかわらず、.NET DLLファイルのみがリストされていました。私は、より直接的にコードのセクションを書き換える考えとイライラ同じ結果を得た:

foreach(string dependency in RequiredFiles) 
{ 
    string fileName = Environment.CurrentDirectory + '\\' + dependency; 
    if(! File.Exists(fileName)) 
    { /* do error handling */ } 
} 

私はまったく同じ結果を得ました。すべてのネイティブDLLファイルは.NETには見えないようです。この原因は何

質問

?さらに重要なのは、ネイティブDLLファイルがファイルシステム内に見えない場合、どのようにしてネイティブDLLファイルが検出されるのでしょうか?

+0

あなたは空白のプロジェクトでこれを再現することはできますか?私はネイティブのDLLが実際には "不可視"になることに深刻な疑念を持っています。それは他の何かが起こっているように聞こえる。間違ったCurrentDirectory、ある種のシャドウコピー、64ビットOSファイルシステムのリダイレクトなどの32ビットプロセスなどがあります。ネイティブDLLはClickOnceの配備によって無視されることがあります。そのようなもの。 –

答えて

2
  • は、例えば、独自のDLLの名前をメイクMySuperNiftyLibrary.dll。名前を変更したテキストファイルにすることができます。あなたが見ているフォルダに入れます。コードをもう一度実行します。その名前がリストされているかどうかを確認します。それがあなたを納得させることができない場合は、小さな名前の小さな.NETクラスライブラリプロジェクトを作成し、それをディレクトリに配置します。

    は、DLLを他のタイプとは対照的に、.NETのDLLにフィルタリングするだろう理由Directory.EnumerateFilesありませんので、あなたはおそらく正しいディレクトリを見てすることはできません。

  • しかし、あなたがしている場合、その後、あなたが探しているのDLLは、トップレベルのディレクトリまたはサブディレクトリにあるかどうかを検討します。 デフォルトでは、EnumerateFilesは最上位ディレクトリのファイルのみをリストします。すべてのサブディレクトリ内のすべてのファイルを一覧表示するには、EnumerateFilesのこのオーバーロードを使用する必要があります。

Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories)

+0

そして今私は馬鹿のように感じません。私のチェックとトリプルチェックのすべての後、私は正しいディレクトリを探していると確信していました。あなたがこの答えを投稿した後で、私が実際にはほぼ同じだが別のディレクトリを見ていることがわかった。欠落しているファイルは、ネイティブDLLだけです... –

0

次に、このような何かが動作するはずです、シェルを使用します。

  Shell32.Shell shl = null; 
      Shell32.Folder folder = null; 
      try 
      { 
       shl = new Shell32.Shell(); 
       folder = shl.NameSpace(Environment.CurrentDirectory); 
       foreach (Shell32.FolderItem file in folder.Items()) 
       { 
        if (!RequiredFiles.Contains(file.path)) 
        {/* do error handling */} 
       } 
      } 
      catch 
      { } 
      finally 
      { 
       if (folder != null) 
       { 
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder); 
        folder = null; 
       } 
       if (shl != null) 
       { 
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shl); 
        shl = null; 
       } 
      } 

はUPDATE:あなたがXP以降のOSの両方でこれを使用する場合、あなたはのShell32.dll(マイクロソフトシェルコントロールと自動化)を参照する必要がありますXP上でコンパイルして、そのようなdllがプロジェクトにコピーされるようにします。 Vistaや7のdllはXPでは動作しませんし、逆もそうです。これは、シェルスクリプトに依存する簡単なアプローチです。そうしないとあなたはシェルのAPIと直接相互運用できますが、それはより複雑です...

2

は、あなたの作業ディレクトリが正しいことを確認していますか?そうでなければ、Environment.CurrentDirectoryはあなたが期待するものを指しません。 DLLファイルは、あなたの実行コードと同じディレクトリにある場合、あなたが代わりに行うことができます:

Assembly.GetExecutingAssembly().Location 
+0

パスを確認しました。それは私が探していたものと同じものでした。 –

関連する問題