What is the best way to handle a specific Win32 Exception like “application not found”?

前端 未结 2 1759
野的像风
野的像风 2021-01-26 07:58

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

相关标签:
2条回答
  • 2021-01-26 08:14

    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-4441e69c548a
      • They're exposed as Exception.HResult.
      • Note that Exception.HResult has a default value of -2146233088 (0x80131500)
    • Win32 error codes:

      • 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 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

      • These are chiefly exposed via COMException in the COMException.HResult property.
      • However some places in .NET will throw a 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 Win32Exceptions 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." );
    }
    
    0 讨论(0)
  • 2021-01-26 08:25

    Win32Exception has a property called ErrorCode, that returns the error HRESULT. With this, you can properly classify your exception, according to this link here.

    0 讨论(0)
提交回复
热议问题