在AppDomain中运行csc.exe时,调用者命令行参数被意外传递的问题
问题根源
兄弟,你碰到的这个情况其实是AppDomain的默认特性搞的鬼:当你创建新的应用域时,如果没有特意配置参数,新域会自动继承当前进程的命令行参数。所以哪怕你没主动给csc.exe传任何参数,你的主程序收到的所有参数都会被“悄悄”传递过去,让csc.exe误以为是给它的指令。
修复方案
解决起来很简单,你只需要在创建AppDomain的时候,显式指定它的参数配置,把不需要的参数清空就行。这里给你补全并修正了代码:
using System; using System.IO; class Program { static void Main(string[] args) { var cscPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Roslyn\csc.exe"; // 先创建应用域的配置对象,手动清空参数 var appDomainSetup = new AppDomainSetup { Arguments = string.Empty, // 这里可以替换成你真正想传给csc的参数,比如"/help" ApplicationBase = Path.GetDirectoryName(cscPath) // 确保csc能找到依赖组件 }; // 用配置好的参数创建新应用域 var cscAppDomain = AppDomain.CreateDomain("cscDomain", null, appDomainSetup); try { // 在新域里执行csc.exe cscAppDomain.ExecuteAssembly(cscPath); } finally { // 用完记得卸载应用域,避免资源浪费 AppDomain.Unload(cscAppDomain); } } }
几个关键细节
- 必须显式设置
Arguments:如果不做这个操作,AppDomain会默认取当前进程的所有命令行参数,也就是你的主程序收到的args。 - 设置
ApplicationBase:把它设为csc.exe所在的目录,能避免csc找不到Roslyn相关依赖的问题,不然可能会触发运行时错误。 - 卸载应用域:执行完csc后一定要调用
AppDomain.Unload,释放掉新应用域占用的资源。
要是之后你需要给csc传特定编译参数,直接改Arguments的值就好,比如想编译一个类库:
Arguments = "/target:library /out:MyCustomLib.dll MySourceClass.cs"
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

