Running cmd commands via .NET? - c#

System.Diagnostics.Process proc0 = new System.Diagnostics.Process();
proc0.StartInfo.FileName = "cmd";
proc0.StartInfo.WorkingDirectory = Path.Combine(curpath, "snd");
proc0.StartInfo.Arguments = omgwut;
And now for some background...
string curpath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
omgwut is something like this:
copy /b a.wav + b.wav + ... + y.wav + z.wav output.wav
And nothing happens at all. So obviously something's wrong. I also tried "copy" as the executable, but that doesn't work.

Try the prefixing your arguments to cmd with /C, effectively saying cmd /C copy /b t.wav ...
According to cmd.exe /? using
/C <command>
Carries out the command specified by
string and then terminates
For your code, it might look something like
// ..
proc0.StartInfo.Arguments = "/C " + omgwut;
Notes:
A good way to test whether your command is going to work is to actually try it from a command prompt. If you try to do cmd.exe copy ... you'll see that the copy doesn't occur.
There are limits to the length of the arguments you can pass as arguments. From MSDN: "The maximum string length is 2,003 characters in .NET Framework applications and 488 characters in .NET Compact Framework applications."
You can bypass the shelling out to command by using the System.IO classes to open the files and manually concatenate them.

Try this it might help you.. Its working with my code.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
Console.WriteLine(result);
}
catch (Exception objException)
{
// Log the exception
}

Even you can try this.. this is even better.
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents=false;
proc.StartInfo.FileName="iexplore";
proc.StartInfo.Arguments="http://www.microsoft.com";
proc.Start();
proc.WaitForExit();
MessageBox.Show("You have just visited " + proc.StartInfo.Arguments);

Daniels cmd /c idea will work. Keep in mind there is a limit to the length of a command line probably 8k in your case see this for details.
Since you are in a .Net app anyway, File.Copy may be quite a bit easier/cleaner than this approach.

Related

how to execute a terminal command in c#

I read many post, from them there is this one
c# - Opening the terminal process and pass commands?
I do the exact same thing in my code
Process proc = new System.Diagnostics.Process ();
proc.StartInfo.FileName = "/bin/bash";
proc.StartInfo.Arguments = "-c \" " + command + " \"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start ();
where command = export DISPLAY=:0.0
and it goes to my catch, "pplicationName='/bin/bash', CommandLine='-c " cd .. "', CurrentDirectory='', Native error= The system cannot find the file specified."
what do I do differently? even if I try to juste set command = "cd .." it doesn't work
You should probably try setting the full path the executable.
proc.StartInfo.FileName = "C:/SOMEPATH/Bash.exe";
I'm assuming as you are specifying a relative path, it's not resolving it. Possibly because you aren't setting a working directory for the process so it's current dir and the current dir you think it has, are different.

Maintaining variables when executing cmd from C# application

I want to call some cmd prompt commands from a .net C# application. However before the command is run I need to set up a varaibles within a batch file. Is there a way to maintain the variables to subsequent calls to the command prompt?
I provide an example below of the problem.
Say I have a simple batch file C:\setEnv.bat containing
set notepad=C:\windows\system32\notepad.exe
Then if I have C# code like thus:
var proc1 = new ProcessStartInfo();
string cmd1 = #"CALL C:\setEnv.bat";
string cmd2 = #"ECHO notepad=%notepad%>C:\test.txt";
proc1.UseShellExecute = true;
var process = new Process();
var startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " +cmd1;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
startInfo.Arguments = "/C " + cmd2;
process.Start();
process.WaitForExit();
Now I'm guessing that the /C is terminating the command prompt thus losing my variables but if I don't have it then the cmd prompt doesn't return after finishing the command.
I thought I could double the cmd1 & cmd2 to a single call but then I would need to do that for every call to the cmd prompt and feels a little redundant calling C:\setenv.bat again and again.
You may use way in this question
For example, use command "set" in cmd1:
string cmd1 = "\" CALL C:\\setEnv.bat && set \"";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
//...
process.Start();
string variables = process.StandardOutput.ReadToEnd();
// next parse variables string
And before start second process set parsed variables in "startInfo.EnvironmentVariables"
A few issues/ideas:
1) How many values to you need to track from one execution to the next? Primarily, can you just use the errorlevel return value or do you need more details?
2) Can you pipe the results of the first directly into the second as one call?
3) Can you output the values from the first call to a file and in the 2nd call, pipe that as input into the 2nd cmd?
4) I assume that you have some processing that is done after the first cmd is run, but before the 2nd cmd is called. Could you create an .exe that can be called by the 1st batch file (after the other code) that does that processing. That way, you have 3 cmds all of which can be run in the same environment and your variables stick around.

Using Process in java

I'm converting some c# code to java
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
This is the code that i try to convert it to java.
I dont know how to run a command and use process in java. I googled it and i found something like that :
Process process = Runtime.getRuntime().exec(command);
Integer result = process.exitValue();
In the line
process.exitValue()
it gives me java.lang.IllegalThreadStateException: process has not exited.
After exec you need to wait for the command to finish with process.waitFor().
process.exitValue() gets the number from System.exit(number)
The error is thrown since the process hasn't exited yet.
From the c# code it looks like you want to get the command's output, this can be done by:
int i=0;
String result = new String();
while((i = process.getInputStream().read()) >= 0)
result += (char)i;
System.out.println(result);

running dos command line from C#?

I am trying to run this command from command-line prompt:
"D:\\fiji\\fiji.exe -macro D:\\fiji\\macros\\FFTBatch.ijm --headless"
It works perfect when I type it in a command-line console.
However, when I was trying to make it work from C# application, it failed. I tried following, but seems the command above did not get executed somehow:
string fijiCmdText = "D:\\fiji\\fiji.exe -macro D:\\fiji\\macros\\FFTBatch.ijm --headless";
System.Diagnostics.Process.Start("cmd.exe", fijiCmdText);
Anyone has any idea how to change it to work? Thanks.
The problem was solved as in the direction Chris Haas pointed out. It does not mean other answers don't work, it just means the problem can be solved at least in one way.
Here it is, simply adding "/C " in the code, and it should work:
Original that did not work:
string fijiCmdText = "D:\\fiji\\fiji.exe -macro D:\\fiji\\macros\\FFTBatch.ijm --headless";
System.Diagnostics.Process.Start("cmd.exe", fijiCmdText)
;
Current code that works:
string fijiCmdText = "/C D:\\fiji\\fiji.exe -macro D:\\fiji\\macros\\FFTBatch.ijm --headless";
System.Diagnostics.Process.Start("cmd.exe", fijiCmdText);
Here is the reference mentioned by Chris Haas. See EDIT3
You don't have to run cmd.exe, just create ProcessStartInfo object and pass the command with its parameters to it. Like this:
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("your command", "parameters");
Here is an example that shows you how to do it:
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("tree.com", "/f /a");
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = info;
p.Start();
p.WaitForExit();
So in your case, this is your command: "D:\\fiji\\fiji.exe" and this is your command parameters or arguments: #"-macro D:\\fiji\\macros\\FFTBatch.ijm --headless"
Try This:
ProcessStartInfo info = new ProcessStartInfo(#"D:\fiji\fiji.exe",#"-macro D:\fiji\macros\FFTBatch.ijm --headless");
Process process = new Process();
process.StartInfo = info;
process.Start();

To run cmd as administrator along with command?

Here is my code:
try
{
ProcessStartInfo procStartInfo = new ProcessStartInfo(
"cmd.exe",
"/c " + command);
procStartInfo.UseShellExecute = true;
procStartInfo.CreateNoWindow = true;
procStartInfo.Verb = "runas";
procStartInfo.Arguments = "/env /user:" + "Administrator" + " cmd" + command;
///command contains the command to be executed in cmd
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I want to keep
procStartInfo.UseShellExecute = true
procStartInfo.RedirectStandardInput = false;
Is it possible to execute the command without using process.standardinput?
I try to execute command I've passed in argument but the command does not executes.
As #mtijn said you've got a lot going on that you're also overriding later. You also need to make sure that you're escaping things correctly.
Let's say that you want to run the following command elevated:
dir c:\
First, if you just ran this command through Process.Start() a window would pop open and close right away because there's nothing to keep the window open. It processes the command and exits. To keep the window open we can wrap the command in separate command window and use the /K switch to keep it running:
cmd /K "dir c:\"
To run that command elevated we can use runas.exe just as you were except that we need to escape things a little more. Per the help docs (runas /?) any quotes in the command that we pass to runas need to be escaped with a backslash. Unfortunately doing that with the above command gives us a double backslash that confused the cmd parser so that needs to be escaped, too. So the above command will end up being:
cmd /K \"dir c:\\\"
Finally, using the syntax that you provided we can wrap everything up into a runas command and enclose our above command in a further set of quotes:
runas /env /user:Administrator "cmd /K \"dir c:\\\""
Run the above command from a command prompt to make sure that its working as expected.
Given all that the final code becomes easier to assemble:
//Assuming that we want to run the following command:
//dir c:\
//The command that we want to run
string subCommand = #"dir";
//The arguments to the command that we want to run
string subCommandArgs = #"c:\";
//I am wrapping everything in a CMD /K command so that I can see the output and so that it stays up after executing
//Note: arguments in the sub command need to have their backslashes escaped which is taken care of below
string subCommandFinal = #"cmd /K \""" + subCommand.Replace(#"\", #"\\") + " " + subCommandArgs.Replace(#"\", #"\\") + #"\""";
//Run the runas command directly
ProcessStartInfo procStartInfo = new ProcessStartInfo("runas.exe");
procStartInfo.UseShellExecute = true;
procStartInfo.CreateNoWindow = true;
//Create our arguments
string finalArgs = #"/env /user:Administrator """ + subCommandFinal + #"""";
procStartInfo.Arguments = finalArgs;
//command contains the command to be executed in cmd
using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
proc.StartInfo = procStartInfo;
proc.Start();
}
why are you initializing the process object with arguments and then later on override those Arguments? and btw: the last bit where you set Arguments you concatenate 'command' right upto 'cmd', that doesn't make much sense and might be where it fails (looks like you're missing a space).
Also, you are currently using the standard command line, you might want to look into using the runas tool instead. you can also call runas from command line.
Also, why are you running 'command' from the command line? why not start it directly from Process.Start with admin privileges supplied then and there? here's a bit of pseudocode:
Process p = Process.Start(new ProcessStartInfo()
{
FileName = <your executable>,
Arguments = <any arguments>,
UserName = "Administrator",
Password = <password>,
UseShellExecute = false,
WorkingDirectory = <directory of your executable>
});

Categories