当某个程序集文件被载入AppDomain,该文件在AppDomain.Unload之前是不能被替换和删除的。
使用AppDomainSetup的影像复制功能可以实现在不卸载程序的情况下替换或者删除程序集文件。
domain.ExecuteAssembly(@"loads\test.exe");
File.Delete(@"loads\test.exe");
上述代码没有在删除文件前调用 AppDomain.Unload(domain); ,所以会出现"拒绝访问"的异常。
接下来我们打开影像复制功能,你会发现目标程序集文件被正确删除。
// 打开影像复制。
domain.SetShadowCopyFiles();
// 设置要进行影像设置的程序集路经。
domain.SetShadowCopyPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "loads"));
domain.ExecuteAssembly(@"loads\test.exe");
File.Delete(@"loads\test.exe");
我们在"loads\test.exe"中使用"Assembly.GetExecutingAssembly().Location"查看,你会发现程序集文件被复制到"c:\documents and settings\user1\local settings\application data\assembly\dl2\6e9nkvqy.yol\dhp83obd.j9j\9730b8d1\00fb5179_6d04c601\test.exe"这样一个目录中,这也是程序集被正确删除的根本原因(^_^)。正因为目标程序集的位置发生变化,因此我们要做更进一步的设置,否则目标程序集在加载动态引用或者读取配置文件时出错。
setup.ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "loads");
setup.ConfigurationFile = Path.Combine(setup.ApplicationBase, "test.exe.config");
setup.ShadowCopyFiles = "true";
setup.ShadowCopyDirectories = setup.ApplicationBase;
AppDomain domain = AppDomain.CreateDomain("a", null, setup);
domain.ExecuteAssembly(@"loads\test.exe");
File.Delete(@"loads\test.exe");
ok, 这回没问题了。