What is the best way to handle a specific Win32 Exception like "application not found"?
Asked Answered
P

2

3

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?

I'm catching it like this:

        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
            }
        }
Pamela answered 21/12, 2018 at 9:47 Comment(1)
Using the message is a bad idea because it will change depending on the locale of the user. Instead, you should use the NativeErrorCode property of the exceptionDulciedulcify
V
2

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.


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." );
}
Vibration answered 5/9, 2020 at 7:37 Comment(1)
C# 6 introduced the exception filters, not 7.x.Newbold
R
0

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

Referendum answered 21/12, 2018 at 10:12 Comment(1)
Check Win32Exception.NativeErrorCode as well, as certain errors like COM errors all have the same ErrorCode but have different NativeErrorCode values (especially when ErrorCode == -2147467259).Vibration

© 2022 - 2024 — McMap. All rights reserved.