2

我的 WPF 程序中使用了一个通用实用程序 dll 文件。我的程序做的第一件事是检查更新的 dll 文件并将其复制到执行目录 - 所有这些都没有引用 dll 中的任何方法或属性。

当我从 Visual Studio (v10) 内部编译和运行程序时,一切都按预期工作。程序启动,检查 dll 文件,如果需要进行复制,然后继续使用程序集。

如果我从 Windows 资源管理器运行编译的 .exe 文件,它似乎做的第一件事就是加载 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 文件进行测试,然后启动您的主 .exe。但是请记住,当您在用户机器上运行此代码时,您无疑会再次碰壁,如果没有 UAC 提升,您无法将 DLL 复制到 c:\program 文件中。这实际上是一个安装程序任务,它不应该出现在您的代码中。

于 2012-06-19T00:36:50.677 回答
1

检查文件被复制到哪里。我可能错了,但 Visual Studio 可能使用项目的文件夹作为当前文件夹,而当您从资源管理器启动时,您的可执行文件的位置被用作工作目录。

您能否尝试输出的值destFileName(例如使用消息框)。我不是 dot net 方面的专家,但通常对常规 DLL 使用延迟加载。这个页面上可能有一些有用的东西。但是我再一次不知道点网。

于 2012-06-19T00:07:25.640 回答
0

如果您需要查找更新的文件,那么您可能需要使用插件基础框架。概念是您在目录中查找具有特定名称的所有文件 - 然后将它们加载到程序中。使用接口来防止它们在程序启动后立即被编译。

于 2012-06-19T01:09:19.410 回答