c# - 处理特定 Win32 异常(如“找不到应用程序”)的最佳方法是什么?
问题描述
我使用文件类型的默认应用程序启动一个进程,但如果用户删除了他的默认应用程序,则会引发 Win32Exception。此外,还有其他情况会引发 Win32Exception,例如,如果用户无权打开默认应用程序。
现在我正在寻找区分异常的最佳方法。
我如何检查究竟抛出了哪个异常?是通过异常消息检查它的唯一方法吗?
我像这样抓住它:
try
{
process.Start();
}
catch (Win32Exception exc)
{
//How to check which exception exactly is thrown?
return return string.Format("Process cannot be started", exc.Message)
}
这是第一个想法,但我认为有更好的方法来完成这项任务:
catch (Win32Exception exc)
{
if(exc.Message == "Application not found")
{
//Do something
}
else if(exc.Message == "Another exception")
{
//Do something else
}
}
解决方案
Win32Exception
您可能需要检查两者 Win32Exception.NativeErrorCode
及其继承的ExternalException.ErrorCode
值。
C# 6 引入了异常过滤器,如果您打算重新抛出异常,则允许您选择处理异常而无需过早地倒回堆栈。
Windows 中有三种主要类型的错误代码:HRESULT、Win32 错误代码和 COM 错误代码。
HRESULT
:HRESULT
值实际上是自描述位字段,格式记录在这里:https ://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a- 它们被暴露为
Exception.HResult
. - 请注意,
Exception.HResult
默认值为-2146233088
(0x80131500
)
Win32错误代码:
- 这些列在此页面上:https ://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d?redirectedfrom=MSDN
- 他们只暴露
Win32Exception
在Win32Exception.NativeErrorCode
财产上。
本页列出了 COM 错误代码:https ://docs.microsoft.com/en-us/windows/win32/com/com-error-codes-1
- 这些主要通过属性暴露
COMException
出来。COMException.HResult
- 但是 .NET 中的某些地方会抛出 a
Win32Exception
而不是 aCOMException
,并且Win32Exception.NativeErrorCode
将包含 COM 错误代码而不是 Win32 错误代码。Process.Start()
就是这样一个例子。这在下面解释。
COMException
也用于 SEH(结构化异常处理),但通常在 .NET 中不会遇到这种情况。
- 这些主要通过属性暴露
关于您的问题:“找不到应用程序”错误消息来自 COM:CO_E_APPNOTFOUND
并且是0x800401F5
- 但奇怪的是它是在 aWin32Exception
而不是 a中返回的COMException
。
有趣的是 .NET Framework(我还没有检查过 .NET Core)总是同时Process.Start
抛出和分支Win32Exception
UseShellExecute == true
false
。但是当UseShellExecute == true
使用 COM 时,COM 错误只是简单地传递到Win32Exception
s 构造函数中,它只是神奇地工作(因为Win32Exception
调用FormatMessage
从错误代码中获取人类可读的错误消息,并FormatMessage
支持返回 Win32、HRESULT 的错误消息和 COM 状态代码(因为它们通常不重叠)。
...这意味着我们只需要这样做:
const Int32 CO_E_APPNOTFOUND = unchecked( (Int32) 0x800401F5 );
try
{
ProcessStartInfo psi = new ProcessStartInfo( "https://www.stackoverflow.com" );
psi.UseShellExecute = true;
psi.Verb = "open";
using( Process p = Process.Start( psi ) )
{
p.WaitForExit();
}
}
catch( Win32Exception w32Ex ) when ( w32Ex.NativeErrorCode == CO_E_APPNOTFOUND )
{
MessageBox.Show( "You don't have a web-browser installed or configured correctly." );
}
推荐阅读
- javascript - 单击后的引导下拉菜单未显示下拉值
- java-8 - 过滤具有多个条件的列表
- javascript - 通过 WASM 构建新的 Rust Vec 时,JavaScript ArrayBuffer “分离”
- javascript - 从键和值是动态的数组中搜索字符串
- jboss - 安装wildfly错误:服务失败
- calabash - 为什么我得到未初始化的常量 Calabash::ABase (NameError)?
- java - 使用 volley 将用户名和密码发布到 php,将返回的 json 数组解析为共享首选项
- ios - 没有找到合适的申请记录。验证您的捆绑标识符是否正确,一切都正确
- docker - 将 Source+Binary Docker 映像转换为仅二进制 Docker 映像
- git - 如何从git忽略的文件夹中删除git-repo中的文件