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 ca
With Win32Exception
you may need to check both Win32Exception.NativeErrorCode
and its inherited ExternalException.ErrorCode
values.
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.
There are three main types of error-codes in Windows: HRESULT, Win32 Error Codes, and COM error codes.
HRESULT
:
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-4441e69c548aException.HResult
.Exception.HResult
has a default value of -2146233088
(0x80131500
)Win32 error codes:
Win32Exception
in the Win32Exception.NativeErrorCode
property.COM error codes are listed on this page: https://docs.microsoft.com/en-us/windows/win32/com/com-error-codes-1
COMException
in the COMException.HResult
property.Win32Exception
instead of a COMException
, and the Win32Exception.NativeErrorCode
will contain the COM error code instead of a Win32 error code.
Process.Start()
is one such example. This is explained below.COMException
is also used for SEH (Structured Exception Handling), but normally you won't encounter that in .NET.On to your question: The "Application not found" error message is from COM: CO_E_APPNOTFOUND
and is 0x800401F5
- but curiously it's returned in a Win32Exception
rather than a COMException
.
What's interesting is that the .NET Framework (I haven't checked .NET Core), Process.Start always throws Win32Exception for both the UseShellExecute == true and false branches. But when UseShellExecute == true
then COM is used, so the COM error is simply passed-into Win32Exception
s constructor and it just magically works (because Win32Exception
calls FormatMessage
to get the human-readable error message from the error-code, and FormatMessage
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." );
}
Win32Exception
has a property called ErrorCode
, that returns the error HRESULT
. With this, you can properly classify your exception, according to this link here.