Posts tagged: Command Line

Visual Basic: Parse Command Line Arguments from a String

By , December 1, 2009 1:15 am

Sometimes I write code that I think I need but never end up using. This was the case with the parseCommandLineString() function that I wrote in Visual Basic .NET. I needed a function that would take a command line string that included arguments and parse it in the same way that Environment.ParseCommandLineArgs() does. Why? Because System.Diagnostics.ProcessStartInfo uses two properties that separate the executable file name from the arguments. Why Microsoft left this functionality out of the framework is beyond me. Anyway, there is a method build into the Windows API that can parse arguments from a command line string: CommandLineToArgv(). Unfortunately, calling it in VB .NET requires Marshalling and I couldn’t find a good example online. Here’s my code:

    Private Declare Function CommandLineToArgv Lib "shell32.dll" Alias "CommandLineToArgvW" (ByVal lpCmdLine As String, ByRef pNumArgs As Integer) As Long
    '''
    ''' Summary: Parse the command line string so that it can be used with System.Diagnostics.Process. I chose to use the Windows API here to ensure that the command line parsing is consistent with how Windows handles it.
    '''
    ''' Parameter command: The string that should be parsed
    ''' Returns: An array of command line arguments similar to what Environment.GetCommandLineArgs() produces.
    ''' It sure would be nice if the framework had a method for doing this. It becomes a drawback of using System.Diagnostics.Process, which requires arguments to be separated from the executable.
    Private Function parseCommandLineString(ByVal command As String) As String()
        Dim numargs As Integer
        Dim t As Integer
        Dim ptrCommand As IntPtr = Marshal.StringToHGlobalUni(command) 'Marshal the string to a pointer
        Dim ptrSplitArgs As IntPtr = CommandLineToArgv(ptrCommand, numargs) 'Pass the pointer to CommandLineToArgv for parsing, retrieve the pointer of the result.
        If ptrSplitArgs = IntPtr.Zero Then Throw New System.ComponentModel.Win32Exception 'Is it a valid pointer? Throw an exception if it isn't.
        Dim splitargs(numargs - 1) As String

        For t = 0 To numargs - 1
            splitargs(t) = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptrCommand, t * IntPtr.Size)).Trim  'Iterate through the arguments and add them to an array.
        Next
        Marshal.FreeHGlobal(ptrCommand)
        Marshal.FreeHGlobal(ptrSplitArgs)
        Return splitargs

    End Function

Panorama Theme by Themocracy