Showing help for a command-line utility - c#

I have a command-line utility that gets quite a bit of downloads from my site. I'm trying to show the usage when a user uses the /? or /help parameters. I have a function called ShowUsage() that has nicely formatted text on the parameters available.
I see that ShowUsage() gets called fine from Visual Studio 2008, when I'm using the command-line parameters in the project properties. However the exe does not display the help text when run from the command-line. Here's a shortened version of ShowUsage():
private static void ShowUsage()
{
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Text File Splitter v1.4.1 released: December 14, 2008");
Console.WriteLine("Copyright (C) 2007-2008 Hector Sosa, Jr");
Console.WriteLine("http://www.systemwidgets.com");
Console.WriteLine("");
}
I tried a bunch of different things from my searches in Google, but none are working. I know this has to be something simple/easy, but for the life of me, I can't figure this one out.
EDIT:
The code that calls ShowUsage():
if (!Equals(cmdargs["help"], null) || !Equals(cmdargs["?"], null))
{
ShowUsage();
}
I have a class that parses the parameters into the cmdargs array. I confirmed that the parameters are in the array. It's something inside ShowUsage() that is preventing from showing the text.
I'm going to try the debug trick, and see what I find.
I'm not using Console.Out anywhere.
d03boy - Just personal preference. It makes the text less cluttered onscreen, at least to me.
EDIT #2
Ok, some more information... I'm running VS2008 in Vista Ultimate 64 bit. I just check the project properties and it is set to "Windows Application." This utility is 32 bit.
I'm going to experiment with creating a separate project in the solution that is a true console program, as some of you have advised.

Can you define "not working"? Simply not doing anything? Throwing an exception? I would expect the problem to be in the Main(...) method - i.e. ShowUsage() isn't being called. Another common issue is not rebuilding it in the correct configuration, so bin/release (or whatever) isn't updated.
Have you built the app as a console exe? i.e. is the "Output Type" = "Console Application" in project properties? It needs to be in order to access the console...
For info, I find the easiest way to do a console help screen (once it gets beyond a handful of lines) is to embed a .txt file into the exe; then I just write out the text file (perhaps still using string.Format if I want to replace tokes).
Alternatively, there is the alternative string format:
Console.WriteLine(#"
Text File Splitter v1.4.1 released: December 14, 2008
Copyright (C) 2007-2008 Hector Sosa, Jr
http://www.systemwidgets.com
");

Are you redirecting Console.Out to somewhere else?
Try throwing a System.Diagnostics.Debugger.Launch() in the ShowUsage method so you can see if it's getting hit at runtime.
Can you reproduce the issue with a simple exe, only accepting those help parameters?

Related

C# application which installs and allows for global command line

I would like to build a simple .NET application that installs on a windows machine which will allow the end user to open a command prompt and type "google test" which will open google and search for test. But I'm not sure how to install a global "keyword" such as "google". Is this down via Environment variables? How does this link up to my .NET application?
Any advice or pointers is appreciated.
Thanks
This is beyond a .NET application and belongs into the Area of Setup programms. Visual Studio used to have a Installer Project, but as there are so many 3rd party ways this was removed.
Having "google test" parsed as a google search for "test" is tricky, but possible. However it depends entirely on how the commandline is parsed in a Windows. Wich is pretty much the way it was parsed since DOS 1.0.
If you just enter a word like "google", the commandline will look if there is a Excetuable file (.exe, .com, .bat) of that name in the current folder (working directory). It will then look into all the folders defined in the path variables. However using path variables is so dated, I could find only a single entry in my Windows Path variable now. And it is for MS backward compatibility: "%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;"
Most starting of programms is done via file associations with a specific type. And protocoll associations with a protocoll (like http, https, steam). Indeed my advise would be to make a .NET Programm named "google" whose sole purpose is to to format the proper URL, then send it to console parsing via ProcessStart. And let Windows solve wich programm to use from there.
Edit: And as I only realized after wirting this, apparently Windwos finally supports commandline aliases. https://learn.microsoft.com/en-us/windows/console/console-aliases
Apparently they even added a way to make them via the WinAPI in Windows 2000. However that requires moving to unmanaged code. And I have no experience, but it appears those aliases might only be valid for one console instance. So you might have to put it into a place like hte autoexec.bat to be called everytime a console is created.

Converting a C# (Windows application) into commandline application?

I am looking to convert a C# (Windows platform application) into a commandline version.
The scenario is: I have implemented a C# (Windows application) in VS 2010. The output of this application is to generate a txt (log) file (in simple explanation).
Now the case is, there is one other application which need to use my this C# application, by calling my C# application from the command line at the run time.
My question is, how is it possible to convert an already existing C# application into commandline application, so that this C# application can be called from the calling (other) program? There is one input parameter which need to be passed on the commandline to my C# application. And then this C# application will process the data according to input parameter and then generate the output log(txt) file.
Added explanation
I am really impressed by the solutions here. Just a bit more expertise is required from readers. I want one application only to work as both commandline application as well Windows-application (forget to mention it before, sorry!), depending on the number of input parameter pass to the application. From this point of view, I have two options to implement it,
1) Make separate functions for both applications (commandline and windows-forms). Call them according to the input parameter pass. In each function implement the complete functionality of each application without disturbing (or going into the code of other application). Also I will be able to re-use 2 main functions, already built in windows-form application into my commandline application after some editing.
Disadvantage: This will make the code size nearly 50% more than case 2.
2) The second idea is same as describe by one of the expert here, to use the same application/functions for commandline as that of already built windows-form application. The only way to distinguish is to look at the input parameter pass, and decide accordingly whether to show the GUI interface or just use the commandline input (and do processing).
Disadvantage: This case will make the code bit messy and difficult to maintain/implement due to extra adding of check for number of input parameter decisions.
Which strategy should I follow for implementation?
Sure - just:
Create a new VS2010 command-line project
You'll now have a "main ()" (or, in MS-Land, "_tmain()") function instead of a root class.
Cut and paste the relevant code into "main()" (or into a function called by main (), or into a class created from main() - your choice).
Do a search-and-destroy mission to find anyplace where you're doing GUI input, and substitute command line parameters instead.
Parse your command line.
Voila! Done!
You don't have to convert it. Your application can stay as a Windows application. You simply need to handle command line arguments.
To get the command line arguments from ANYWHERE in the application, just use Environment.GetCommandLineArgs();
You want to get value from command line is not a good reason to convert winform app to console app. You may use,
string[] args = Environment.GetCommandLineArgs();
However you can change application type by opening project properties (right click on project name) and change the Output type.
Just don't show the GUI if you get paramater passed in, as when called from the other program.

What is causing Ghostscript to return an error of -100?

So, I am using Matthew Ephraim's GhostscriptSharp, which is a simple C# wrapper for the unmanaged Win32 Ghostscript DLL in my ASP.Net MVC project. Some background:
What I am attempting to do is have a user upload a PDF, and then convert that document into an image that I can then save off into whatever directory I choose (as well as do some other OOP to tie that new image to my site).
I decided to use Mr. Ephraim's wrapper class (GhostscriptSharp) because it was simple enough to use, and it gives me relatively clean access to the DLL's API.
To test it, I created a dummy C# console application to make sure I could load the DLL, access it, hand it a PDF file on the local disk and then have it write a JPG to the same local disk. After a few learning experiences, I had success. I would hand it C:\INPUT.pdf, it would hand me C:\OUTPUT.jpg.
However, after integrating the GhostScriptSharp code that I had in the console application into my ASP.NET MVC project to the point of where I was calling the DLL with P/invoke, Ghostscript is returning with the int/error code -100, which is a fatal error (is called E_Fatal in the GhostScript source code). I get the same result with both the file that is uploaded through the HTML form, and if I hand it the exact same hard-coded paths that I used in my working console application.
For reference, the lines which the exception is thrown are 93-97 in GhostScriptSharp.cs (which is in the CallApi function):
int result = InitAPI(gsInstancePtr, args.Length, args);
if (result < 0) {
throw new ExternalException("Ghostscript conversion error", result);
}
Obviously the exception is thrown because result is -100.
When InitAPI is called, the instance ptr is a valid int (though I don't know if the instance of GS is correct or not), args has a length of 20 (is a string[]) of valid GhostScript options (including the correctly-escaped paths to my input & output files).
Long story short, what am I doing wrong? The error code -100 seems like a catch-all because there is no documentation that states what could possibly be going wrong here.
Any help is much appreciated, thank you in advance.
The -100 error is a generic "fatal error" in GhostScript.
A few things to check:
1) Permissions (al operations require file access)
2) Scope, you want to add the GS bin folder to the PATH variables
3) Consider not calling GhostScript directly from asp.net, GS can be very CPU intensive, rather process files in a separate service
I have also created a wrapper, send me an email (address on profile) and I will send it you. It allows one to pass in the GS bin folder which helps.
So, ended up being an ID10T error that was derailing me here in this specific instance.
In Matthew Ephraim's GhostscriptSharp code, he uses a couple of enums to define the options set forth for Ghostscript, and two in particular were the GhostscriptDevices and GhostscriptPageSizes enums. Problem is, the way they're written Resharper (Jetbrains Visual Studio plugin) has default rules for naming Enum members. Not thinking, I fixed all of these definitions to please Resharper not realizing that these are passed directly to Ghostscript, so instead of getting a7 for -sPAPERSIZE GS was getting A7, and for -sDEVICE it was getting Jpeg instead of jpeg.
For the time being permissions weren't a problem on my end, but only because I run the Cassini web dev test server in Visual Studio.
Thanks to #MarkRedman and #tvanfosson for their helpful suggestions!
Most likely the process running the web application does not have permission to write to the directories that you are using. I'd suggest creating some specific directory for the app to use and a local id to use to run the app pool, then give that id enough privileges to read/write the directory you've created.

c# program works from cmd prompt but not run separately?

I would post a snippet, but I honestly have no idea what part of my code could possibly be doing this. The program is sizable, I don't want to make you all wade through it. What kinds of things could possibly be the cause of this? Everything works perfectly when called from the command prompt: "readoo.exe". But when I click the exe in its file. . . "readoo.exe has encountered a problem and needs to close. . ."
this is intended to eventually be a scheduled task -> i'm worried, will it work?
i've never debugged, all i've ever used is notepad. I am learning, and feel that this strengthens my understanding of a project.
it crashes nearly immediately. there are no shortcuts, though the file paths are relative.
trying this method: shortcut -> properties -> shortcut -> Start In. I don't have a "shortcut" option
my program reads log files, parses, and creates 4 new files based on the found content
Microsoft Error Report says file not found. But how can this be? the files are there, albeit relative.
Take a copy of your project, and then start hacking bits out of it. When it no longer crashes, you've removed the bit causing the problem.
At what point does it fail when you double-click on it? Immediately, or only when you take a certain action?
You could also add a lot of logging to it, which could indicate where the problem is too.
This is probably looking for a dll that it can't find or is finding a different version from what it wants.
You could try Process Monitor or Process Explorer from sysinternals to see what dlls it loads when it does work and where it finds them.
Try putting a System.Diagnostics.Debugger.Break()call as the first thing in Main() and you'll be asked to attach a debugger - this should definitely show you what is different betweent the 2 invocations.
I would start with identifying what is different in the two methods of execution. Is there a shortcut modifying anything?
The starting directory?
The execution account?
command line arguments?
There are 2 things that it could be:
The current directory could be different when you click on the program or run from the command prompt.
The settings and path could be different when you click on the programe you are using the standard command prompt, are you opening the visual studio command prompt when you run the program from the prompt.
If your application relies on some file that should be on the same path of that exe, that can occurr.
You will have to change the properties of the exe (or shortcut to the exe) to "Start In" the directory where your exe is. For a shortcut, right click on the shortcut -> properties -> shortcut -> Start In.
I guess that is what I think could be the cause.
EDIT: Add a Console.ReadLine towards the end of your code to make it pause for you to see any exception thrown. That should help when you run it using windows explorer.
Put a try/catch around your code and output the exception message to the console in the catch block. That should give you some clues.

Any kind of way of detecting case-sensitve filename errors?

we are making a project to run in ASP.Net on Mono/*nix
Our problem is that we develop on Windows, and we just build and test it every so often on Mono. So we have been having a lot of trouble recently with case sensitive filenames. Everything seems to work good in Windows and then we move to Mono and it's silently broken.(as in, it builds but won't run or parts of it don't work)
How would you recommend that I detect this while we are developing on Windows? Basically, how do we make the case-sensitive filenames look wrong in our code where the code works on Windows but not *nix?
One thing you can do is use MONO_IOMAP so that Mono silently corrects the errors and emulates a case-insensitive file system:
http://www.mono-project.com/IOMap
Another thing you can use to actually find the issues is a new "profiler module" that logs every time a string triggers MONO_IOMAP and tells you where in your code it was created:
http://twistedcode.net/blog/post/2009/12/21/A-utility-to-help-porting-Windows-NET-applications-to-MonoUnix.aspx
You could use a compiler directive which would indicate when you are building for *nix systems which would validate the file paths.

Categories