CodeDOM——执行编译后的代码,第二次会产生错误

本文关键字:第二次 错误 代码 执行 编译 CodeDOM | 更新日期: 2023-09-27 18:17:04

我目前正在与CodeDOM代码生成器和执行编译程序集作斗争。除了第二次运行编译后的代码外,一切都很顺利。

设置>

用户"编程"一个将被转换成可执行程序的模型。用户可以定义程序集是只在内存中创建还是在磁盘上创建,是要有源代码还是只有可执行文件。当他点击"运行"按钮时,CodeDOM树被放在一起并被编译、写入磁盘(如果需要)并执行。

当他第二次点击"run"按钮时,抛出一个异常:

错误CS0016:无法写入输出文件":——"进程无法访问该文件,因为它正在被另一个进程。"

由于我可以随时编译代码而不会遇到错误,因此我建议它与我运行程序集的方式有关。我在网上搜索了关于这个主题的信息,但我所得到的只是创建一个单独的AppDomain,然后卸载它。

下面是执行程序集的代码片段:
if ( RunProject )
{
  _log.info( "Compiled without errors, running..." );
  Assembly compiledAssembly = res.CompiledAssembly;
  AppDomain compiledAssemblyDomain = AppDomain.CreateDomain( "compiledAssemblyDomain" );
  compiledAssemblyDomain.ExecuteAssemblyByName( compiledAssembly.GetName( ) );
  AppDomain.Unload( compiledAssemblyDomain );
}

可执行文件只能在退出程序时被删除,就好像该文件被当前appdomain锁定一样。该怎么办?谢谢你的帮助!


当上面的代码执行时,主文件被加载到执行程序集中(我错了吗?)调试控制台输出以下信息:

[13:42:19.5576171]  i  Compiled without errors, running...
'XXX.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:'...'bin'main.exe'

,在退出执行的程序集后几秒钟:

The thread '.NET SystemEvents' (0x20d0) has exited with code 0 (0x0). 
The thread '<No Name>' (0x1d20) has exited with code 0 (0x0).

,其中XXX是编译代码的主应用程序的名称。文件不应该加载到其他地方吗?没有XXX.vshost.exe打开一个处理和不关闭后卸载AppDomain?

CodeDOM——执行编译后的代码,第二次会产生错误

我曾为此纠结过不少(我在《滚动游戏开发工具包2》中做过类似的事情)。你必须非常小心地确保你对编译代码所做的一切都发生在另一个AppDomain中,这样当你卸载AppDomain时,所有对DLL的引用都被卸载了。如果您从编译的代码中引用了一个类型,那么DLL也将被加载到您的 AppDomain中,而卸载另一个域将没有什么好处。所以我要做的就是在一个通用的DLL中定义接口,它可以被加载到两个域中,这样我就可以在另一个DLL中调用函数,而不需要从另一个DLL中加载类型。只要确保在另一个DLL中实例化的每个对象都使用共享DLL中定义的接口(或未在用户定义的DLL中定义的另一个公共接口)。然后将您从DLL实例化的每个对象强制转换为这些接口之一。你永远不能直接使用DLL中定义的类型。

EDIT:观察MSDN文档中关于CompiledAssembly属性

的以下说明

注意CompiledAssembly属性的get访问器调用Load方法来加载将程序集编译到当前应用程序域中。调用get访问器之后,在卸载当前的AppDomain之前,不能删除已编译的程序集。