简体   繁体   中英

Which .NET exception should I use for signaling external application failure?

I'm new to using C# and .NET, but I want to try to play nice and re-use system components.

In the code I'm maintaining, there are several instances where we run external tools and applications, which looks something like this:

using (var Setup = Process.Start(SetupInfo) )
{
    Setup.WaitForExit(SetupTimeout);
    if (!Setup.HasExited )
        throw new TimeoutException(
            "Setup did not complete within the expected time");
}

I'm trying to add validation of the exit codes as well for those external tools that have well-defined exit codes, ie something like this inside the 'using' block:

switch ( Setup.ExitCode )
{
    case 0: 
        break;
    case 1: 
        throw new SetupFailedException("Setup execution failed");
    case 2: 
        throw new SetupFileNotFound("Setup did not find required files");
    default: 
        throw new ExternalErrorException("Setup failed for some other reason");
}

...where the first two would derive from the generic 'ExternalErrorException'. But is there some existing generic exception I could re-use for this, ie to signal that an external process has failed to run as expected, rather than invent my own?

I don't think there is one you could reuse.

I think throwing your own exceptions has more value, it allows you to be specific. Your base exception usage is something I like to do too.

Throwing a dedicated exception type only makes sense if there is code somewhere up the call stack that is going to catch the exception and deal with the failure. Dealing with a gross error like this is quite difficult, you have no idea why the setup program is misbehaving like this.

Which makes it very likely that there is little point in continuing to execute code, things just go downhill from there. After all, an essential program didn't get installed, it is quite liable to throw more exceptions when you try to use it. Now without a good explanation why it failed, the true reason was that the installer didn't work.

Or, if this is just an auxiliary operation that doesn't otherwise affect your main program, needs to be reported to the user so she can contact IT support to figure out a way around the problem.

Neither of which requires a dedicated set of exception types. Only catch exceptions that you know how to recover from.

Why are you throwing exceptions? From what you are saying, it seems you have specific logic that needs to be performed based on the results of the setup. An Exception is not the way to signal business logic. If anything, I'd have an enumeration that corresponds to the exit codes which can then be checked.

If you really have a need to trash the stack and have an Exception bubble all the way up, you can have your method return a value from the enumeration, and then have a wrapper method which would take the value and then map to an Exception which should be thrown.

Ultimately, if you feel that using a custom Exception is the right way to go, then you should not have a deep Exception hierarchy . Rather, you would derive from Exception directly.

As someone else has already questioned your motives I shall not do so. I like you often feel compelled to reuse .NET exceptions as that is what feels the most OOP but that is sometimes an excuse because I might be being lazy.

There's a lot of people that would state that the more verbose your exception is then the better it may be for consuming applications/developers of your code especially if you comment your exception class fully.

As Hans mentioned , it doesn't make much sense here to create custom exception types for each case since the calling code is unlikely to act upon the different result cases. I would go even farther and avoid the use of even a single custom exception type if possible.

Personally, I would use System.Runtime.InteropServices.ExternalException for all cases, and simply add the failure reason (when available based on the exit code and/or other data) to the exception message. If you ever need to add subclasses for specific cases, these can derive from ExternalException instead of a custom type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM