4

.cab ファイルに含まれるファイルのバージョン番号を取得する小さなアプリを作成しました。

cab から一時ディレクトリにすべてのファイルを抽出し、すべてのファイルをループして、次のようにバージョン番号を取得します。

//Attempt to load .net assembly to retrieve information
Assembly assembly = Assembly.LoadFile(tempDir + @"\" + renameTo);
Version version = assembly.GetName().Version;
DataRow dr = dt.NewRow();
dr["Product"] = renameTo;
dr["Version"] = version.ToString();
dt.Rows.Add(dr); 

次に、終了したら、次のように抽出されたすべてのファイルを削除します。

        foreach (string filePath in filePaths)
        {
            //Remove read-only attribute if set
            FileAttributes attributes = File.GetAttributes(filePath);

            if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                File.SetAttributes(filePath, attributes ^ FileAttributes.ReadOnly);
            }

            File.Delete(filePath);
        }

これは、.net .exe で時々失敗することを除いて、すべてのファイルで機能します。ロックされているように見えないように、ファイルを手動で削除できます。

この作業を行うには、何を探す必要がありますか? Assembly.LoadFile はおそらくファイルをロックしていますか?

4

3 に答える 3

6

Assembly.LoadFile は実際にファイルをロックします。ファイルからアセンブリを読み込み、その後ファイルを削除する必要がある場合は、次のことを行う必要があります。

  1. 新しい AppDomain を開始する
  2. その appdomain にアセンブリをロードします
  3. そこでのみ使用してください。メインのアプリドメインでアセンブリの型を使用しないでください。
  4. AppDomain.Unloadを呼び出してAppDomainを破棄します
  5. 次に、ファイルを削除します

アセンブリが実行中の AppDomain に読み込まれている間は、そのアセンブリを含むファイルを削除できません。

于 2012-05-25T16:37:29.193 に答える
2

AssemblyName.GetAssemblyNameAssemblyNameファイルをロックせずにオブジェクトを取得します。msdnを参照してください。そこからバージョンを入手できます。

于 2012-05-25T17:51:10.203 に答える
1

もう 1 つの方法 (別の AppDomain で Load from file を使用する方法に加えて) は、Assembly.Load from bytesを使用してファイルの MemoryStream コピーからアセンブリをメインの AppDomain にロードすることです。

コードを完全に正しくするには、1 つのファイルに同じ ID を持つアセンブリがある場合 (つまり、同じファイル名を持つ 2 つの厳密に署名されていないアセンブリ)、アセンブリごとに個別の AppDomains が必要になる場合があることに注意してください。

別の AppDomain を使用しても、シナリオでは LoadReflectionOnlyFrom を使用してバイトからロードする方が安全です。この場合、AppDomain のアンロードに失敗してもファイルがロックされたままになる可能性はなく、ファイルのロックを自分で完全に制御できるからです。バイトからの読み込みを使用してアセンブリを定期的に読み込むには、関連する問題を理解するためにかなりの読み取りが必要であり、回避することをお勧めします。

于 2012-05-25T16:47:01.717 に答える