2

WPFプログラムで使用する汎用ユーティリティdllファイルがあります。私のプログラムが最初に行うことは、更新されたdllファイルをチェックし、それを実行ディレクトリにコピーすることです。これらはすべて、dllからメソッドやプロパティを参照することなく行われます。

Visual Studio(v10)内からプログラムをコンパイルして実行すると、すべてが期待どおりに機能します。プログラムが起動し、dllファイルをチェックし、必要に応じてコピーしてから、アセンブリの使用に進みます。

コンパイルされた.exeファイルをWindowsエクスプローラーから実行すると、最初にUtil.dllアセンブリをロードするように見えます。これによりファイルがロックされ、更新できなくなります。

Visual Studioと.exeファイルでプログラムの動作が異なる理由について誰かが洞察を持っていますか?.exeファイルの実行時にアセンブリが読み込まれる原因を追跡することについて何か考えはありますか?

プログラム起動のコードスニペットは次のとおりです。

void AppLoad(object sender, StartupEventArgs e)
{

  //Used to see what assemblies are loaded.
  System.Text.StringBuilder sb = new System.Text.StringBuilder();
  foreach (var item in AppDomain.CurrentDomain.GetAssemblies())
  {
    sb.AppendLine(item.FullName.ToString());
  }
  System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "test.txt", sb.ToString());


  //Check for the latest Util dll.
  if (!UpdateUtil())
  {
    //Shutdown.
    Application.Current.Shutdown();
    return;
  }

  //Start the main window.
  MainWindow m = new MainWindow();
  m.Show();
}

bool UpdateUtil()
{
  //Verify network path.
  if (!Directory.Exists(_componentPath))
  {
    MessageBox.Show("The program encountered an error.\r\rPlease contact your Program Administrator with the following information:\r\r" +
      "Program Name - Genesis Admin\r\r" +
      "Error Message - Network Component path not found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    return false;
  }
  //Verify file existance.
  string sourceFileName = _componentPath + "Util.dll";
  if (!File.Exists(sourceFileName))
  {
    MessageBox.Show("The program encountered an error.\r\rPlease contact your Program Administrator with the following information:\r\r" +
      "Program Name - Genesis Admin\r\r" +
      "Error Message - Network Util file not found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    return false;
  }

  string destFileName = AppDomain.CurrentDomain.BaseDirectory + "Util.dll";
  if (!File.Exists(destFileName) || File.GetLastWriteTime(sourceFileName) > File.GetLastWriteTime(destFileName))
    File.Copy(sourceFileName, destFileName, true);

  return true;
}
4

3 に答える 3

6

これは一般的に危険なことです。アセンブリは、メソッドのマシンコードを生成する必要があるときに、ジャストインタイムコンパイラによってロードされます。おそらく期待していないのは、インライン化されるコードです。これは、リリースビルドで有効になっている重要な最適化です。デバッガーで実行すると、その最適化はオフになります。

スニペットでは、「util.dll」からどのタイプがロードされるかは明らかではありません。ただし、util.dllからのすべての型が、UpdateUtil()呼び出しから遠く離れた個別のメソッドに含まれるように、コードを再構築してください。メソッドの[MethodImpl(MethodImplOptions.NoInlining)]属性を使用してインライン化を抑制します。

これを行うための最善の方法は、テストを実行してからメインの.exeを起動する小さなbootstrapper.exeファイルを使用することです。ただし、ユーザーのマシンでこのコードを実行すると、間違いなく再び壁にぶつかることに注意してください。UACの昇格なしにDLLをc:\programファイルにコピーすることはできません。これは実際にはインストーラータスクであり、コードに含めるべきではありません。

于 2012-06-19T00:36:50.677 に答える
1

ファイルがコピーされている場所を確認してください。私は間違っているかもしれませんが、Visual Studioはプロジェクトのフォルダーを現在のフォルダーとして使用する可能性がありますが、エクスプローラーから起動すると、実行可能ファイルの場所が作業ディレクトリとして使用されます。

destFileName(メッセージボックスのように)の値を出力してみてください。私はドットネットの専門家ではありませんが、通常、通常のDLLには遅延ロードを使用します。このページに何か役立つものがあるかもしれません。しかし、もう一度、私はドットネットを知りません。

于 2012-06-19T00:07:25.640 に答える
0

更新されたファイルを探す必要がある場合は、プラグインベースフレームワークを使用することをお勧めします。コンセプトは、ディレクトリ内の特定の名前ですべてのファイルを検索し、それらをプログラムにロードすることです。インターフェイスを使用して、プログラムの起動直後にコンパイルされないようにします。

于 2012-06-19T01:09:19.410 に答える