How continuously communicate to Cmd? - c#

I found how to open cmd in C#.
But I can use Inputstream only once.
Create Cmd Process
ProcessStartInfo CmdInfo = new ProcessStartInfo();
Process cmd = new Process();
CmdInfo.FileName = #"cmd";
CmdInfo.WindowStyle = ProcessWindowStyle.Hidden;
CmdInfo.CreateNoWindow = true;
CmdInfo.UseShellExecute = false;
CmdInfo.RedirectStandardInput = true;
CmdInfo.RedirectStandardOutput = true;
CmdInfo.RedirectStandardError = true;
cmd.EnableRaisingEvents = false;
cmd.StartInfo = CmdInfo;
cmd.Start();
Now we can use cmd.StandardInput and cmd.StandardOutput.
Use Cmd
// Use cmd 1
cmd.StandardInput.WriteLine("cd");
cmd.StandardInput.Close(); // if don't close, I can't get output
Console.WriteLine( cmd.StandardOutput.ReadToEnd() ); // Done!
// Use cmd 2
cmd.StandardInput.WriteLine("cd C:\"); // It will occure ObjectDisposedException
I want solve this problem.

I don't think you're going to get far with that approach. The code is a hint ProcessStart ! It's a new process! After you've started the process it's completely seperate to the one in which your code resides, the only way you would be able to communicate with this new process is via COM or remoting or some other inter application communication channel... MSMQ etc.
As far as I know the cmd (command prompt) offers none of these.
I think you'll want to study up on powershell...
Calling PowerShell From C#
http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C
etc etc

The command shell executable will not process commands from a redirected standard input until the input is closed.
You have three choices:
Create a new process for each command.
Pipeline all of the commands that you want to execute, then close the standard input handle.
Create a batch file containing all of the commands and then execute that.
If you choose to create a new process for each command, use cmd.exe's "/C" command line switch to execute the command rather than passing it through standard input.

Related

How to execute 2 different commands cmd on C#

I was working on a project which needs to run two cmd commands on C#, I looked up on how to do it but nothing worked for me, and everyone was giving the solution to execute only one cmd command.
I would like to execute one command when the user clicks a button, then another one right after, without quitting the cmd, and if possible to hide the cmd window.
My goal would be to execute the 2 following commands in the cmd, to run a Run.bat file:
cd C:\users\user\documents\file
Run.bat
Thanks.
You can directly call "C:\users\user\documents\file\Run.bat" and set the working directory as well as the shell execute flag :
string path = #"C:\users\user\documents\file\";
var process = new System.Diagnostics.Process();
process.StartInfo.FileName = path + "Run.bat";
process.StartInfo.WorkingDirectory = path;
process.StartInfo.UseShellExecute = true;
process.Start();
//process.WaitForExit();

C# command line execute commands belongs to another executable

Below is the code where I'm trying to run one command with argument. (Call Tectia SFTP client profile & upload file)
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.Arguments = $"/c sftpg3 {profile}";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
using (StreamWriter sw = cmd.StandardInput){
if (sw.BaseStream.CanWrite)
sw.WriteLine($"/c sput {filename} {output}");
}
After the process started, it logins into the into the SFTP and stucked. It won't input the next command as it deemed as another program.
Would like to ask how does it execute the next command after login? I tried Calling CMD with && concatenating and it won't works too. We can only use SFTP via command line as client requested.
Launch sftpg3 with the -B - option to read from standard input.
Launch sftpg3 with the -B <filename> option to read from a batch
file of commands.
More details of command line arguments is available in the documentation.
Also, I don't think you want to write /c the second time around. /c is just something passed to cmd.exe. On that note, why are you calling cmd.exe instead of the binary directly?

Writing and executing multiple lines sequentially in an elevated command prompt using c#

Am a Newbie in C# and I have 3 commands(command2, command3 and command4) I need to execute in the elevated command prompt and I will also like to view the execution process as it happens. Currently, the problem is that the code below just opens the elevated command prompt and without executing the commands. I also seek better interpretations of the lines if wrong.
My code and Interpretation/Understanding of each line based on reviews of similar cases: ConsoleApp1
class Program
{
static void Main(string[] args)
{
string command2 = #"netsh wlan";
string command3 = #" set hostednetwork mode=true ssid=egghead key=beanhead keyusage=persistent";
string command4 = #" start hostednetwork";
string maincomm = command2.Replace(#"\", #"\\") + " " + command3.Replace(#"\", #"\\") ; //I merged commands 2 and 3
ProcessStartInfo newstartInfo = new ProcessStartInfo();
newstartInfo.FileName = "cmd"; //Intend to open cmd. without this the newProcess hits an error saying - Cannot run process without a filename.
newstartInfo.Verb = "runas"; //Opens cmd in elevated mode
newstartInfo.Arguments = maincomm; //I intend to pass in the merged commands.
newstartInfo.UseShellExecute = true; //
newstartInfo.CreateNoWindow = true; // I intend to see the cmd window
Process newProcess = new Process(); //
newProcess.StartInfo = newstartInfo; //Assigns my newstartInfo to the process object that will execute
newProcess.Start(); // Begin process and Execute newstartInfo
newProcess.StartInfo.Arguments = command4; //I intend to overwrite the initial command argument hereby passing the another command to execute.
newProcess.WaitForExit(); //
}
}
This is what I did to overcome the challenge and It gave me exactly what I wanted. I modified my code to use the System.IO to write directly to the elevated command prompt.
ProcessStartInfo newstartInfo = new ProcessStartInfo();
newstartInfo.FileName = "cmd";
newstartInfo.Verb = "runas";
newstartInfo.RedirectStandardInput = true;
newstartInfo.UseShellExecute = false; //The Process object must have the UseShellExecute property set to false in order to redirect IO streams.
Process newProcess = new Process();
newProcess.StartInfo = newstartInfo;
newProcess.Start();
StreamWriter write = newProcess.StandardInput ; //Using the Streamwriter to write to the elevated command prompt.
write.WriteLine(maincomm); //First command executes in elevated command prompt
write.WriteLine(command4); //Second command executes and Everything works fine
newProcess.WaitForExit();
Referrence: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardinput(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo(v=vs.110).aspx
I think an understanding of some properties of the ProcessStartInfo might clear things.
The verb - Gets or sets the verb to use when opening the application or document specified by the FileName property.,
+The UseShellExecute - Gets or sets a value indicating whether to use the operating system shell to start the process.
+The FileName - Gets or sets the application or document to start MSDN Docs
When you use the operating system shell to start processes, you can start any document (which is any registered file type associated with an executable that has a default open action) and perform operations on the file, such as printing, by using the Process object. When UseShellExecute is false, you can start only executables by using the Process object Documentation from MSDN.
In my case, cmd is an executable. the verb property is some thing that answers the question "How should my I run my FileName(for executables e.g cmd or any application)?" for which I answered - "runas" i.e run as administrator. When the FileName is a document (e.g `someFile.txt), the verb answers the question "What should I do with the file for which answer(verb) could be -"Edit","print" etc. also?"
use true if the shell should be used when starting the process; false if the process should be created directly from the executable file. The default is true MSDN Docs - UserShellInfo.
Another thing worth noting is knowing what you are trying to achieve. In my case, I want to be able to run commands via an executable(cmd prompt) with the same process - i.e starting the cmd as a process I can keep track of.

Running cmd with C# and parameter

I have to compile a game like this
love "C:\testgame"
in the cmd. So I use this code, but it seems like the parameter is missinterpreted. Also, the console closes after a sec. But if I use Messagebox.Show I can see the command in the cmd is the same I manually use (and this works)
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput =
true;
cmd.StartInfo.RedirectStandardOutput =
true;
cmd.StartInfo.CreateNoWindow = false;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.Write(#"cd %ProgramFiles(x86)%\LOVE\");
MessageBox.Show("love \""+fldBrowDiag.SelectedPath.ToString()+#"\"+lsb_projects.SelectedItem.ToString()+"\"");
cmd.StandardInput.Close();
cmd.Close();
First, the "cd" command you issue will probably fail because you don't have quotes around the argument. (that program files env variable will have spaces in it.)
Second, instead of writing to stdin directly, maybe consider using the "/c" switch that will instruct cmd.exe to execute the specified commands directly. You can separate the commands with '&&'.
Try this to simplify things:
var process = Process.Start(
new ProcessStartInfo(#"C:\Program Files (x86)\LOVE\love.exe", #"C:\game") {
WorkingDirectory = #"C:\Program Files (x86)\LOVE" });
Why can't you just start cmd with the correct arguments to launch your process?
eg cmd /C love "c:\game" to close after finish or cmd /K love "c:\game to leave open after finish?

c# redirect (pipe) process output to another process

I am trying to run a process in c# using the Process class.
Process p1 = new process();
p1.startinfo.filename = "xyz.exe";
p1.startinfo.arguments = //i am building it based on user's input.
p1.start();
So based on user input i am building the argument value. Now i have a case where i have to pipe the output of p1 to another process say grep. so i basically tried this
p1.startinfo.arguments = "-info |grep 1234" ;
what i intended is something like xyz.exe -info|grep 1234
but this doesn't seem to work in .net .. I can actually create another process variable and run "grep" as a separate process.. But i was wondering if there is any way to do as iam trying out above..
The much easier way would be to do just use cmd as your process.
Process test = new Process();
test.StartInfo.FileName = "cmd";
test.StartInfo.Arguments = #"/C ""echo testing | grep test""";
test.Start();
You can capture the output or whatever else you want like any normal process then. This was just a quick test I built, but it works outputting testing to the console so I would expect this would work for anything else you plan on doing with the piping. If you want the command to stay open then use /K instead of /C and the window will not close once the process finishes.

Categories