我的WPF程序中使用了一个通用的Utility 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;
}
答案 0 :(得分:6)
这通常是一件很危险的事情,当需要为方法生成机器代码时,程序集会由即时编译器加载。您可能不指望的是获取内联的代码,这是在发布版本中启用的重要优化。使用调试器运行时,该优化是 off 。
在您的代码段中,从“util.dll”加载哪种类型并不明显。但请务必重新构建代码,以便来自util.dll的所有类型都位于远离UpdateUtil()调用的单独方法中。使用方法上的[MethodImpl(MethodImplOptions.NoInlining)]属性抑制内联。
到目前为止,最好的方法是使用一个小的bootstrapper .exe文件进行测试然后启动你的主.exe。但请记住,当您在用户的计算机上运行此代码时,无疑会再次碰到墙,您无法将DLL复制到没有UAC提升的c:\ program文件中。这实际上是一个安装程序任务,它不应该在您的代码中。
答案 1 :(得分:1)
检查文件的复制位置。我可能错了,但Visual Studio可能会将项目文件夹用作当前文件夹,而当您从资源管理器启动时,可执行文件的位置将用作工作目录。
您可以尝试输出destFileName
的值(与消息框一样)。我不是dot net的专家,但通常使用延迟加载常规DLL。 this page上可能有一些有用的东西。但我再一次不知道dot net。
答案 2 :(得分:0)
如果您需要查找更新的文件,那么您可能需要使用插件基础框架。概念是您在目录中按特定名称查找所有文件 - 然后将它们加载到程序中。使用接口可以防止在程序启动后立即编译它们。