Linux下Wine运行C# .NET应用调用命令报错但直接调用正常
错误原因
- 二者的参数解析逻辑存在本质差异:
- 你在Linux终端直接执行
wine cmd /c /bin/gnome-terminal -- sh -e /bin/MyScripts/script.sh时,Linux shell会先完成参数拆分,将/c和后续整串命令作为两个独立参数传递给Wine的cmd程序,cmd可以正常拆分识别可执行文件和后续参数。 - 当你在.NET代码中通过
ProcessStartInfo.Arguments传递参数时,整段字符串会原封不动传递给cmd。而Windows cmd(包括Wine实现的cmd)的/C参数解析规则为:如果/C后的内容没有被外层双引号包裹,cmd会将/C后的整段内容识别为单个可执行文件路径去搜索,因此抛出你遇到的报错,认为整串/bin/gnome-terminal -- sh -e /bin/MyScripts/script.sh是不存在的程序。
- 你在Linux终端直接执行
- 部分Wine版本中,Wine内部运行的程序继承的环境变量与终端直接启动Wine时的环境变量存在差异,也可能加剧路径识别异常,但该场景下的报错根因是参数解析规则问题。
修复方案
方案1:移除cmd中转,直接调用Linux原生程序(最推荐)
Wine原生支持Windows程序直接调用Linux宿主的可执行文件,不需要通过cmd中转,修改后代码如下:
System.Diagnostics.Process process = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.FileName = "/bin/gnome-terminal"; startInfo.Arguments = "-- sh -e /bin/MyScripts/script.sh"; process.StartInfo = startInfo; process.Start();
该方案没有多余中转层,兼容性和执行效率最高。
方案2:修正cmd调用的引号规则
如果有必须使用cmd中转的场景(比如需要连带执行Windows侧命令),只需要给/C后的整段命令添加外层双引号即可,注意C#字符串中需要转义双引号:
System.Diagnostics.Process process = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.FileName = "cmd"; startInfo.Arguments = "/C \"\"/bin/gnome-terminal -- sh -e /bin/MyScripts/script.sh\"\""; process.StartInfo = startInfo; process.Start();
此处两层双引号是适配cmd的/C参数规则:当命令内容包含空格时,外层包裹的双引号会被cmd自动剥离,再执行内部的命令逻辑。
修改代码重新编译后,使用wine Application.exe启动即可正常执行目标脚本。
内容的提问来源于stack exchange,提问作者Shantanu Shinde
相关产品推荐
相关产品推荐

