Improve the way that I'm passing debug command

2019-02-20 12:09发布

Im my console application I pass the arguments like this:

#Region " DEBUG CommandLine Arguments "

    Private Function Set_CommandLine_Arguments() As List(Of String)

#If DEBUG Then
        ' Debug Commandline arguments for this application:
        Dim DebugArguments = "HotkeyMaker.exe /Hotkey=Escape /run=notepad.exe"
        Return DebugArguments.Split(" ").ToList
#Else
        ' Nomal Commandline arguments:
        Return My.Application.CommandLineArgs.ToList
#End If

    End Function

#End Region

But that has a big obvious problem, the space character will produce false positive arguments, for example:

MyProgram.exe /Run="Process path with spaces.exe"

All we know that as normally the arguments are separated in tokens delimitted by enclosed double quotes " " chars or a space char, so I will get a lot of false positives customizing my debug arguments.

In C# or VBNET how I can improve the function to obtain a list of (custom) arguments correctly separated?

UPDATE 2:

I made this example to try to clarify my intentions:

Module Module1

    ''' <summary>
    ''' Debug commandline arguments for testing.
    ''' </summary>
    Private ReadOnly DebugArguments As String =
    "ThisProcess.exe /Switch1=Value /Switch2=""C:\folder with spaces\file.txt"""

    ''' <summary>
    ''' Here will be stored the commandline arguments of this application.
    ''' If DebugArguments variable is nothing then the "normal" arguments which are passed directly from the console are used here,
    ''' Otherwise, my custom debug arguments are used.
    ''' </summary>
    Private Arguments As List(Of String) = Set_CommandLine_Arguments()

    Sub Main()
        Parse_Arguments()
    End Sub

    Private Sub Parse_Arguments()

        For Each Arg As String In Arguments

            MsgBox(Arg)
            ' Result:
            ' ------
            ' 1st arg: ThisProcess.exe
            ' 2nd arg: /Switch1=Value
            ' 3rd arg: /Switch2="C:\folder
            ' 4th arg: with
            ' 5th arg: spaces\file.txt"

        Next Arg

        ' Expected arguments:
        ' ------------------
        ' 1st arg: ThisProcess.exe
        ' 2nd arg: /Switch1=Value
        ' 3rd arg: /Switch2="C:\folder with spaces\file.txt"

    End Sub

    Public Function Set_CommandLine_Arguments() As List(Of String)

#If DEBUG Then

    If Not String.IsNullOrEmpty(DebugArguments) Then
        ' Retun the custom arguments.
        Return DebugArguments.Split.ToList
    Else
        ' Return the normal commandline arguments passed directly from the console.
        Return My.Application.CommandLineArgs.ToList
    End If

#Else

        ' Return the normal commandline arguments passed directly from the console.
        Return My.Application.CommandLineArgs.ToList

#End If

    End Function

End Module

1条回答
够拽才男人
2楼-- · 2019-02-20 12:53

I think it might be the way you are trying to manage the debug command line.

If you go to Project Properties -> Debug, under start options you can set a starting command line. If you also escape file/path names with quotes (like Windows does in the registry and for shortcut paths), the arguments/path will remain intact. For instance:

/Hotkey=Escape /run="\Program Files\folder name\notepad.exe"

There are multiple ways to get the command line arguments, but NET will parse the commandline for you. Two that will work anywhere are:

myCmd = Environment.CommandLine
args = Environment.GetCommandLineArgs() 

The first will return the full commandline including the name of the current app as the first segment. GetCommandLineArgs will parse the commandline into a string array, again with args(0) being the name of the current executable.

vbArgs = My.Application.CommandLineArgs

This is slightly different, with just the arguments returned (no exe name) and the return is a ReadOnlyCollection(of String)

There is still another way, reminiscent of the bygone days of DOS, which is very useful:

Public Sub Main(args As String())

Rather than start the app from a main form, in Properties -> Application, set it the start up object as Sub Main, then create a sub in a module as above. If you add a string array parameter, NET will parse the commandline, skip the executable name and pass you the arguments in the array. I personally prefer this because I rarely care about the executable name.

This may be particularly useful in this case because if there is a commandline, you probably do not want to show a Form or start a message pump. Even with a straight WinForm app, the start up order of things can be different or include extra steps when passed a file to open or whatever.

You can get the same set of args in VS/VB by setting the starting commandline as described at the outset. All of the GetCommandArgs variations will return the same info in the IDE as at runtime (with the exception that those which include the EXE name, which will report ...myApp.vshost.exe in the IDE).

Example

Using this commandline in VS project properties:

/Hotkey=Escape /run="\Program Files\folder name\notepad.exe" "/arg=this is an arg"

(Line breaks surely distort things here)

Public Sub Main(args As String())
    For j As Integer = 0 To args.Length - 1
        Console.WriteLine("arg {0} == {1}", j, args(j))
    Next
End Sub

Output:

arg 0 == /Hotkey=Escape
arg 1 == /run=\Program Files\folder name\notepad.exe
arg 2 == /arg=this is an arg

Spaces are preserved in the second arg(1), because they were escaped with quotes as the user will have to do - the quotes are also removed. Copy them to a list for processing or whatever the app needs to do.

You get the same args the same way from the same place whether it is runtime or in the IDE with nothing to do differently.

查看更多
登录 后发表回答