1

In my C# code I have roughly this:

    public void RunCommand()
    {
        var processStartInfo = new ProcessStartInfo(
            "notepad.exe")
        {
            UseShellExecute = true,
            Verb = "Runas",
        };
        var process = Process.Start(processStartInfo);
        process.WaitForExit(1000);
    }

When run, this prompts the user to grant elevated privileges. If the user refuses, the call throws a Win32Exception with the text "The operation was cancelled by the user".

I want to catch this exception specifically, i.e., tell it apart from other exceptions. I want to be able to know that the user has cancelled.

Can I be reasonably confident that when a Win32Exception is thrown, it is probably this? Or can the call throw Win32Exception for all sorts of other reasons? I don't want to start string matching on the error message, since that presumably varies depending on user settings...

Claus Appel
  • 379
  • 1
  • 4
  • 13
  • It seems you have already tried it. Why should the exception type change? If it fails, does it really matter why it failed? I could think of other problems like FileNotFound, if `notepad.exe` is not available. – Thomas Weller Jan 21 '20 at 09:48
  • I don't expect the exception type to _change_, but I expect that this call might throw **Win32Exception** for all sorts of other reasons. So if I catch **Win32Exception**, I'm not confident that it was due to user cancellation. – Claus Appel Jan 21 '20 at 09:50
  • 1
    Check if the `Win32Exception.ErrorCode` is 1223 to be sure. – Matthew Watson Jan 21 '20 at 09:57
  • [Process.Start never returns when UAC denied](https://stackoverflow.com/q/23350175/7444103) – Jimi Jan 21 '20 at 10:00
  • _"Check if the Win32Exception.ErrorCode is 1223 to be sure."_ - See also 0x0...4C7 (1223 in Hex) in [Win32 Error Codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d) – Fildor Jan 21 '20 at 10:02
  • In my case I get error code -2147467259. – Claus Appel Jan 21 '20 at 10:03
  • That's the generic (`0x80004005`) *Access denied* exception (`HRESULT`). – Jimi Jan 21 '20 at 10:06
  • What is the difference between 1223 and -2147467259? Do both of them indicate that the application failed to get elevated permissions? – Claus Appel Jan 21 '20 at 10:10
  • The error codes are documented [here](https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes). `1223` is ERROR_CANCELLED. – Matthew Watson Jan 21 '20 at 10:15
  • 1
    There's a macro to map a Win32 error to a `HRESULT`. It's probably in the documentation already linked (if you're interested) – Jimi Jan 21 '20 at 10:44

1 Answers1

1

I ended up doing this, which seems to work on my system:

    public void RunCommand()
    {
        var processStartInfo = new ProcessStartInfo(
            "notepad.exe")
        {
            UseShellExecute = true,
            Verb = "Runas",
        };
        var process = Process.Start(processStartInfo);
        process.WaitForExit(1000);
    }
    catch (Win32Exception e)
    {
        if (e.ErrorCode == 1223 || e.ErrorCode == -2147467259)
            // Throw easily recognizable custom exception.
            throw new ElevatedPermissionsDeniedException("Unable to get elevated privileges", e);
        else
            throw;
    }
Claus Appel
  • 379
  • 1
  • 4
  • 13