 |
|
 |
Changing
Regex Spliter = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase|RegexOptions.Compiled);
to
Regex Spliter = new Regex("^-{1,2}|^/|=|:(?!\\)", RegexOptions.IgnoreCase|RegexOptions.Compiled);
fixes an issue where the argument value is a file path similar to:
/attachment "C:\temp\test.txt"
by not splitting on a colon when followed by a backslash.
So, the following code arguments:
/arg1:Test /arg2 "C:\path\to\file.txt"
arg1 = Test
arg2 = C:\path\to\file.txt
Hope this helps someone out!
|
|
|
|
 |
|
 |
I've looked a quite a few different classes to do command line argument parsing after getting sick of reimplementing it each new application I write. This one is my favourite. It is set out in a very logical and easy to understand manner (unlike many) and is nice and compact. Easily converted to vb.net as well. Thanks Richard!
|
|
|
|
 |
|
 |
I've been looking for this utility for a long time.
I've taken a few runs at writing it myself, but this is really a well thought-out
solution!
Thanks for sharing,
Ross
|
|
|
|
 |
|
|
 |
|
 |
Thanks for the jump off point Richard. Here's a revised version I annotated for my own understanding. It also handles the false-positive matching on parameter values that contain more than one valid delimiting character, even though the param value is enclosed in quotes:
public static class UtilClass
{
public static StringDictionary SplitArgString(this string[] Args)
{
StringDictionary parameters = new StringDictionary();
Regex validDelims = new Regex(@"^-{1,2}|^/|[^['""]?.*]=['""]?$|[^['""]?.*]:['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
Regex quotedString = new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
string currentParam = null;
string[] parts;
foreach (string arg in Args)
{
parts = validDelims.Split(arg, 3);
switch (parts.Length)
{
case 1:
if (currentParam != null)
{
if (!parameters.ContainsKey(currentParam))
parameters.Add(currentParam, quotedString.Replace(parts[0], "$1"));
currentParam = null;
}
break;
case 2:
if (currentParam != null && !parameters.ContainsKey(currentParam))
parameters.Add(currentParam, "true");
currentParam = parts[1];
break;
case 3:
if (currentParam != null && !parameters.ContainsKey(currentParam))
parameters.Add(currentParam, "true");
currentParam = parts[1];
if (!parameters.ContainsKey(currentParam))
parameters.Add(currentParam, quotedString.Replace(parts[2], "$1"));
currentParam = null;
break;
}
}
if (currentParam != null)
{
if (!parameters.ContainsKey(currentParam))
parameters.Add(currentParam, "true");
}
return parameters;
}
}
|
|
|
|
 |
|
 |
I'm not sure if validDelims is correct. It cannot handle cases like: -i=file.txt - as the result i=file.txt becomes the argument name.
--
Piotr
|
|
|
|
 |
|
 |
I have trouble to define parameters with path values. For example: --path d:\temp\file.txt or --path "d:\temp\file.txt" or --path 'd:\temp\file.txt'
|
|
|
|
 |
|
 |
Yes, this parser is totally sux, it do not work with file paths, useless.
|
|
|
|
 |
|
 |
Don't know why you make your self a problem? Use -file:"c:\directory name\file name.txt" instead. It works fine...
|
|
|
|
 |
|
 |
Very few command line applications work with file paths as arguments if you don't enclose them in quotes. This should not surprise you.
|
|
|
|
 |
|
 |
This is excellent. Thank you
|
|
|
|
 |
|
|
 |
|
 |
Hi,
All the pleasure is mine. Feel free to use it.
I would recommend all interested people to look at your updated version.
Thanks for you words,
Richard
|
|
|
|
 |
|
 |
I thought i'd just add my comment, which is I've been using an "MS" one for years, and it seems solid and powerful. It does automatic shorthands, and optons file. Here's a link.
http://www.koders.com/csharp/fid9953548D02FEE3252D7CBA336A4C6346DF9B0B56.aspx[^]
You define a class
public class CLIArgs
{
public string ConnectionStr = string.Empty;
public string ScriptsFolder = string.Empty;
}
and then do somehting like this
CLIArgs parsedArgs = new CLIArgs();
if (!CommandLine.Parser.ParseArguments(args, parsedArgs))
{
Console.WriteLine(CommandLine.Parser.ArgumentsUsage(typeof(CLIArgs)));
Console.Write("\n");
Console.Write("Blah blah blah\n");
return;
}
if (parsedArgs.ConnectionStr.Length == 0)
{
Console.WriteLine("ConnectionStr must be specified");
return;
}
|
|
|
|
 |
|
 |
Can I ask you why you submit buggy code and even do not have time to correct it in six year?
Do not confuse other developers and keep you code for yourself.
|
|
|
|
 |
|
 |
Why to bitch about code that is given to you free to learn from?
If you have a bug complaint, fix it, and post the solution. The author has posted some excellent code and has been active in discussing bugs and edge cases. If you can't fix the code yourself, learn to do so, rather than whining and expecting the author to do EVERYTHING for you.
|
|
|
|
 |
|
|
 |
|
 |
Or is this you, his name is Richard L. McCutchen, is that L for Lopes?
|
|
|
|
 |
|
 |
Hi,
Firstable I am glad to meet you since I evaluated entityspaces a while back and loved it. Very goos work.
And to answer your question: no I am not Richard L. McCutchen. L. is not for Lopes at all. I'm going to look at his website.
Best regards,
R. LOPES
Just programmer.
Http://sili.co.nz/blog
|
|
|
|
 |
|
 |
Hi,
Thank you for finding this complete ripoff.
I'm not even angry, I'm really sorry for the guy. He even put a copyright in it indeed and moreover a more restrictive GPL license. Also it says created in "March 2008".
So I am going to warn the guy and notify the website to remove the article.
Thank you again very much,
R. LOPES
Just programmer.
Http://sili.co.nz/blog
|
|
|
|
 |
|
 |
I am about to create our command line version for ES2009 and went looking for a sample. I found yours, went to look at a few more articles, found his and was like what the heck? By the way, ES2009 runs under Visual Studio and doesn't require MyGeneration or CodeSmith anymore (sorry for the commerical). I really thought in the end his article was yours since the names seemed to almost match.
- Mike
|
|
|
|
 |
|
 |
Hi,
Is there already a trial for ES2009 ?
I forget to look even if I just finished reading the ES2009 features and some of your blog posts. I saw there was one trial for ES2008 but this one still rely on MyGeneration. Actually MyGeneration is great, I used it for many tasks in the past. Of course for the OR/M, Visual Studio integration is a definitive plus.
By the way I responded to the guy that ripped off my article, and I posted that: http://sili.co.nz/blog/2009/01/hello-you-have-been-ripped-off/
Thanks again,
R. LOPES
Just programmer.
Http://sili.co.nz/blog
|
|
|
|
 |
|
 |
I found that on XP the inclusion of double quotes "" would cause separate command line options to be merged into a single command line argument passed into Main.
For example:
myapp.exe /dir:"C:\program files\myapp\data" /confirm:true /server:localhost
on XP void Main(string[] args) would contain only two arguments.
args[0] myapp.exe
args[1] /dir:"C:\program files\myapp\data" /confirm:true /server:localhost
The only way to make it work on XP was to replace the double quotes with single quotes
myapp.exe /dir:'C:\program files\myapp\data' /confirm:true /server:localhost
which would then correclty return
args[0] myapp.exe
args[1] /dir:'C:\program files\myapp\data'
args[2] /confirm:true /server:localhost
args[3] /server:localhost
Todd Smith
|
|
|
|
 |
|
 |
NConsoler is an open source library that provides command line parser functionality based on attribute metadata attached to type.
Library is very easy to add and use in your application. NConsoler gives an ability to display help and validation messages without any line of code.
http://nconsoler.csharpus.com/
Example code:
using System;
using NConsoler;
public class Program {
public static void Main(params string[] args) {
Consolery.Run(typeof(Program), args);
}
[Action]
public static void Method(
[Required] string name,
[Optional(true)] bool flag) {
Console.WriteLine("name: {0}, flag: {1}", name, flag);
}
}
and use it:
program.exe "Maxim" /-flag
|
|
|
|
 |
|
 |
Hey, thank you very much!
But I have changed my code to inheritance:
public class Arguments : Dictionary<string,>
Like that I can use all the functionality of a Dictionary class. That makes it much easier. That didn't needed a lot of changes in the using code, but it gives a lot more comfort.
Greets tt
--------------
the whole code:
using System.Text.RegularExpressions;
using System.Collections.Generic;
namespace CommandLine.Utility
{
{
public Arguments(string[] Args)
{
Regex splitter = new Regex( @"^-{1,2}|^/|=|:",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
Regex remover = new Regex( @"^['""]?(.*?)['""]?$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
string parameter = null;
string[] parts;
foreach (string Txt in Args)
{
parts = splitter.Split(Txt, 3);
switch (parts.Length)
{
case 1:
if (parameter != null)
{
if (!base.ContainsKey(parameter))
{
parts[0] = remover.Replace(parts[0], "$1");
base.Add(parameter, parts[0]);
}
parameter = null;
}
break;
case 2:
if (parameter != null)
{
if (!base.ContainsKey(parameter))
{
base.Add(parameter, "true");
}
}
parameter = parts[1];
break;
case 3:
if (parameter != null)
{
if (!base.ContainsKey(parameter))
base.Add(parameter, "true");
}
parameter = parts[1];
if (!base.ContainsKey(parameter))
{
parts[2] = remover.Replace(parts[2], "$1");
base.Add(parameter, parts[2]);
}
parameter = null;
break;
}
}
if (parameter != null)
{
if (!base.ContainsKey(parameter))
{
base.Add(parameter, "true");
}
}
}
}
}
|
|
|
|
 |