1

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
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • are you talking about MyProgram.exe **receiving** commandline args or sending them as with your `/Run` example? – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 14:07
  • @Plutonix When my app is in debug mode I pass (it receives) a custom arguments `Dim DebugArguments = ...`. If I want to pass an argument which has spaces and is enclosed like this: `"I'm an arg"` then I get 3 arguments: 1st: `I'm` 2nd: `an` 3rd:`arg`, but of course that arg really should be threated only as one arg, If i pass the same argument without debug mdoe, it is only 1 arg instead of those bad 3,'cause is enclosed with double quotes.Im not trying to change the way that my app receives arguments as normally,I only want to set correctly the arguments when I try to test them in debug mode. – ElektroStudios Nov 30 '13 at 14:30
  • you can try NDesk.options http://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c – Amitd Nov 30 '13 at 15:00

1 Answers1

1

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.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • the solution does not solve the problem, to parse the arguments (only in debug mode I do this) I need to split them in a "list" of arguments. the problem as you can see in the code above is that I'm splitting the arguments taking by delimitter the space character, then I'll get 3 arguments: 1st:`/run="\Program` 2nd:`Files\folder` 3rd:`name\notepad.exe"` you understand my problem? sorry if I'd explained it bad, maybe this other older question can clear things: http://stackoverflow.com/questions/16107276/setting-default-debug-commandline-arguments-by-code – ElektroStudios Nov 30 '13 at 15:46
  • so, just dont split them!! move them from the array to your List. see edit. that 3rd notepad arg is passed to you correctly - you are chopping them up. Are you also trying to parse the 'command' from the text as well? (e.g. break "/run" off of the 3rd arg?) – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 15:53
  • But I have any array, I need to create by myself the array (well, the list type) which will contains my custom arguments for debug testing, that's the question, I need to index them manually splitting them correctly. In my code above I've posted a string, which I need to convert correctly in an "arguments list". I know that this can be done from the project properties where the quotes/spaces are assigned right, but i would like to do it using code – ElektroStudios Nov 30 '13 at 15:59
  • I seen your last edit but... that does not work (at least for what I'm trying to do) the third argument is break by the spaces characters. could you add to your answer how do you convert that string `HotkeyMaker.exe /Hotkey=Escape /run="\Program Files\folder name\notepad.exe"` into the string array to pass it to a method? `ByVal args As String()` – ElektroStudios Nov 30 '13 at 16:09
  • if you escape the file names or any arg that has a space (like `/arg=this is an arg` ==> '"/arg=this is an arg"' or `"/arg=this is an arg"') then VS will keep it together, YOU just need to copy it to the list – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 16:12
  • All what are you saying is for the usage of NORMAL arguments like Environment.CommandLine there are stored the normal arguments but not the DEBUG arguments which I made from code (not from project property page), then the debug arguments string I need to convert them to an array properly in the same way that the Environment.CommandLine contains the normal arguments. Don't you see that I'm trying to set the arguments at runtime? and the problem are the spaces/quotes which aren't properly parsed by me – ElektroStudios Nov 30 '13 at 16:19
  • Depends on the definition of NORMAL. The `Environment.CommandLine` is just the **raw** commandline. Look at `Environment.GetCommandLineArgs` - it is a string array of arguments just like that I show for `Sub Main(args())` except as I noted in the last edit (an extra arg). If you define the Debug Args in VS props, they will come thru the same way as from the user in both `Sub Main` and `Environment.GetCommandLineArgs`. (I am not sure you can actually SET the command line from code - that goes back to at least DOS 2.1). – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 16:43
  • how are you not having the same problem at runtime if you are processing the command**LINE** manually? where do you get the runtime commandline from? am i missing something? Did you notice, I was pointing you to a different Environ item: CommandLine**Args** - NET/EXE loader will parse your debug args the very same way it does the actual command line. – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 17:28
  • yes I think that you've totally missed what I've tried to explain, maybe is my fault 'cause the English language or I don't know... but really the question is not solved. I'm not having any problem when I open the CMD to run the CLI application passing any kind of arguments, vbnet parses them correctly as you hve said, the problem is that when I try to set the application arguments by myself (see the first code of my question) I can't parse them as the same efficacy that the vb mechanism does about the double-quotes and spaces – ElektroStudios Nov 30 '13 at 17:32
  • @ElektroStudios `My.Application.CommandLineArgs` is a little different than `Environment.CommandLineArgs`. But the larger point is that NET WILL parse your debug command line (from VS proj props) to that SAME format for development. See Editx3 - I suspect the real issue is that you do not want to escape args with spaces? – Ňɏssa Pøngjǣrdenlarp Nov 30 '13 at 18:55