Search code examples
c++exceptionboostcommand-line

Exiting gracefully when running an invalid command c++


I'm using boost for running commandline commands from my application. I am using the following piece of code that I've encapsulated into a helper function:

tuple<string, int> Utility::RunCommand(const string& arguments) const
{
    string response;
    int exitCode;
    try
    {
        ipstream iStream;
        auto childProcess = child(arguments, std_out > iStream);
        string line;

        while (getline(iStream, line) && !line.empty())
        {
            response += line;
        }

        childProcess.wait();
        exitCode = childProcess.exit_code();
    }
    catch (...)
    {
        // log error
        throw;
    }

    return make_tuple(response, exitCode);
}

Now I have a command which only runs on machines with certain properties. This method returns the expected response and error code on those machines. On other machines, it throws an exception.

I've tried running the command manually on a machine where it's supposed to fail and it returns the following output:

POWERSHELL
PS C:\Users\xyz> dummy-cmd
dummy-cmd : The term 'dummy-cmd' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ dummy-cmd
+ ~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (dummy-cmd:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

COMMAND PROMPT
C:\Users\xyz>dummy-cmd
'dummy-cmd' is not recognized as an internal or external command,
operable program or batch file.

How can I make it run such that it returns a non-zero error code rather than throwing an exception?


Solution

  • That's what your catch clause is for, to handle exceptions. It doesn't have to rethrow them:

    tuple<string, int> Utility::RunCommand(const string& arguments) const
    {
        string response;
        int exitCode;
        try
        {
            ipstream iStream;
            auto childProcess = child(arguments, std_out > iStream);
            string line;
    
            while (getline(iStream, line) && !line.empty())
            {
                response += line;
            }
    
            childProcess.wait();
            exitCode = childProcess.exit_code();
        }
        catch (PlatformNotSupportedException& e)
        {
            std::cerr << "That operation is not supported on this platform." << std::endl;
            exit(1);
        }
        catch (...)
        {
            std::cerr << "Unspecified error occurred." << std::endl;
            exit(1); // give nonzero exit code
            //throw; // take out this
        }
    
        return make_tuple(response, exitCode);
    }