C# Multiple Input and Output to a Single CMD Process - c#

Hi how do i enter a command to a cmd process which is already started by my application and also to redirect the output back. After that i want to enter my input again.
static void Main(string[] args)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.CreateNoWindow = false;
psi.FileName = "cmd.exe";
psi.Arguments = "/k";
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
Process p = new Process();
p.StartInfo = psi;
p.Start();
while(true)
{
p.StandardInput.WriteLine(Console.ReadLine());
Console.WriteLine(p.StandardOutput.ReadToEnd());
}
Console.Read();
}

Related

How can i pass multiple commands same time in this code

I'm trying to run cmd from local folder and wanted to pass multiple commands at the same time Eg: once i'm able to run this command, p.StandardInput.WriteLine("multichain-util create chain34");after executing this i want to pass this command p.StandardInput.WriteLine("multichai-cli chain 34 -daemon")
class Program
{
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.WorkingDirectory = #"D:\multichain-windows-2.0.2";
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
p.StandardInput.WriteLine("multichain-util create chain34");
p.StandardInput.Flush();
p.StandardInput.Close();
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd());
Console.ReadKey();
}
}
Move all process related stuff into a method. Take in a list of commands as a parameter for that command. And then instead of one p.StandardInput.WriteLine(), iterate through the list of commands and write them all.
static void Main()
{
var commands = new List<string>() { "dir", "mkdir ABC", "dir" };
ExecuteCmd(commands);
Console.ReadLine();
}
static void ExecuteCmd(List<string> commands)
{
Process p = new Process();
p.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
foreach (var comm in commands)
p.StandardInput.WriteLine(comm);
p.StandardInput.Flush();
p.StandardInput.Close();
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd());
}

Reading Output from cmd getting errors

i have been looking up "how to get standard output from cmd" and i found a few tutorials, but none, yes NONE seemed to work, im trying to read all the output that "cmd.exe" has for me.
heres the whole code, Scroll down for the error location
public static string C(string arguments, bool b)
{
System.Diagnostics.Process process = new
System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new
System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle =
System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = arguments;
process.StartInfo = startInfo;
process.Start();
string res = "";
if (b)
{
StringBuilder q = new StringBuilder();
while (!process.HasExited)
{
q.Append(process.StandardOutput.ReadToEnd());
}
string r = q.ToString();
res = r;
}
if(res == "" || res == null)
{
return "NO-RESULT";
}
return res;
}
Where i get my error (System.InvalidOperationException: 'StandardOut has not been redirected or the process hasn't started yet.')
string res = "";
StringBuilder q = new StringBuilder();
while (!process.HasExited)
{
q.Append(process.StandardOutput.ReadToEnd()); // Right here
}
string r = q.ToString();
res = r;
You are creating a ProcessStartInfo named startInfo, then set some properties on process.StartInfo and then assign startInfo to process.StartInfo basically reverting what you set previously.
You should be setting RedirectStandardOutput, RedirectStandardInput and UseShellExecute on the startInfo:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = arguments;
process.StartInfo = startInfo;
process.Start();

C# with WMIC command

I'm trying to execute wmic command on C# and get the output, but the function is only returning first line and the command which is not running.
Code:
private static String wimc(String cmd)
{
var psi = new ProcessStartInfo("wmic");
psi.Arguments = #"shadowcopy call create Volume='C:\'";
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
var p = Process.Start(psi);
p.WaitForExit();
String output = p.StandardOutput.ReadToEnd();
return output;
}
Output on C#:
Executing (Win32_ShadowCopy)->create()
Only show first line and command not working
Cmd output(expected)
Executing (Win32_ShadowCopy)->create() Method execution successful. Out Parameters: instance of __PARAMETERS {
ReturnValue = 0;
ShadowID = "{B2FDCFDE-7C48-4F96-9648-9A15DB89506C}";
};
shadowcopy on cmd was created with sucess
For redirecting wmic to the console output you need to add /OUTPUT:STDOUT to your arguments.
And of course you will need to run your C# application as administrator.
var psi = new ProcessStartInfo("wmic");
psi.Arguments = #"/OUTPUT:STDOUT shadowcopy call create Volume='C:\'";
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
var p = Process.Start(psi);
p.WaitForExit();
String output = p.StandardOutput.ReadToEnd();
String errOutput = p.StandardError.ReadToEnd();
Here is what worked for me.
System.Diagnostics.ProcessStartInfo usbDevicesInfo = new System.Diagnostics.ProcessStartInfo("wmic", "path CIM_USBDevice get Caption");
usbDevicesInfo.RedirectStandardOutput = true;
usbDevicesInfo.UseShellExecute = false;
usbDevicesInfo.CreateNoWindow = true;
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = usbDevicesInfo;
process.Start();
process.WaitForExit();
Console.WriteLine("ExitCode: " + process.ExitCode.ToString() + "\n");
result = process.StandardOutput.ReadToEnd();
Console.WriteLine(result);

C# Process Standard Input

I am currently trying to disconnect from a network folder through the command line and am using the following code:
System.Diagnostics.Process process2 = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C NET USE F: /delete";
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
process2.StartInfo = startInfo;
process2.Start();
StreamWriter sw = process2.StandardInput;
sw.WriteLine("Y");
sw.Close();
process2.WaitForExit();
process2.Close();
Occasionally, I get the message "Is it ok to continue disconnecting and force them closed? (Y/N) [N]", to which I want to reply "Y", but I seem to be having issues with that working.
Does anyone know why my code is not inputting "Y" to standard input?
Use below code to get the message "Is it ok to continue disconnecting and force them closed? (Y/N) [N]", to which reply "Y"
static void Main(string[] args)
{
System.Diagnostics.Process process2 = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C NET USE F: /delete";
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
process2.StartInfo = startInfo;
process2.Start();
Read(process2.StandardOutput);
Read(process2.StandardError);
while (true)
process2.StandardInput.WriteLine("Y");
}
private static void Read(StreamReader reader)
{
new Thread(() =>
{
while (true)
{
int current;
while ((current = reader.Read()) >= 0)
Console.Write((char)current);
}
}).Start();
}
I think this may help you..

Process.Exited event is not be called

I have the following code snippet to call into command line:
p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = "/C " + "type " + “[abc].pdf”;
psi.UseShellExecute = false;
psi.RedirectStandardInput = false;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
p.StartInfo = psi;
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
p.Start();
p.WaitForExit();
Strangely, When [abc] is a small pdf file(8kb) p_Exited is called. But when it's a large pdf file(120kb) it is never called. Any clues?
Thanks,
You need to consume the output stream when the standard output has been redirected:
p.Start();
p.StandardOutput.ReadToEnd();
p.WaitForExit();

Categories