首页 > 解决方案 > 处理特定 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
            }
        }

标签: c#.netexceptionwin32exception

解决方案


Win32Exception您可能需要检查两者 Win32Exception.NativeErrorCode及其继承的ExternalException.ErrorCode值。

C# 6 引入了异常过滤器,如果您打算重新抛出异常,则允许您选择处理异常而无需过早地倒回堆栈。

Windows 中有三种主要类型的错误代码:HRESULT、Win32 错误代码和 COM 错误代码。


关于您的问题:“找不到应用程序”错误消息来自 COM:CO_E_APPNOTFOUND并且是0x800401F5- 但奇怪的是它是在 aWin32Exception而不是 a中返回的COMException

有趣的是 .NET Framework(我还没有检查过 .NET Core)总是同时Process.Start抛出和分支Win32ExceptionUseShellExecute == truefalse。但是当UseShellExecute == true使用 COM 时,COM 错误只是简单地传递到Win32Exceptions 构造函数中,它只是神奇地工作(因为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." );
}

推荐阅读