前言
偶然發現,如果想用如下代碼在 .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】,邀你加入技術交流群