前言
偶然发现,如果想用如下代码在 .NET 6 中打开指定 URL:
Process.Start("https://baidu.com");
会引发异常:
而同样的代码在 .NET Framework 中是可以正常执行的。
难道,.NET 6 下的实现逻辑不一样?
深入探究
通过调用堆栈,我们发现最后调用的是StartWithCreateProcess
方法:
对应的 .NET 6 源代码如下:
private bool StartCore(ProcessStartInfo startInfo)
{if (!startInfo.UseShellExecute){return this.StartWithCreateProcess(startInfo);}return this.StartWithShellExecuteEx(startInfo);
}
这和 .NET Framework 中的实现逻辑基本一致:
public bool Start()
{this.Close();ProcessStartInfo processStartInfo = this.StartInfo;if (processStartInfo.FileName.Length == 0){throw new InvalidOperationException(SR.GetString("FileNameMissing"));}if (processStartInfo.UseShellExecute){return this.StartWithShellExecuteEx(processStartInfo);}return this.StartWithCreateProcess(processStartInfo);
}
那么问题出在哪呢?
通过 dnspy 调试 .NET Framework 版本的测试程序,我们发现,最后执行的是StartWithShellExecuteEx
而不是StartWithCreateProcess方法:
而之所以走不同的逻辑分支,是由processStartInfo.UseShellExecute
控制的。
所以,解决方案也很简单,设置UseShellExecute = true
:
Process.Start(new ProcessStartInfo("https://baidu.com") { UseShellExecute = true });
结论
造成这样的原因,是因为UseShellExecute
在 .NET 6 上默认为 false:
public bool UseShellExecute { get; set; }
而在 .NET Framework 上默认为 true:
[DefaultValue(true)]
[MonitoringDescription("ProcessUseShellExecute")]
[NotifyParentProperty(true)]
public bool UseShellExecute
{get{return this.useShellExecute;}set{this.useShellExecute = value;}
}private bool useShellExecute = true;
当UseShellExecute = false
时,代码会将传入参数作为文件名使用,从而引发“系统找不到指定的文件”异常。
添加微信号【MyIO666】,邀你加入技术交流群