问题描述
我使用文件类型的默认应用程序启动了一个进程,但是如果用户删除了其默认应用程序,则会引发Win32Exception.此外,在其他情况下会引发Win32Exception,例如如果用户无权打开默认应用程序.
I start a process with the default application for the file type, but if the user has deleted his default application, a Win32Exception is thrown. In addition there are other cases when a Win32Exception is thrown e.g. if the user has no rights to open the default application.
现在,我正在寻找区分异常的最佳方法.
Now I'm looking for the best way to seperate between the exceptions.
我如何检查到底抛出了哪个异常?是通过异常消息检查它的唯一方法吗?
How can i check which exception exactly is thrown? Is the only way to check it by its Exception message?
我正在这样捕捉它:
try
{
process.Start();
}
catch (Win32Exception exc)
{
//How to check which exception exactly is thrown?
return return string.Format("Process cannot be started", exc.Message)
}
这是我首先想到的,但是我认为有一种更好的方法可以完成此任务:
This was mit first idea but i think there is a better way to accomplish this task:
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
值.
With Win32Exception
you may need to check both Win32Exception.NativeErrorCode
and its inherited ExternalException.ErrorCode
values.
C#6引入了异常过滤器,如果您打算重新引发异常,则允许您选择处理异常,而无需提前回退堆栈.
C# 6 introduces exception filters which allow you to opt-in to handling an exception without needing to rewind the stack prematurely if you intend to re-throw the exception.
Windows中的错误代码主要有三种类型:HRESULT,Win32错误代码和COM错误代码.
There are three main types of error-codes in Windows: HRESULT, Win32 Error Codes, and COM error codes.
-
HRESULT
:
-
HRESULT
值实际上是自我描述的位域,其格式记录在这里: https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a - 它们公开为
Exception.HResult
. - 请注意,
Exception.HResult
的默认值为-2146233088
(0x80131500
)
HRESULT
values are actually self-describing bit-fields and the format is documented here: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a- They're exposed as
Exception.HResult
. - Note that
Exception.HResult
has a default value of-2146233088
(0x80131500
)
Win32错误代码:
Win32 error codes:
- 这些内容在此页上列出: https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d?redirectedfrom=MSDN
- 它们仅在
Win32Exception.NativeErrorCode
属性中的Win32Exception
上公开.
- These are listed on this page: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d?redirectedfrom=MSDN
- They're exposed only on
Win32Exception
in theWin32Exception.NativeErrorCode
property.
COM错误代码在此页面上列出: https://docs.microsoft.com/zh-cn/windows/win32/com/com-error-codes-1
COM error codes are listed on this page: https://docs.microsoft.com/en-us/windows/win32/com/com-error-codes-1
- 这些主要通过
COMException.HResult
属性中的COMException
公开. - 但是,.NET中的某些位置将引发
Win32Exception
而不是COMException
,并且Win32Exception.NativeErrorCode
将包含COM错误代码而不是Win32错误代码.-
Process.Start()
就是这样一个例子.下面对此进行了说明.
- These are chiefly exposed via
COMException
in theCOMException.HResult
property. - However some places in .NET will throw a
Win32Exception
instead of aCOMException
, and theWin32Exception.NativeErrorCode
will contain the COM error code instead of a Win32 error code.Process.Start()
is one such example. This is explained below.
关于您的问题:未找到应用程序"错误消息来自COM:
CO_E_APPNOTFOUND
且为0x800401F5
-但奇怪的是,它是在Win32Exception
而不是COMException
中返回的.On to your question: The "Application not found" error message is from COM:
CO_E_APPNOTFOUND
and is0x800401F5
- but curiously it's returned in aWin32Exception
rather than aCOMException
.有趣的是,.NET Framework(我尚未检查.NET Core),
Process.Start
对于UseShellExecute == true
和false
分支总是会抛出Win32Exception
.但是,当使用UseShellExecute == true
时使用COM,因此COM错误只是传递到Win32Exception
的构造函数中,并且可以神奇地起作用(因为Win32Exception
调用FormatMessage
可以从错误中获取人类可读的错误消息-代码,并且FormatMessage
支持返回Win32,HRESULT和COM状态代码的错误消息(因为它们通常不重叠).What's interesting is that the .NET Framework (I haven't checked .NET Core),
Process.Start
always throwsWin32Exception
for both theUseShellExecute == true
andfalse
branches. But whenUseShellExecute == true
then COM is used, so the COM error is simply passed-intoWin32Exception
s constructor and it just magically works (becauseWin32Exception
callsFormatMessage
to get the human-readable error message from the error-code, andFormatMessage
supports returning error-messages for Win32, HRESULT and COM status codes (as they generally don't overlap)....这意味着我们只需要这样做:
...which means we just need to do this:
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." ); }
这篇关于处理特定的Win32异常(例如“未找到应用程序")的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
-