Start a command line including arguments from C# - c#

I need to start a complete command line like "app.exe /arg1:1 /arg2:true" from my C# app.
Process.Start and ProcessStartInfo needs to have the filename and arguments property set. Is there a way to mimic a true shell-like execute (like the one when you press WIN+R)?

Yes, you can launch cmd.exe with the full command-line you want to send as the arguments.
info.FileName = "cmd.exe";
info.Arguments = "app.exe /arg1:1 /arg2:true";

ProcessStartInfo.UseShellExecute makes Process.Start behave exactly like the Shell:
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute.aspx

I've found the solution I've been looking for: Executing another program from C#, do I need to parse the "command line" from registry myself?
Thanks again for your help!

Related

command execution in C#

I need to execute the following command, it works perfectly, if I execute it via command prompt, here the command line is using kodakprv.exe to send a print of a tiff file.
but when trying to execute it via c#, its not throwing any error but not sending the print either, tried to execute this command via xp_cmdshell in SQL, but it didn't work, in the xp_cmdshell documentation found that, quotes are not allowed for more then once, but kodakprv.exe print logic requires 3 pair of quotes
Please suggest can we use multiple quotes in C# while executing the command or suggest any better solution for it
String sCommand = "\"c:\\progra~1\\imagin~1\\kodakprv.Exe\" /pt \"D:\\SQLDev\\Dlls\\Testing.TIF\" \"\\\\Galactica\\C-Test1\"";
// Put your code here
System.Diagnostics.Process ExecuteCommand = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = #" /c " + sCommand.ToString();
MessageBox.Show(startInfo.Arguments);
ExecuteCommand.StartInfo = startInfo;
ExecuteCommand.Start();
You don't need all those quotes. Only paths with spaces require quotes. None of your paths have spaces.
Shortnames, as you are using, may not exist (they can be turned off), or may not have the name you think. Windows does not preserve short names, only long names.
You are running your program via CMD. Unless your command line has redirection characters (as CMD handles redirection characters) then CMD is not required. You can start your program directly, which would be the preferred way (faster, less resources used).
Your window is set to hidden. Therefore you cannot see the message it is telling you. Unhide your window.
Your program will likely exit and close the window before you can read it. Either stick a &pause at the end of the command line sent to CMD, or read what is on both StdErr and StdOut as you specify to capture them in your code.

Stop Command Prompt from closing so quickly

I'm trying to troubleshoot why the following function isn't working.
public void RunCmd()
{
string strCmdText;
strCmdText = "/C [enter command stuff here]";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
However whenever I try to run it or throw in some breakpoints, command opens, shows an error, and then closes really quickly (so quickly that I can't read anything).
Is there a way I can halt the program or figure out what's going on? Breakpoints don't seem to be working.
When I directly type it in Command Prompt instead of running it via this c# script, it the command works fine.
try this:
strCmdText = "/K [enter command stuff here]";
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
Maybe try adding a pause command?
There are a various options. Using /K will prevent the window from closing.
You can also edit your command to add a SLEEP after the main call. For example, the following will wait 2 seconds before exiting:
public void RunCmd()
{
string strCmdText = "/C \"[enter command stuff here]\" & \"SLEEP 2\"";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
Process.Start has two parameters there: the process name and the arguments to pass to the process. CMD is having a problem understanding what the argument "[enter" is. If it is not an argument CMD understands, it will immediately exit.
cin.get()
That waits for a keyboard press from the user.
create temp folder under c: then append " < c:\temp\log.txt" to the end of command. this writes the output to a file
In addition to the tip about using /K vs /C to create a shell that 'lingers', you'll probably want to inject an empty "set" command to see what environmental variables (and paths) are set in the spawned shell. In all likelihood, the difference between the successful run of your script in your own shell session and the one that fails in the spawned shell, is the environment settings in which it is run.

C# process with an input and output file

When creating a new process you can give some StartInfo with it before you start the process.
But how would one give the input of/output to parameter.
the output to is achievable through a File.WriteAllLines() with the output of the command.
But now the following must me achieved:
C:\Windows\System32\inetsrv\appcmd.exe add site /in < iisSite.xml
But when we give the
add site /in < iisSite.xml
with the arguments method of StartInfo appcmd thinks it is a parameter for it's program.
See this error
Failed to process input: The parameter
'd:\import\iisSite.xml' must begin with a / or - (HRESULT=80070057).
So we need somehow the same parsing as the command prompt would do it.
What could be possible is something like ReadAllLines and use that as an input, but I thought maybe there is a better solution.
Any suggestions?
Thanks in advance!
Stream redirection like that is a feature of the command processor cmd. If you want to do that then you need to invoke it and send your arguments. See EDIT2 and EDIT3 in this post.
EDIT
And direct from Raymond
using < is not the way to do it. Use >
so for example: appcmd.exe add site /in > iisSiteExport.xml
and have your program spit out all the output as if it was printing to the Console

Network COPY Cmds within C# - File Not Found?

I'm trying to copy a file over to a networked folder on a mapped drive. I tested out COPY in my command line which worked, so I thought I'd try automating the process within C#.
ProcessStartInfo PInfo;
Process P;
PInfo = new ProcessStartInfo("COPY \"" + "c:\\test\\test.txt" + "\" \"" + "w:\\test\\what.txt" + "\"", #"/Z");
PInfo.CreateNoWindow = false; //nowindow
PInfo.UseShellExecute = true; //use shell
P = Process.Start(PInfo);
P.WaitForExit(5000); //give it some time to finish
P.Close();
Raises an exception : System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
What am I missing? Would I have to add anything else to the command parameters?
I've tried File.Copy but it doesn't appear to work (File.Exists("<mappeddriveletter>:\\folder\\file.txt");) brings up false.
This SO post contains an example
Run Command Prompt Commands
how to do it right. You need to call cmd.exe with /c copy as a parameter.
Well, for the technical bit: copy in itself is not an executable, but merely a command interpreted by cmd. So basically, you'd have to start cmd.exe as a process, and pass it a flag that makes it run the copy command (which you'll also have to supply as a parameter).
Anyways, I'd side with Promit and recommend looking into File.Copy or something similar.
e: Ah, missed your comment on Promit's answer when I posted this.
Wouldn't it be a lot easier to use File.Copy ?

How to send series of commands to a command window process?

We have a few commands(batch files/executables) on our network path which we have to call to initialize our 'development environment' for that command window. It sets some environmental variables, adds stuff to the Path etc. (Then only whatever working commands we type will be recognized & I don't know what goes inside those initializing commands)
Now my problem is, I want to call a series of those 'working commands' using a C# program, and certainly, they will work only if the initial setup is done. How can I do that? Currently, I'm creating a batch file by scratch from the program like this for example:
file.Writeline("InitializationStep1.bat")
file.Writeline("InitializeStep2.exe")
file.Writeline("InitializeStep3.exe")
Then the actual commands
file.Writeline("Dowork -arguments -flags -blah -blah")
file.Writeline("DoMoreWork -arguments -flags -blah -blah")
Then finally close the file writer, and run this batch file.
Now if I directly execute this using Process.<strike>Run</strike>Start("cmd.exe","Dowork -arguments"); it won't run.
How can I achieve this in a cleaner way, so that I have to run the initialization commands only once? (I could run cmd.exe each time with all three initializers, but they take a lot of time so I want to do it only once)
As #Hakeem has pointed out, System.Diagnostic.Process does not have a static Run method. I think you are referring to the method Start.
Once you have completed building the batch file, then simply execute it using the following code,
Process p = new Process();
p.StartInfo.FileName = batchFilePath;
p.StartInfo.Arguments = #"-a arg1 -b arg2";
p.Start();
Note that the # symbol is required to be prefixed to the argument string so that escape sequence characters like \ are treated as literals.
Alternative code
Process.Start(batchFilePath, #"-a arg1 -b arg2");
or
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = batchFilePath;
processStartInfo.Arguments = #"-a arg1 -b arg2";
Process.Start(processStartInfo);
More information
Process.Start method
Example of multi command batch file
dir /O
pause
dir
pause
Save this file as .bat and then execute using the Start method. In this case you can specify the argument with the command in the batch file itself (in the above example, the /O option is specified for the dir command.
I suppose you already have done the batch file creation part, now just append the arguments to the commands in the batch file.
Redirecting Input to a process
Since you want to send multiple commands to the same cmd process, you can redirect the standard input of the process to the take the input from your program rather than the keyboard.
Code is inspired from a similar question at: Execute multiple command lines with the same process using C#
private string ProcessRunner()
{
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe");
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
Process process = Process.Start(processStartInfo);
if (process != null)
{
process.StandardInput.WriteLine("dir");
process.StandardInput.WriteLine("mkdir testDir");
process.StandardInput.WriteLine("echo hello");
//process.StandardInput.WriteLine("yourCommand.exe arg1 arg2");
process.StandardInput.Close(); // line added to stop process from hanging on ReadToEnd()
string outputString = process.StandardOutput.ReadToEnd();
return outputString;
}
return string.Empty;
}
The method returns the output of the command execution. In a similar fashion, you could also redirect and read the StandardOuput stream of the process.
The Process.Run method that you mentioned, is that from the Process class in System.Diagnostics namespace? AFAIK, the Process type doesn't have either a static or instance method named Run. If you haven't already I'd try with the Start method on Process, either instance or static

Categories