我的应用程序使用CodeDom动态编译来自源文件的一部分JavaScript代码。在Windows上,一切正常。但是在Linux上运行应用程序最终会抛出InvalidOperationException,它不会为调试提供有用的信息。这种情况的根本原因是什么?
我使用Mono 4.0.x在Debian Jessie上测试了应用程序
private JScriptCodeProvider compiler = new JScriptCodeProvider();
private CompilerParameters parameters = new CompilerParameters();
参数:
parameters.ReferencedAssemblies.Add("System.dll");
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
编译:
// This line throws InvalidOperationException
var result = compiler.CompileAssemblyFromSource(parameters, scriptCode);
跟踪信息:
e
{System.InvalidOperationException: Process has not been started.
at System.Diagnostics.Process.get_ExitCode () [0x00015] in <filename
unknown>:0
at (wrapper remoting-invoke-with-check)
System.Diagnostics.Process:get_ExitCode ()
at System.CodeDom.Compiler.Executor.InternalExecWaitWithCapture
(System.String cmd, System.String currentDir,
System.CodeDom.Compiler.TempFileCollection tempFiles, System.String&
outputName, System.String& errorName) [0x000f1] in <filename
unknown>:0
at System.CodeDom.Compiler.Executor.ExecWaitWithCapture
(System.String cmd, System.CodeDom.Compiler.TempFileCollection
tempFiles, System.String& outputName, System.String& errorName)
[0x00006] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.Compile
(System.CodeDom.Compiler.CompilerParameters options, System.String[]
fileNames, Boolean keepFiles) [0x0009c] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.FromSourceBatch
(System.CodeDom.Compiler.CompilerParameters options, System.String[]
sources) [0x0006b] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch
(System.CodeDom.Compiler.CompilerParameters options, System.String[]
sources) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource
(System.CodeDom.Compiler.CompilerParameters options, System.String[]
sources) [0x00014] in <filename unknown>:0
at ***.ScriptEngine.compile () [0x00036] in
***ScriptEngine.cs:139 }
System.InvalidOperationException
答案 0 :(得分:1)
Codedom在Linux上有点奇怪。它的实现方式与在Windows上的实现方式不同,如果实现的话。如果您打算制作跨平台应用程序,我建议使用Mono的compiler as a service或CS-Script's更友好的实现。编译器作为服务没有很好的文档记录,并且与Microsoft的运行时编译器的工作方式不同。 CS-Script是Microsoft和Mono运行时编译器的包装器,它有很好的文档记录和直接。
答案 1 :(得分:0)
由于某些原因,CodeDom无法生成新进程以将源代码编译为临时程序集。我想在处理许可时出了点问题。见下文:
converting method System.CodeDom.Compiler.Executor:ExecWaitWithCapture (string,System.CodeDom.Compiler.TempFileCollection,string&,string&)
Method System.CodeDom.Compiler.Executor:ExecWaitWithCapture (string,System.CodeDom.Compiler.TempFileCollection,string&,string&) emitted at 0x42060b90 to 0x42060bd5 (code length 69) [MyApp.exe]
converting method System.CodeDom.Compiler.Executor:InternalExecWaitWithCapture (string,string,System.CodeDom.Compiler.TempFileCollection,string&,string&)
Method System.CodeDom.Compiler.Executor:InternalExecWaitWithCapture (string,string,System.CodeDom.Compiler.TempFileCollection,string&,string&) emitted at 0x42060c00 to 0x42061080 (code length 1152) [MyApp.exe]
converting method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:.ctor ()
Method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:.ctor () emitted at 0x42061150 to 0x42061189 (code length 57) [MyApp.exe]
converting method System.Diagnostics.Process:.ctor ()
Method System.Diagnostics.Process:.ctor () emitted at 0x420611a0 to 0x420611b5 (code length 21) [MyApp.exe]
converting method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_StartInfo ()
Method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_StartInfo () emitted at 0x420611c0 to 0x42061222 (code length 98) [MyApp.exe]
converting method System.Diagnostics.Process:get_StartInfo ()
Method System.Diagnostics.Process:get_StartInfo () emitted at 0x42061240 to 0x420612d0 (code length 144) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:.ctor ()
Method System.Diagnostics.ProcessStartInfo:.ctor () emitted at 0x420612e0 to 0x42061302 (code length 34) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:.cctor ()
Method System.Diagnostics.ProcessStartInfo:.cctor () emitted at 0x42061310 to 0x42061338 (code length 40) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_FileName (string)
Method System.Diagnostics.ProcessStartInfo:set_FileName (string) emitted at 0x42061340 to 0x420613a0 (code length 96) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_CreateNoWindow (bool)
Method System.Diagnostics.ProcessStartInfo:set_CreateNoWindow (bool) emitted at 0x420613a0 to 0x420613bf (code length 31) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_UseShellExecute (bool)
Method System.Diagnostics.ProcessStartInfo:set_UseShellExecute (bool) emitted at 0x420613c0 to 0x420613df (code length 31) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_RedirectStandardOutput (bool)
Method System.Diagnostics.ProcessStartInfo:set_RedirectStandardOutput (bool) emitted at 0x420613e0 to 0x420613ff (code length 31) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_RedirectStandardError (bool)
Method System.Diagnostics.ProcessStartInfo:set_RedirectStandardError (bool) emitted at 0x42061400 to 0x4206141f (code length 31) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:set_WorkingDirectory (string)
Method System.Diagnostics.ProcessStartInfo:set_WorkingDirectory (string) emitted at 0x42061420 to 0x42061480 (code length 96) [MyApp.exe]
converting method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start ()
Method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start () emitted at 0x42061480 to 0x420614e2 (code length 98) [MyApp.exe]
converting method System.Diagnostics.Process:Start ()
Method System.Diagnostics.Process:Start () emitted at 0x42061500 to 0x42061555 (code length 85) [MyApp.exe]
converting method System.Diagnostics.Process:Start_common (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process)
Method System.Diagnostics.Process:Start_common (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process) emitted at 0x42061560 to 0x420616d0 (code length 368) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_FileName ()
Method System.Diagnostics.ProcessStartInfo:get_FileName () emitted at 0x42061730 to 0x4206175e (code length 46) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_StandardErrorEncoding ()
Method System.Diagnostics.ProcessStartInfo:get_StandardErrorEncoding () emitted at 0x42061760 to 0x42061774 (code length 20) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_StandardOutputEncoding ()
Method System.Diagnostics.ProcessStartInfo:get_StandardOutputEncoding () emitted at 0x42061780 to 0x42061794 (code length 20) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_UseShellExecute ()
Method System.Diagnostics.ProcessStartInfo:get_UseShellExecute () emitted at 0x420617a0 to 0x420617b4 (code length 20) [MyApp.exe]
converting method System.Diagnostics.Process:Start_noshell (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process)
Method System.Diagnostics.Process:Start_noshell (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process) emitted at 0x420617c0 to 0x420630d8 (code length 6424) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_HaveEnvVars ()
Method System.Diagnostics.ProcessStartInfo:get_HaveEnvVars () emitted at 0x420631c0 to 0x420631e9 (code length 41) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_RedirectStandardInput ()
Method System.Diagnostics.ProcessStartInfo:get_RedirectStandardInput () emitted at 0x420631f0 to 0x42063204 (code length 20) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_RedirectStandardOutput ()
Method System.Diagnostics.ProcessStartInfo:get_RedirectStandardOutput () emitted at 0x42063210 to 0x42063224 (code length 20) [MyApp.exe]
converting method System.Diagnostics.Process:get_IsWindows ()
Method System.Diagnostics.Process:get_IsWindows () emitted at 0x42063230 to 0x4206327a (code length 74) [MyApp.exe]
converting method (wrapper managed-to-native) System.IO.MonoIO:CreatePipe (intptr&,intptr&)
Method (wrapper managed-to-native) System.IO.MonoIO:CreatePipe (intptr&,intptr&) emitted at 0x42063280 to 0x4206330d (code length 141) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_RedirectStandardError ()
Method System.Diagnostics.ProcessStartInfo:get_RedirectStandardError () emitted at 0x42063310 to 0x42063324 (code length 20) [MyApp.exe]
converting method System.Diagnostics.Process:FillUserInfo (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&)
Method System.Diagnostics.Process:FillUserInfo (System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&) emitted at 0x42063330 to 0x42063468 (code length 312) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_UserName ()
Method System.Diagnostics.ProcessStartInfo:get_UserName () emitted at 0x42063490 to 0x420634be (code length 46) [MyApp.exe]
converting method (wrapper managed-to-native) System.Diagnostics.Process:CreateProcess_internal (System.Diagnostics.ProcessStartInfo,intptr,intptr,intptr,System.Diagnostics.Process/ProcInfo&)
Method (wrapper managed-to-native) System.Diagnostics.Process:CreateProcess_internal (System.Diagnostics.ProcessStartInfo,intptr,intptr,intptr,System.Diagnostics.Process/ProcInfo&) emitted at 0x420634c0 to 0x42063570 (code at System.Diagnostics.Process.get_ExitCode () [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ExitCode ()
at System.CodeDom.Compiler.Executor.InternalExecWaitWithCapture (System.String cmd, System.String currentDir, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.Executor.ExecWaitWithCapture (System.String cmd, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.Compile (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames, Boolean keepFiles) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.FromSourceBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] sources) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.CodeCompiler.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] sources) [0x00000] in <filename unknown>:0
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource (System.CodeDom.Compiler.CompilerParameters options, System.String[] sources) [0x00000] in <filename unknown>:0
at com.example.myapp.ScriptEngine.compile () [0x00000] in <filename unknown>:0
length 176) [MyApp.exe]
converting method (wrapper managed-to-native) object:__icall_wrapper_mono_helper_ldstr (intptr,intptr)
Method (wrapper managed-to-native) object:__icall_wrapper_mono_helper_ldstr (intptr,intptr) emitted at 0x42063570 to 0x420635f9 (code length 137) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_Arguments ()
Method System.Diagnostics.ProcessStartInfo:get_Arguments () emitted at 0x42063600 to 0x4206362e (code length 46) [MyApp.exe]
converting method System.Diagnostics.ProcessStartInfo:get_WorkingDirectory ()
Method System.Diagnostics.ProcessStartInfo:get_WorkingDirectory () emitted at 0x42063630 to 0x4206365e (code length 46) [MyApp.exe]
converting method (wrapper managed-to-native) System.ComponentModel.Win32Exception:W32ErrorMessage (int)
Method (wrapper managed-to-native) System.ComponentModel.Win32Exception:W32ErrorMessage (int) emitted at 0x42063660 to 0x420636e1 (code length 129) [MyApp.exe]
converting method System.ComponentModel.Win32Exception:.ctor (int,string)
Method System.ComponentModel.Win32Exception:.ctor (int,string) emitted at 0x420636f0 to 0x42063727 (code length 55) [MyApp.exe]
converting method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ExitCode ()
Method (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ExitCode () emitted at 0x42063740 to 0x420637a2 (code length 98) [MyApp.exe]
converting method System.Diagnostics.Process:get_ExitCode ()
Method System.Diagnostics.Process:get_ExitCode () emitted at 0x420637c0 to 0x42063864 (code length 164) [MyApp.exe]
converting method (wrapper managed-to-native) System.Diagnostics.StackTrace:get_trace (System.Exception,int,bool)
Method (wrapper managed-to-native) System.Diagnostics.StackTrace:get_trace (System.Exception,int,bool) emitted at 0x42063890 to 0x42063924 (code length 148) [MyApp.exe]
在我看来,是时候尝试新事物了。然后我改变了我的代码如下:
#if LINUX
bool writeOk = true;
string tmpScriptName = String.Format("/tmp/com.myapp.script-{0}.js", Environment.TickCount);
try {
File.WriteAllText(tmpScriptName, scriptCode);
} catch (Exception) {
writeOk = false;
} finally {
if (writeOk) {
result = compiler.CompileAssemblyFromFile(parameters, tmpScriptName);
try {
File.Delete(tmpScriptName);
} catch (Exception) { }
}
}
#else
result = compiler.CompileAssemblyFromSource(parameters, scriptCode);
#endif
幸运的是,它又有效了。