C# Run command on command prompt and show the command - c#

I am trying to create an app that starts cmd.exe and send command. It is important that the command is visible on cmd. Here is that I got so far but it doesn't seem to be working. Any idea?
Process myProc = new Process();
myProc.StartInfo.FileName = "cmd.exe";
myProc.StartInfo.RedirectStandardInput = true;
myProc.StartInfo.RedirectStandardOutput = true;
myProc.StartInfo.UseShellExecute = false;
myProc.Start();
StreamWriter sendCommand = myProc.StandardInput;
sendCommand.WriteLine("run.exe --forever"); //I want this command to show up in cmd
When the code above is executed, run.exe is ran but the command does not show up in cmd.
What am I doing wrong?

Here's an addendum to my comment to make it clearer:
Process myProc = new Process();
myProc.StartInfo.FileName = "cmd.exe";
myProc.StartInfo.RedirectStandardInput = true;
//myProc.StartInfo.RedirectStandardOutput = true;
myProc.StartInfo.UseShellExecute = false;
myProc.Start();
System.IO.StreamWriter sendCommand = myProc.StandardInput;
sendCommand.WriteLine("run.exe --forever");
This will allow everything outputted by cmd to show in the cmd console.

why you are using the streamwriter ?
you can use the Arguments
myProc.StartInfo.Arguments="run.exe --forever";

Related

How to import a Windows Power Plan with C#

I'm working on a small C# app that will import a power plan to the user's PC and set it as active.
It working perfectly with a .bat file when the .pow file is in the same folder and I'm running commands:
powercfg -import "%~dp0\Optimized.pow"
powercfg /setactive 62ffd265-db94-4d48-bb7a-183c87641f85
Now, in C# I tried this:
Process cmd = new Process();
cmd.StartInfo.FileName = "powercfg";
cmd.StartInfo.Arguments = "-import \"%~dp0\\Optimized\"";
cmd.StartInfo.Arguments = "powercfg /setactive 62ffd265-db94-4d48-bb7a-183c87641f85";
cmd.Start();
//and this:
private void button1_Click(object sender, EventArgs e)
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine("powercfg -import \"%~dp0\\Optimized\"");
cmd.StandardInput.WriteLine("powercfg /setactive 6aa8c469-317b-45d9-a69c-f24d53e3aff5");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
But the program doesn't see the .pow file in the project folder (I actually tried to put it in each and every folder in the project).
How it can be implemented to let the powercfg see the file?
Any help is much appreciated!
Thanks!
You could try something like this:
var cmd = new Process {StartInfo = {FileName = "powercfg"}};
using (cmd) //This is here because Process implements IDisposable
{
var inputPath = Path.Combine(Environment.CurrentDirectory, "Optimized.pow");
//This hides the resulting popup window
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
//Prepare a guid for this new import
var guidString = Guid.NewGuid().ToString("D"); //Guid without braces
//Import the new power plan
cmd.StartInfo.Arguments = $"-import \"{inputPath}\" {guidString}";
cmd.Start();
//Set the new power plan as active
cmd.StartInfo.Arguments = $"/setactive {guidString}";
cmd.Start();
}
This fixes the Arguments parameter that is being overwritten/used twice, as well as correctly disposes of the cmd variable. Additional lines added to hide the resulting pop-up window, and for generating the Guid upfront and specifying it as part of the command line.
Your first snippet does not work because you're reassigning cmd.StartInfo.Arguments before executing the process. The first assignment is lost when you throw it out in favor of the second assignment.
The first snippet most likely doesn't work because when you set cmd.startInfo.FileName to just a filename with no path, it will search only the directory of your C# app's .exe (likely in project/bin/Debug/). Since the FileName is cmd.exe and there is probably no cmd.exe in your project folder, it can't find anything.
You may also consider setting cmd.StartInfo.WorkingDirectory to an appropriate directory with your .pow file so that your relative paths will resolve correctly.

Activating conda environment from c# code (or what is the differences between manually opening cmd and opening it from c#?)

I want to run a gpu accelerated python script on windows using conda environment (dlwin36).
I’m trying to activate dlwin36 and execute a script:
1) activate dlwin36
2) set KERAS_BACKEND=tensorflow
3) python myscript.py
If I manually open cmd on my machine and write:"activate dlwin36"
it works.
But when I try opening a cmd from c# I get:
“activate is not recognized as an internal or external command, operable program or batch file.”
I tried using the following methods:
Command chaining:
var start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.Arguments = "/c activate dlwin36&&set KERAS_BACKEND=tensorflow&&python myscript.py";
Process.Start(start).WaitForExit();
(I’ve tested several variations of UseShellExecute, LoadUserProfile and WorkingDirectory)
Redirect standard input:
var commandsList = new List<string>();
commandsList.Add("activate dlwin36");
commandsList.Add("set KERAS_BACKEND=tensorflow");
commandsList.Add("python myscript.py");
var start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.UseShellExecute = false;
start.RedirectStandardInput = true;
var proc = Process.Start(start);
commandsList.ForEach(command => proc.StandardInput.WriteLine(command));
(I’ve tested several variations of LoadUserProfile and WorkingDirectory)
In both cases, I got the same error.
It seems that there is a difference between manually opening cmd and opening it from c#.
The key is to run activate.bat in your cmd.exe before doing anything else.
// Set working directory and create process
var workingDirectory = Path.GetFullPath("Scripts");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
UseShellExecute = false,
RedirectStandardOutput = true,
WorkingDirectory = workingDirectory
}
};
process.Start();
// Pass multiple commands to cmd.exe
using (var sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
// Vital to activate Anaconda
sw.WriteLine("C:\\PathToAnaconda\\anaconda3\\Scripts\\activate.bat");
// Activate your environment
sw.WriteLine("activate your-environment");
// Any other commands you want to run
sw.WriteLine("set KERAS_BACKEND=tensorflow");
// run your script. You can also pass in arguments
sw.WriteLine("python YourScript.py");
}
}
// read multiple output lines
while (!process.StandardOutput.EndOfStream)
{
var line = process.StandardOutput.ReadLine();
Console.WriteLine(line);
}
You need to use the python.exe from your environment. For example:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\path-to-Anaconda3\envs\tensorflow-gpu\python.exe";
or in your case:
start.Arguments = "/c activate dlwin36&&set KERAS_BACKEND=tensorflow&&\"path-to-Anaconda3\envs\tensorflow-gpu\python.exe\" myscript.py";
I spent a bit of time working on this and here's the only thing that works for me: run a batch file that will activate the conda environment and then issue the commands in python, like so. Let's call this run_script.bat:
call C:\Path-to-Anaconda\Scripts\activate.bat myenv
set KERAS_BACKEND=tensorflow
python YourScript.py
exit
(Note the use of the call keyword before we invoke the activate batch file.)
After that you can run it from C# more or less as shown above.
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.Arguments = "/K c:\\path_to_batch\\run_script.bat";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.WorkingDirectory = "c:\\path_to_batch";
string stdout, stderr;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
stdout = reader.ReadToEnd();
}
using (StreamReader reader = process.StandardError)
{
stderr = reader.ReadToEnd();
}
process.WaitForExit();
}
I am generating the batch file on the fly in C# to set the necessary parameters.
If this is gonna help anyone in the future. I found that you must run the activation from C:\ drive.

Executing "systeminfo" cmd command WaitForExit doesn't continue

I try execute systeminfo cmd commnand and I have a problem. My problem is that when it comes to method WaitForExit(), the program doesn't continue. I try
using (var 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.WriteLine("systeminfo");
cmd.StandardInput.Flush();
cmd.WaitForExit();
var result = cmd.StandardOutput.ReadToEnd();
cmd.StandardInput.Close();
cmd.StandardOutput.Close();
return result;
}
Is there a particular reason you go through cmd here? That's so utterly unnecessary here and also explains your problem. You run an interactive instance of cmd, pretending as if you typed systeminfo and then wait for cmd to exit. Just as a normal interactive instance, it won't do that. It will just sit there, waiting for more commands. Instead, why not just call systeminfo directly?
using (var systeminfo= new Process
{
FileName = "systeminfo",
RedirectStandardOutput = true,
CreateNoWindow = false,
UseShellExecute = false,
})
{
systeminfo.Start();
var result = systeminfo.StandardOutput.ReadToEnd();
systeminfo.WaitForExit();
return result;
}
You can try the following options:
Option 1:
Subscribe to Process.Exited event and when the systeminfo process exits, read the stream to get the result of the process.
Option 2:
Redirect the systeminfo process output to a text file. When process exists event occurs, read the result from the text file.
also instead of cmd.StandardInput.WriteLine("systeminfo"); pass the systeminfo process as the argument. It will provide you more control.
ex: cmd.StartInfo.Arguments = "/C systeminfo.exe";
You must add command to cmd, cmd run that and return results and exit.
Use command like "cmd /c ver" works fine and return windows version.

WPF Run CMD line with simple argument, print output - without batch file

I'm having some difficulty doing this without using a batch file. What I want to do is when a button is clicked, run the command line with a simple argument that I specify.
Here's my code so far:
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe");
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.UseShellExecute = true;
startInfo.Arguments = "dir";
Process.Start(startInfo);
string output = Process.StandardOutput.ReadToEnd();
txtblkOutput.Text = output;
However, this just opens a cmd window and nothing happens. The text box remains blank.
However I can do this:
var process = new Process();
process.StartInfo.FileName = "C:/Users/user/Documents/SUB-20 Tool/commands.bat";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
txtblkOutput.Text = output;
Inside the batch file it just says dir. And this works, I get the output sent to my textbox.
Why does this work only with a batch file? Can I do this without it, with just using the argument property?
This is the excepted behaviour. When you execute cmd.exe with the argument dir, it does not execute the command.
As an exemple, see the screenshot below :
The correct way to execute a command in the arguments is the following :
cmd.exe /C <command>

How to send commands to cmd in C#

I am coding a program in C# and I need to open cmd.exe, send my commands and get its answers.
I searched around and found some answers to take diagnostics.process in use.
Now, I have two problems:
When I get the output of process, the output is not shown on the cmd consoule itself.
I need to call g95 compiler on the system. When I call it from cmd manually, it is invoked and does well, but when I call it programmatically, I have the this error: "g95 is not recognized as an internal or external ..."
On the other hand, I only found how to send my commands to cmd.exe via arguments and process.standardInput.writeline(). Is there any more convenient method to use. I need to send commands when the cmd.exe is open.
I am sending a part of my code which may help:
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
myProcess.StartInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe");
//myProcess.StartInfo.Arguments = "/c g95";
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_ErrorDataReceived);
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();
myProcess.StandardInput.WriteLine("g95 c:\\1_2.f -o c:\\1_2.exe");
You can specify the g95 directly and pass the desired command line parameters to it. You don't need to execute cmd first. The command may not be regognized because the settings from the user profile are not loaded. Try setting the property LoadUserProfile in StartInfo to true.
myProcess.StartInfo.LoadUserProfile = true;
This should also set the path variables correctly.
Your code would look something like this:
Process myProcess = new Process();
myProcess.StartInfo = new ProcessStartInfo("g95");
myProcess.StartInfo.Arguments = "c:\\1_2.f -o c:\\1_2.exe"
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.LoadUserProfile = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.OutputDataReceived += myProcess_OutputDataReceived;
myProcess.ErrorDataReceived += myProcess_ErrorDataReceived;
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();
You are getting the error
"g95 is not recognized as an internal or external ..."
because you haven't added the path to g95.exe in your PATH environment variable. You will get similar result if you open up command prompt and type g95. Here is a link to G95 Windows FAQ page that explains it.

Categories