Commands in CommandConsoleFramework

Commands are implemented through methods on modules and classes. Any method with the correct signature and attribute(s) can be registered as a command within the framework. When a user types into the console and presses 'enter', the first word of the line is matched against the name of each registered command method. If a matching method name is found, that method is executed and passed a CommandLine object which contains information about, and helper routines for working with, the command line string entered by the user.

Command Attributes

There are two method attributes provided by the framework: the CommandMethod and the CommandMethodArgument. Every command method must be decorated with the CommandMethod attribute. If the command requires additional parameters, then information about those parameters can be specified using optional CommandMethodArgument attributes. The optional information is used by the default help system to generate the help text for the console command.

You can also specify an array of alternate names for a command using the appropriate overload of the CommandMethod attribute. The command interpreter will automatically map any alternate name to the associated method. Note however that two methods cannot have the same alternate name; that is, all combined command method names and alternate names must be unique.

Example - The "Help" Command Declaration Supporting "?"

    <CommandMethod("Displays available commands, or info on a specific command.", "Follow help with a command name to get help for the specific command (if available).", "?")>
    <CommandMethodArgument("CommandName", 0, "(Optional) Displays help for the specified command, if available.")>
    Public Overridable Sub Help(line As CommandLine)
        ....
    End Sub

Command Method Signature

The signature for a command method is a simple sub routine that takes a single CommandLine parameter, and has the CommandMethod attribute.
<CommandMethod()>
Public Sub SomeCommand(line As CommandLine)

End Sub

Overloads of the CommandMethod constructor allow you to add help information for the command. The Description is displayed in the full help list, and the FormattedHelpText is the "extended help" displayed when detailed help is requested for the command. The FormattedHelpText value supports the framework's output formatting.

Registering Commands

When the CommandInterpreter first runs, it will automatically discover command methods on any type defined in the executing assembly that is a sealed class with no public constructor (or a module), if those methods are shared.

You can also manually register commands prior to calling CommandInterpreter.Run by using the RegisterMethod() or RegisterObject() methods on CommandInterpreter.Registration.

Manual Command Method Registration Example

Imports CommandConsoleFramework

Module Module1
    Sub Main()
        CommandInterpreter.Registration.RegisterMethod(AddressOf SomeCommand)
        CommandInterpreter.Run()
    End Sub

    Public Sub SomeCommand(line As CommandLine)
        line.SetResultMessage("Some command executed!")
    End Sub
End Module

Example File System Commands Class

Public NotInheritable Class FileSystemCommands

    Protected Sub New()
    End Sub

    <CommandMethod("Displays the contents of a directory.")>
    <CommandMethodArgument("Directory", "The path of the directory to enumerate")>
    Public Shared Sub Dir(line As CommandLine)
        Dim path As String = line.ArgumentString.Trim
        If System.IO.Directory.Exists(path) Then
            Try
                ConsoleOutput.WriteColored(ConsoleColor.DarkYellow, True, "Contents of {0}", path)
                Dim directoryNames() As String = System.IO.Directory.GetDirectories(path)
                Dim fileNames() As String = System.IO.Directory.GetFiles(path)
                For Each name As String In directoryNames
                    Dim info As New System.IO.DirectoryInfo(name)
                    ConsoleOutput.WriteIndented(3, True, "{0} [{1}]", info.Name, info.LastWriteTime)
                Next
                For Each name As String In fileNames
                    Dim info As New System.IO.FileInfo(name)
                    ConsoleOutput.WriteIndented(3, True, "{0} {1} bytes [{2}]", info.Name, info.Length, info.LastWriteTime)
                Next
                ConsoleOutput.WriteColored(ConsoleColor.DarkYellow, True, "{0} Directories", directoryNames.Length)
                ConsoleOutput.WriteColored(ConsoleColor.DarkYellow, True, "{0} Files", fileNames.Length)
            Catch ex As Exception
                line.SetResultMessage("Error enumerating directory. This may be due to an invalid relative path.", True)
            End Try

        Else
            line.SetResultMessage("Invalid Directory", True)
        End If
    End Sub

    <CommandMethod("Displays detailed information about a file or directory.")>
    <CommandMethodArgument("Path", "The path of the file or directory to view")>
    Public Shared Sub FileInfo(line As CommandLine)
        Dim dirName As String = line.ArgumentString.Trim()
        If System.IO.Directory.Exists(dirName) Then
            Dim info As New System.IO.DirectoryInfo(dirName)
            ConsoleOutput.WriteFormatted("\[r3]\[c6]Name: \[c16]{0}\[n]\[r3]\[c6]Extension: \[c16]{8}\[n]\[r3]\[c6]Full Name: \[c16]{1}\[n]\[r3]\[c6]Parent: \[c16]{2}\[n]\[r3]\[c6]Root: \[c16]{3}\[n]\[r3]\[c6]Attributes: \[c16]{4}\[n]\[r3]\[c6]Creation Time: \[c16]{5}\[n]\[r3]\[c6]Last Access: \[c16]{6}\[n]\[r3]\[c6]Last Write: \[c16]{7}\[n]", info.Name, info.FullName, info.Parent, info.Root, info.Attributes, info.CreationTime, info.LastAccessTime, info.LastWriteTime, info.Extension)
        ElseIf System.IO.File.Exists(dirName) Then
            Dim info As New System.IO.FileInfo(dirName)
            ConsoleOutput.WriteFormatted("\[r3]\[c6]Name: \[c16]{0}\[n]\[r3]\[c6]Extension: \[c16]{8}\[n]\[r3]\[c6]Full Name: \[c16]{1}\[n]\[r3]\[c6]Directory: \[c16]{2}\[n]\[r3]\[c6]Length: \[c16]{3}\[n]\[r3]\[c6]Read Only: \[c16]{9}\[n]\[r3]\[c6]Attributes: \[c16]{4}\[n]\[r3]\[c6]Creation Time: \[c16]{5}\[n]\[r3]\[c6]Last Access: \[c16]{6}\[n]\[r3]\[c6]Last Write: \[c16]{7}\[n]", info.Name, info.FullName, info.DirectoryName, info.Length, info.Attributes, info.CreationTime, info.LastAccessTime, info.LastWriteTime, info.Extension, info.IsReadOnly)
        Else
            line.SetResultMessage("File or directory not found.", True)
        End If
    End Sub

    <CommandMethod("Copies a file.")>
    <CommandMethodArgument("Source", 0, "Source path and file name")>
    <CommandMethodArgument("Destination", 1, "Destination path and file name")>
    Public Shared Sub Copy(line As CommandLine)
        Dim args() As String = line.ParseArguments(" ")
        If args.Length = 2 Then
            Try
                System.IO.File.Copy(args(0), args(1))
                line.SetResultMessage("File Copied")
            Catch ex As Exception
                line.SetResultMessage(ex.Message, True)
            End Try
        Else
            line.SetResultMessage("Invalid number of arguments.", True)
        End If
    End Sub

    <CommandMethod("Deletes the specified file or directory (and all contents).")>
    <CommandMethodArgument("Path", "The path of the file or directory to delete")>
    Public Shared Sub Delete(line As CommandLine)
        Dim pathName As String = line.ArgumentString.Trim
        If System.IO.Directory.Exists(pathName) Then
            ConsoleOutput.WriteFormatted("\[r3]\[c14]Press 'Y' to confirm deletion of this directory and all contents. Press any other key to cancel.")
            If Console.ReadKey.Key = ConsoleKey.Y Then
                Try
                    System.IO.Directory.Delete(pathName, True)
                    line.SetResultMessage("Directory Deleted")
                Catch ex As Exception
                    line.SetResultMessage("Error: " & ex.Message, True)
                End Try
            Else
                line.SetResultMessage("Delete Canceled")
            End If
        ElseIf System.IO.File.Exists(pathName) Then
            ConsoleOutput.WriteFormatted("\[r3]\[c14]Press 'Y' to confirm deletion of this file. Press any other key to cancel.")
            If Console.ReadKey.Key = ConsoleKey.Y Then
                Try
                    System.IO.File.Delete(pathName)
                    line.SetResultMessage("File Deleted")
                Catch ex As Exception
                    line.SetResultMessage("Error: " & ex.Message, True)
                End Try
            Else
                line.SetResultMessage("Delete Canceled")
            End If
        Else
            line.SetResultMessage("File or directory not found.", True)
        End If
    End Sub

    <CommandMethod("Creates a new directory.")>
    <CommandMethodArgument("Path", "The path and name of the directory to create")>
    Public Shared Sub MakeDir(line As CommandLine)
        Dim pathName As String = line.ArgumentString.Trim
        If System.IO.Path.IsPathRooted(pathName) Then
            Try
                System.IO.Directory.CreateDirectory(pathName)
                line.SetResultMessage("Directory Created")
            Catch ex As Exception
                line.SetResultMessage("Error: " & ex.Message, True)
            End Try
        Else
            line.SetResultMessage("Must supply a directory name with an absolute path.", True)
        End If
    End Sub

    <CommandMethod("Runs an external program or file.")>
    <CommandMethodArgument("Target", "The program or file to run.")>
    Public Shared Sub Run(line As CommandLine)
        Try
            System.Diagnostics.Process.Start(line.ArgumentString.Trim)
            line.SetResultMessage("Run Initiated")
        Catch ex As Exception
            line.SetResultMessage("Error: " & ex.Message, True)
        End Try
    End Sub
End Class

Last edited May 18, 2012 at 3:34 AM by ReedKimble, version 2

Comments

No comments yet.