 |
|
|
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
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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 { /// /// Arguments class ///
public class Arguments : Dictionary<string,> { // Constructor 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;
// Valid parameters forms: // {-,/,--}param{ ,=,:}((",')value(",')) // Examples: // -param1 value1 --param2 /param3:"Test-:-work" /param4=happy -param5 '--=nice=--' foreach (string Txt in Args) { // Look for new parameters (-,/ or --) and a // possible enclosed value (=, parts = splitter.Split(Txt, 3);
switch (parts.Length) { // Found a value (for the last parameter // found (space separator)) case 1: if (parameter != null) { if (!base.ContainsKey(parameter)) { parts[0] = remover.Replace(parts[0], "$1"); base.Add(parameter, parts[0]); } parameter = null; } // else Error: no parameter waiting for a value (skipped) break; // Found just a parameter case 2: // The last parameter is still waiting. // With no value, set it to true. if (parameter != null) { if (!base.ContainsKey(parameter)) { base.Add(parameter, "true"); } } parameter = parts[1]; break;
// Parameter with enclosed value case 3: // The last parameter is still waiting. // With no value, set it to true. if (parameter != null) { if (!base.ContainsKey(parameter)) base.Add(parameter, "true"); }
parameter = parts[1];
// Remove possible enclosing characters (",') if (!base.ContainsKey(parameter)) { parts[2] = remover.Replace(parts[2], "$1"); base.Add(parameter, parts[2]); } parameter = null; break; } } // In case a parameter is still waiting if (parameter != null) { if (!base.ContainsKey(parameter)) { base.Add(parameter, "true"); } } } } }
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Great peace of code.
What about adding a prop Count, so we can check in our apps
Arguments CommandLine = new Arguments(args);
if (CommandLine.Count > 0) // do parm proccessing else Console.WriteLine("No Parms Defined");
TNX!
modified on Friday, May 16, 2008 5:31 AM
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
I wanted to use your code in my application and I wanted to know what are the restrictions on the usage. Please let me know the type of license you have attached to this code.
Thank you
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Any mention of the license type? I'm finding this handy too and want to use it in a small tool im writing. Thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi there,
Thank you. The license is: "free to use and to modify". I don't any license on these piece of code. If you want to, you can mention me . All my new stuff use MIT license and is this also very permissive even for commercial applications.
Cheers,
Richard LOPES Just programmer.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I tried the suggestion to remove |: from the Splitter regex and it does fix file name issue but now it can not read value of height defined as /height:'400' on the command line.
Also someone else suggested to make change in the regex. I can't find the original statement in the code, nor does the mod work.
Any help is much appreciated.
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
Saved me hours of work and it works first go. Have done this before many times in the old UNIX days and didn't really want to go through it all again.
Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am new to C# (old time C coder) and remember what a pain it was to parse args[]... this was a 10 minute setup (I had to figure out how to use "Project...Add existing item..." to add the .cs file to my project and w/o any code changes it just worked exactly how I needed it to.
Thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is a great little piece of code. Thumbs up for that.
It's also a beautiful illustration of the reputation of "the French way of doing things". In the Netherlands we have a proverb about this. I just hope people interested in this code have the time to go through all the comments, because without them, you might lose a lot of time debugging.
We also have a saying "Live like God in France", so it must be an enjoyable country to live in. Or at least at some point in time.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for the code. I intergrated it with an in-house project in 10 minutes.
I had to make the change to handle filename paths (Im need; -output c:\temp\foo.html, quickly fixed by removing |: from regex as posted below).
Nice one!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for the code example, GriffonRL. I used your class to quickly put together a parser for my program, defiantly less of a hassle then putting it together myself.
I'm not complaining, but just saying, because you look like your taking advice for the next version, the resulting calls to the object getting alittle messy with all the if else statements. Maybe it could be handled better on my end. It would also be cool to make the parser recognize two unique commands as being the same, like -h and -?, for example.
Anyway, thanks alot for the code, defiantly made my day easier, if I give any serious thought to improvements I'll post something more indepth.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The class seems to be broken when trying to use space separated name/value pairs. For example, a parameter such as:
-xmlFile="E:\HOME PWR Reports\MembershipRpt.xml"
returns a value of "true" for 'xmlFile'.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
Strange, the class is build to handle this kind of scenario. It works for me. You can try to use simple quotes instead of double quotes. Are you also passing other parameters before or after your xmlfile path ? I would like to reproduce the problem. I may have also to try with the downloadable version on Codeproject because the version I casually use in my apps is an updated one.
Cheers,
R. LOPES Just programmer.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
I didn't tried it yet but you can also tweak the splitter regex and remove the ':' character from it. The other reason could be the space you have in your path even if you enclosed everything inside double quotes. Of course, this should not be a problem unless... Unless you get the parameters from Environment.CommandLine instead of the Args array.
Happy coding,
R. LOPES Just programmer.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Try this pls:
Regex isParam = new Regex(@"^^-{1,2}|^/", RegexOptions.IgnoreCase | RegexOptions.Compiled);
Regex Spliter = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled);
[...]
bool isparam = isParam.IsMatch(Txt); if (isparam) Parts = Spliter.Split(Txt, 3); else Parts = new string[] { Txt };
This will splitt only if - -- oder / detected.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I really like your command-line parser - alas, it lets me down in one case:
if I have an argument that expects a file name including a path, such as "C:\temp\*.xml", I cannot seem to get those properly.
When I call my app with an argument "/filespec c:\temp\*.xml", or even when I put the file name / path in double quotes ("), I always get "True" for the "filespec" argument.
It appears that the parser will choke on the ":" in the path and think this is another argument to split up; it should *NOT* do this, especially if the file path/file spec is enclosed in double quotes!
Any chance you could fix this? Also- whenever I download your code, I always seem to get the v1.0 version (Oct 2002) - not the bug fixed version of November. Did you upload the most current version at all?
Thanks again for a great little piece of software!
============================= Marc Scheuner, Berne, Switzerland mscheuner - at - gmail.com May The Source Be With You!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Marc,
Good points.
For your parsing problem, you found a problem. This could be fixed by tweaking the regex in case one use " or ' characters. The splitter regex has to be enhanced for such cases. But I may be not enough. I didn't have the time right now to look at the problem, because of a heavy schedule. If you are really in need you can give it a try.
That leads us to the second good point you made. I didn't updated the source in the past 2 years but I should do it some day because many people in the comments threads came up with good ideas and fixes. Again I am always postponing this task of puting every contributed bit together to upload an updated and rock solid version. However, I think I can manage at last a moment before mid-september to update the code, the article and give credits to every people who pointed out problems, fixes and enhancements. Please note I use an enhanced version of this class myself (but this doesn't include the fix you need).
I'm sorry not to come right now with a good answer. It's at the very least on my todo list.
Keep coding,
R. LOPES Just programmer.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Simply removing the "|:" from the regex seems to fix the problem. That is never a legitimate delimiter that I have heard of anyway.
This also solves the problem above which has ":" in the parameter.
Dave
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
the "|:" delimiter is most certainly a valid delimiter, but only in one very specific instance is it ever used that I can think of. That instance being the processing of Optical Character Recognition fields when determining the begining of an ABA Routing numbers and Account numbers fields on checks. The "|:" is used to delimit the begining of a new field either the ABA Routing number or the account number example |:123456789|:1112223334444"' 0001 as you can see from this example the aba routing number is preceded and anteceded by the "|:" character and an OCR system is instructed that data to follow represents a contiguous field from that special delimiter. Hopefuly your needs will not include OCR Check Processing but if it does you may need to put that "|:" delimiter back in
HTH
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
that part of the regex does is not to allow "|:" as a delimiter, but is meant allow ":" as a delimiter between the parameter and the value. in your example, leaving that bit in would cause the same problem with ABA routing numbers as it would for file paths, etc. But, only if you were passing in the Routing number as a value for a parameter.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I was able to fix this by: First, changing the Remover so that it would match on quoted strings, instead of making the quotes optional: Regex Remover= new Regex(@"^['""](.*?)['""]$",RegexOptions.IgnoreCase|RegexOptions.Compiled); Removing the ? following the character classes makes the classes required for a match. Now, you can differentiate between the quoted paramter value, and the parameter itself. Then, before the switch change the single line that splits the Arg to if (!Remover.IsMatch(Arg)) { Parts = Splitter.Split(Arg, 3); } else { Parts = new String[] { Remover.Replace(Arg, "$1")}; }
Now, it will split the parameters correctly (since they will not start with a single, or double, quote. And,if the parameters are separated by spaces, the value will have the quotes stripped before the switch.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
He man, you've been doing a great job. I wrote a slightly different version of your code. The way i needed it was with 1 parameter who has got possible multiple values. In my case i wanted 1 parameter database, and then be able to write down multiple database-names. In my case there will be no true value if the parameter is standalone, it will have a value-colection with count == 0
this way i can put a line down like this: program.exe -database db1 db2 db2 -debug -build:1401 where db1, db2 and db3 will be added to the parameter database
So here is what i did:
using System; using System.Collections; using System.Collections.Specialized; using System.Text.RegularExpressions;
namespace Piramide.Bis.Conversie.Util { /// <summary> /// CommandLine Argument Parser /// </summary> public class CmdArgParser { // Variables private Hashtable _parameters;
public Hashtable Parameters { get { return _parameters; } }
/// <summary> /// Constructor /// </summary> public CmdArgParser(string[] Args) { _parameters = new Hashtable(); Regex splitter = new Regex(@"^-|^/|=|:", RegexOptions.IgnoreCase|RegexOptions.Compiled); Regex remover = new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase|RegexOptions.Compiled);
string parameter = null; string[] parts; ArrayList values = new ArrayList();
&n | | | |