Console Application input parameters - string identification - c#

I have a console app that takes in string parameters. The app runs through the command line like so:
C:\ExampleApp.exe this is a "test"
In the above example, there are 4 different strings read in as parameters.. Is there any way to determine which parameter had quotes around it? When I do a Console.WriteLine(args[3]), it prints out as test and not "test".

Environment.CommandLine
returns a complete command line as a single string, just parse it and you will get the original parameters, quoted or not.

As far as I know the quotes are stripped by the framework before beeing passed to your main function, have you tried to escape the qoutes using a backslash?

Related

How can I use System.Commandline.DragonFruit to parse options if the options are not preceded with double dash

I have an existing console app that takes option args that don't have the -- in front of them. For example:
./myapp businessDate=20230128 type=charley location=nashville
Currently I parse the args[] array tokens and split them around the "=" to get the key/value
I can't change that, because other programs already call it that way. But it appears that DragonFruit needs to have it this way instead.
./myapp --businessDate=20230128 type=charley --location=nashville
So my question is, can DragonFruit be configured to NOT use the -- prefix on options when I use the equals sign to separate the key from the value the way I currently do it in the example above? I believe the answer is "no", because of the Posix compliance. But maybe I missed something.
What I Tried
I ran the example program here Building your first app with System.CommandLine.DragonFruit And it worked fine when I ran it:
$ dotnet run --int-option=123 --bool-option=true
The value for --int-option is: 123
The value for --bool-option is: True
The value for --file-option is: null
But when I tried it without the --, this way instead, it gave me errors, and I was hoping it would work as above:
$ dotnet run int-option=123 bool-option=true
Unrecognized command or argument 'int-option=123'.
Unrecognized command or argument 'bool-option=true'.

Running complex command line from C#

I'm trying to run the following command line from C#:
Process.Start("C:\\Program Files\\GoToTags\\GoToTags Encoder\\GoToTags.Encoder.exe --records "{'Url':'http://petshop.intato.com/index.php?id='" + TxtBoxIDCode.Text + "'','RecordType':'Website'}"");
Obviously it is not working.
The problem is that I need to keep the proper signs such as the : in order to make it work properly.
The original command is:
C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe --records "{'Url':'http://petshop.intato.com/index.php?id=29','RecordType':'Website'}"
I have to run that command and at the same time, replace that 29 with the content of a textbox
Would anyone be able to help me with that?
The string.Format command is your friend...
string path = #"C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe";
string args = string.Format("--records \"{'Url':'http://petshop.intato.com/index.php?id={0}','RecordType':'Website'}\"", TxtBoxIDCode.Text);
Process.Start(path, args);
You have several pitfalls awaiting you.
Firstly, as you've already discovered, the backslashes in path names cause problems in the strings, as they could also indicate C# escape sequences. It's usually good practice to use C#'s #"..." syntax for file names, partly to avoid needing to double up the backslashes and make it easier to read, and partly because you could inadvertently leave a \t in there and it'd go unnoticed for ages.
Secondly, the single-parameter call to Process.Start only takes a command - it cannot accept command arguments - so you have to call the two-parameter overload.
Thirdly, the quotes around of the value of the records argument need handling so that the C# syntax knows what you want with them - i.e. to pass them to the command. I've separated out the command arguments into two parts to make that clearer. I have elected to use backslashes to escape them, though using the alternative #"...""..." would be just as good, and the choice is largely down to personal preference unless the context points you strongly one way rather than the other.
string cmd = #"C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe";
string url = "http://petshop.intato.com/index.php?id=" + TxtBoxIDCode.Text;
string cmdArgs = "--records \"{'Url':'" + url + "','RecordType':'Website'}\"";
Process.Start(cmd, cmdArgs);
[edited to add:]
If for some reason you find you either want or need to use string.Format to help build your cmdArgs, there's a fourth gotcha waiting in the wings for you, in that string.Format looks for the brace ({ and }) characters to delimit insertion parameter specifications, but your records command-line argument wants braces characters in the string. The way to achieve that would be to double up the braces that you want, like this:
string cmdArgs =
string.Format("--records \"{{'Url':'{0}','RecordType':'Website'}}\", url)";
In addition to the other answers, you should use the two-argument overload of Process.Start. The first argument is the executable, and the second argument is the command line arguments.
Normally, if you insist on using a single argument call, you should enclose your executable in double quotes, as such:
"\"C:\\Program Files\\GoToTags\\GoToTags Encoder\\GoToTags.Encoder.exe\" ...arguments here..."
However, this form does not work for Process.Start(string) because it specifically disallows it.

Accessing the commandline using C#

I need to access the commandline from within a C# application. I can't find a way to detect mismatched double quotes if I use the "args" parameter.
The application I'm working on the moment has an option to encrypt a string that you pass to it via the commandline.
eg.
program.exe -encrypt somestring
Results in:
EZs/6rWxvJ82+VE8unJ0Xw==
Now if the user types in this:
program.exe -encrypt somestring extra characters
it ignores everything after "somestring" (you can still access the rest of the values through the "args" parameter).
You can workaround this easily using double quotes:
program.exe -encrypt "somestring extra characters"
And of course if you want to use embedded quotes you can escape them with "\":
program.exe -encrypt "somestring \"extra\" characters"
The problem occurs when the user inputs something like this:
program.exe -encrypt "somestring extra characters
or:
program.exe -encrypt somestring ex"tra characters
The program will completely ignore the double quote, which not be what the user was expecting. I would like to detect cases like these and inform the user about the mismatched/unescaped quote, otherwise they might end up with an encrypted version of the wrong string.
This is how the command line passes arguments to your C# program. You cannot change that. You can however access the command arguments string as a whole and perform the validation yourself.
MSDN: Environment.CommandLine Property
Just do it manually: check that either you have only one argument after the -encrypt argument, and if not that the next argument starts with double quotes and the last argument ends with double quotes. If none of these happens throw a custom error to the user.
When the next argument after -encrypt starts with double quotes and the last argument ends with double quotes build the string yourself using Array.Copy or something of that kind.

Spaces and backslashes in Visual Studio build events

I have an application that is supposed to aid my project in terms of pre- and post-build event handling. I'm using ndesk.options for command line argument parsing. Which gave me weird results when my project path contains spaces. I thought this was the fault of ndesk.options but I guess my own application is to blame. I call my application as a post-built event like so:
build.exe --in="$(ProjectDir)" --out="c:\out\"
A simple foreach over args[] displays the following:
--in=c:\my project" --out=c:\out"
What happened is that the last " in each parameter was treated as if it was escaped. Thus the trailing backslash was removed. And the whole thing is treated as a single argument.
Now I thought I was being smart by simply escaping the first " as well, like so:
build.exe --in=\"$(ProjectDir)" --out=\"c:\out\"
In that case the resulting args[] look like this:
--path="c:\my
project"
--out="c:\out"
The trailing backslash in the parameters is still swallowed and the first parameter is now split up.
Passing this args[] to ndesk.options will then yield wrong results.
How should the right command line look so that the correct elements end up in the correct args[] slots? Alternatively, how is one supposed to parse command line arguments like these with or without ndesk.options? Any suggestion is welcome.
Thanks in advance
Did you try to escape the last backslash?
build.exe --in="$(ProjectDir)\" --out="c:\out\\"
This works probably only, as long as the ProjectDir ends in \, which should be given.
This is just an idea, but I did not give it a try
EDIT:
I found a comment which suggests to leave out the trailing "
I actually used "." to solve this same problem:
build.exe --in="$(ProjectDir)." --out="c:\out\."
primarily because otherwise it might look like you are trying to escape the second quote...which you're not, you're escaping the final \ (which is hidden).
I also added a REM in the postbuild command describing why I did that.

Possible to pass name/value as parameter into Windows Console Application?

Building one of my first console apps.
This console app will run some stored procedures I'm defining. I would like to be able to pass in parameter values via the command line.
Is there any way to pass in a name value pair? For example:
myConsoleApp.exe sproc_GetLastActives, #LastActiveDate - 11/20/2009
I know how to retreive the parameter values, but I'm noticing that the args[] are split if I put in a / or a ,. How can I pass in name value pair?
Thanks!
Do you want that in a single string? Try this:
myConsoleApp.exe "sproc_GetLastActives, #LastActiveDate - 11/20/2009"
(i.e. just add quotes)
Slashes and commas shouldn't affect things, but the command line parser splits on spaces unless you've quoted it.
There are several solutions to this problem the most common is to use '/' or '-' to prefix parameters and = to delimit them from their arguments for example
consoleapp.exe /spname=sproc_GetLastActives /LastActiveDate="11/20/2009"
in your code your code you can use String.Split(arg[i], new char[] {'='}) to bust up the individual parameters.
consoleapp.exe key1 val1 key2 val2
args[] gives your 4 items, pair them up in your code. :P
Similar to mykhaylo's response, why not pass in the values at one string:
consoleapp.exe sproc_name key1=value1 "key2=Value With Spaces" key3=value3
Then just test for the presence of the = sign and parse it to get your key/value pair.

Categories