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.
Related
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.
I'm looking to automate nupkg creation in a c# app. I'm aiming to include nuget.exe in my project and use System.Diagnostics to launch cmd.exe as a process and then pass the required commands, which would be 'cd project\path\here', 'nuget spec something.dll' and 'nuget pack something.nuspec'.
The code I have so far is:
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo(#"C:\Windows\System32\cmd.exe", #"mkdir testdir");
p.StartInfo = info;
p.Start();
Console.ReadLine();
However, it doesn't even create the testdir, and I've got no idea how to chain those commands. There is a method called WaitForInputIdle on my p Process, but it raises events and I've got no idea how to handle those to be honest.
A perfect solution would also let me read output and input. I've tried using StreamWriter p.StandardInput, but then there's the problem of checking whether a command is finnished and what was the result.
Any help would be much appreciated.
Edit: Success! I've managed to create a directory :)
Here's my code now:
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo(#"C:\Windows\System32\cmd.exe");
info.RedirectStandardInput = true;
info.UseShellExecute = false;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
sw.WriteLine("mkdir lulz");
}
Still no idea how to await for input and follow up with more commands, though.
You can do this by three ways
1- The easiest option is to combine the two commands with the '&' symbol.
var processInfo = new ProcessStartInfo("cmd.exe", #"command1 & command2");
2- Set the working directory of the process through ProcessStartInfo.
var processInfo = new ProcessStartInfo("cmd.exe", #"your commands here ");
processInfo.UseShellExecute = false;
processInfo.WorkingDirectory = path;
3- Redirecting the input and output of the process. (Also done through the ProcessStartInfo).This is required when you like to send more input to the process, or when you want to get the output of the process
Also see this answer
I have been messing around with triggering a bash script via C#. This all works fine when I first call the "open" command with arguments which in turn opens my .command script via Terminal.
Once the "open" command is used once Terminal or iTerm will remain open in the background, at which point calling the "open" command with arguments then has no further effect. I sadly have to manually quit the application to trigger my script again.
How can I pass arguments to an already open terminal application to restart my script without quitting?
I've searched online ad can't seem to work it out, it already took a good amount of time solve the opening code. Your help is much appreciated.
Here is the C# code I'm using to start the process:
var p = new System.Diagnostics.Process();
p.StartInfo.FileName = "open";
p.StartInfo.WorkingDirectory = installFolder;
p.StartInfo.Arguments = "/bin/bash --args \"open \"SomePath/Commands/myscript.command\"\"";
p.Start();
Thanks
EDIT:
Both answers were correct, this might help others:
ProcessStartInfo startInfo = new ProcessStartInfo("/bin/bash");
startInfo.WorkingDirectory = installFolder;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.StandardInput.WriteLine("echo helloworld");
process.StandardInput.WriteLine("exit"); // if no exit then WaitForExit will lockup your program
process.StandardInput.Flush();
string line = process.StandardOutput.ReadLine();
while (line != null)
{
Debug.Log("line:" + line);
line = process.StandardOutput.ReadLine();
}
process.WaitForExit();
//process.Kill(); // already killed my console told me with an error
You can try:
before calling p.Start():
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
// for the process to take commands from you, not from the keyboard
and after:
if (p != null)
{
p.StandardInput.WriteLine("echo helloworld");
p.StandardInput.WriteLine("executable.exe arg1 arg2");
}
(taken from here)
This is what you may be looking for :
Gets a stream used to write the input of the application.
MSDN | Process.StandardInput Property
// This could do the trick
process.StandardInput.WriteLine("..");
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";
I'm trying to launch an application from c# code. Below is the code.. But the exe gives the error "Application has encountered a problem and needs to close. Sorry for the inconvenience".
I'm passing the command values as
command = "\"C:\\Program Files\\Nimbuzz\\Nimbuzz.exe\"";
code:
private int ExecuteSystemCommand(string command)
{
procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = false;
proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
return proc.Id;
}
But the exe opens normally when opened from the desktop short cut. I dont know whats wrong. Please suggest.
You must specify the EXE you want to execute.
Process.Start("cmd.exe", ...)
It would appear that these articles answer the question:
ProcessStartInfo.UseShellExecute
ProcessStartInfo.FileName
Well I just found out that, I need to set the Working directory first before calling the Process.Start()
Directory.SetCurrentDirectory("C:\\Program Files\\Nimbuzz\\");