Command Line Patterns or Best Practices?

mskeel

Senior Contributor
Joined
Oct 30, 2003
Messages
913
I've parsed the command line on a console app a couple of different ways but I'm curious if there is a pattern or "best" way to do it. Physically parsing is easy. I've got a C# implementation of the GetOpt library. It's applying the arguments to the business logic -- setting up the application to run. That is the part I wonder about.

Here is what I generally do:
Code:
Public Class CommandLineApp

    //define these up top so it's easier to change them later
    Private Class DefinedParameters  
        Public Const firstArgLong As String = "arg1"
        //...
    End Class

    Public Sub New()

    End Sub

    Public CommandLinePattern()
       //1. Get the command line parameters -- either passed in or Environment.GetCommandLineArgs()

       //2. Check initial error Conditions for early trouble

       //3. Set up GetOpt

       Try
              //4. Parse command line using GetOpt
          
              //5. Check for early termination scenarios -- user asks for help or version number, improper use of arguments, etc.

              //6. Set up boolean flags or variables for all the parameters that are left that could be good (such as hide banner or output file or configuration type)

              //7. Run the business/meaty part of the app with the flags/variables

       Catch e As ArgumentException
              Console.WriteLine(e.Message)
              ShowHelp()
       End Try
End Function

Here's an example in code to perhaps make things a little more clear. You can ignore this if you want, I'm just including it as an example to supplement some of my statements above.
Visual Basic:
Public Class CommandLineApp

    ''define these up top so it's easier to change them later
    Private Class DefinedParameters  
        Public Const loud As String = "loud"
        Public Const loud2 As String = "l"
        Public Const hidebanner As String = "hidebanner"
        Public Const hidebanner2 As String = "b"
        Public Const version As String = "version"
        Public Const version2 As String = "v"
        Public Const help As String = "help"
        Public Const help2 As String = "h"
        Public Const help3 As String = "?"
    End Class
'
    Public Sub New()
'
    End Sub
'
    'Usage: Appy filename [-l|--loud] [-b|--hidebanner] | [-v|--version] | [--help|-h|-?]
    ''This is called from the static Main() function but could easily BE the Main()
    Public Function Run(ByVal commandLineArgs As String()) As Boolean

        If commandLineArgs.Length = 1 Then  ''you have to either a filename, -v, or -h or the user needs more help
            ShowHelp()
            Return True
        End If

        ''Setting up GetOpt
        Dim commandLineParser As New Heyes.GetOpt(commandLineArgs)

        Dim expectedArgs() As String = {DefinedParameters.loud, DefinedParameters.loud2, _
                                        DefinedParameters.hidebanner, DefinedParameters.hidebanner2, _
                                        DefinedParameters.version, DefinedParameters.version2, _
                                        DefinedParameters.help, DefinedParameters.help2, DefinedParameters.help3}

        Try
            commandLineParser.SetOpts(expectedArgs)
            commandLineParser.Parse()

            ''If there is a request for the version, always honor it
            If commandLineParser.IsDefined(DefinedParameters.version) OrElse commandLineParser.IsDefined(DefinedParameters.version2) Then
                ShowBanner()
                Return True
            End If

            ''if more than one file is attempted, send the user some help
            If commandLineParser.Args.Count > 2 Then ''1 or 0 files is alright.  Remember, the exe is the first arg
                Console.WriteLine("Only one file may be specified at a time.")
                ShowHelp()
                Return True 'ditch out, becuase you failed
            End If

            ''no matter what, if the user wants help, give it to them, unless they want the version which I took care of above and ditched out
            If commandLineParser.IsDefined(DefinedParameters.help) OrElse _
               commandLineParser.IsDefined(DefinedParameters.help2) OrElse _
               commandLineParser.IsDefined(DefinedParameters.help3) Then

                ShowHelp()
                Return True ''ditch out, we gave them their help.
            End If

            If commandLineParser.IsDefined(DefinedParameters.loud) AndAlso commandLineParser.IsDefined(DefinedParameters.loud2) Then
                Console.WriteLine("Options cannot be specified more than once")
                Console.WriteLine("Paramater name: " + DefinedParameters.loud + ", " + DefinedParameters.loud2)
                ShowHelp()
                Return True
            End If

            If commandLineParser.IsDefined(DefinedParameters.hidebanner) AndAlso commandLineParser.IsDefined(DefinedParameters.hidebanner2) Then
                Console.WriteLine("Options cannot be specified more than once")
                Console.WriteLine("Paramater name: " + DefinedParameters.hidebanner + ", " + DefinedParameters.hidebanner2)
                ShowHelp()
                Return True
            End If

            ''define the arguments we have that aren't a help or version
            Dim hideBanner As Boolean = False

            If commandLineParser.IsDefined(DefinedParameters.loud) OrElse commandLineParser.IsDefined(DefinedParameters.loud2) Then
                Me._loud = True
            End If

            If commandLineParser.IsDefined(DefinedParameters.hidebanner) OrElse commandLineParser.IsDefined(DefinedParameters.hidebanner2) Then
                hideBanner = True
            End If

            ''Now down to business
            Execute(commandLineParser.Args(1), hideBanner)
            Return True

        Catch e As ArgumentException
            Console.WriteLine(e.Message)
            ShowHelp()
            Return True
        End Try
End Function

What do you do? Is there a good pattern to use or any general concepts that work particularly well? As I've said, what I do works, it just feels kind of clunky. I'm just curious what other developers are doing with regards to command line interfaces.
 
Back
Top