how can i make my console application window to behave like a command prompt window and execute my command line arguments?
This should get you started:
public class Program
{
public static void Main(string[] args)
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
proc.Start();
new Thread(() => ReadOutputThread(proc.StandardOutput)).Start();
new Thread(() => ReadOutputThread(proc.StandardError)).Start();
while (true)
{
Console.Write(">> ");
var line = Console.ReadLine();
proc.StandardInput.WriteLine(line);
}
}
private static void ReadOutputThread(StreamReader streamReader)
{
while (true)
{
var line = streamReader.ReadLine();
Console.WriteLine(line);
}
}
}
The basics are:
open cmd.exe process and capture all three streams (in, out, err)
pass input from outside in
read output and transfer to your own output.
The "Redirect" options are important - otherwise you can't use the process' respective streams.
The code above is very basic, but you can improve on it.
I believe you are looking for this
var command = "dir";
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
Console.WriteLine(result);
Related
I have written a console application to call the AZcopy tool programmatically, but I was not able to call azcopy tool. Can you please redirect me the workable source ? I have downloaded azcopy_windows_amd64_10.12.1 and put azcopy.exe into C:\Windows\System32\azcopy.exe location
static void Main(string[] args)
{
string strCmdText = #"AzCopy.exe sync ""D:\temp"" ""https://myhubforazcopy.blob.core.windows.net/myhubforazcopy1?sp=racwdl&st=2021-09-05T17:19:11Z&se=2021-09-06T01:19:11Z&spr=https&sv=2020-08-04&sr=c&sig=MAraJ0PxqJMDdYuWzrOUEwYda%2BkXEukP%2Fs%3D"" --destination-delete=true";
CallProcess(strCmdText);
}
public static void CallProcess(string strCmdText)
{
//C:\Windows\System32\azcopy.exe
var process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = #"C:\Windows\System32\cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
Arguments = strCmdText,
UseShellExecute = false,
CreateNoWindow = false,
WorkingDirectory = #"D:\AzCopy\bin\Debug\"
};
process.StartInfo = startInfo;
process.Start();
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
Console.WriteLine(process.StandardOutput.ReadToEnd());
}
Starting cmd with the program you want to execute as the argument doesn't actually runt that program, you'll need to pass the entire argument (your program) after the /c flag, like so:
string strCmdText = #"/c AzCopy.exe sync ""D:\temp"" ...
Make sure that AzCopy is in your PATH or specify the precise path to it
But it would be better if you just directly run AzCopy instead of starting a command prompt which then starts AzCopy, this would be done like so:
// Notice how the 'azcopy' at the start is gone
var arguments = #"""D:\temp"" ""https://myhubforazcopy.blob ..."
var process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = #"C:\Windows\System32\azcopy.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
Arguments = arguments,
UseShellExecute = false,
CreateNoWindow = false,
WorkingDirectory = #"D:\AzCopy\bin\Debug\"
};
Solution :
static void Main(string[] args)
{
string strCmdText = #"/c azcopy.exe sync ""D:\temp"" ""https://myhubforazcopy.blob.core.windows.net/myhubforazcopy1?sp=racwdl&st=2021-09-05T17:19:11Z&se=2021-09-06T01:19:11Z&spr=https&sv=2020-08-04&sr=c&sig=MAraJ0PxqJMDdYuWzrOUEwYda%2BkXEukP%2Fs%3D"" --delete-destination=true";
CallProcess(strCmdText);
}
public static void CallProcess(string strCmdText)
{
var process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = #"cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
Arguments = strCmdText,
UseShellExecute = false,
CreateNoWindow = false,
WorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
};
process.StartInfo = startInfo;
process.Start();
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
Console.WriteLine(process.StandardOutput.ReadToEnd());
}
I have a created a small app that would download and Install Python and then install a list of Python Libraries using pip.
I am using the Process.WaitForExit() method to make sure that the installation of Python is complete before I begin the libraries installation. Below is my code for installing Python
public void installPython()
{
Process process = new Process();
process.StartInfo.FileName = #"C:\Python36\python-3.6.3-amd64.exe";
process.Start();
process.WaitForExit();
}
Below is the code which then launches cmd and executes the pip command :
public void installLibraries()
{
int exitCode;
string command = "pip install -r requirements.txt";
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
Then in the Main method I call the installPython method and then the installLibraries method
Unfortunately the compiled .exe isn't following the correct order. When I run the command from the cmd after browsing to the directory, I get the error :
output>>(none)
error>>'pip' is not recognized as an internal or external command,
operable program or batch file.
Is there a mistake in how I am using the Process functions?
This is Start process and wait until finished.
public static void StartProcessAndWait(string processFile, string arguments, string workingDirectory)
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = processFile,
Arguments = arguments,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
RedirectStandardError = true,
WorkingDirectory = workingDirectory
}
};
proc.Start();
var _ = ConsumeReader(proc.StandardOutput);
// ReSharper disable once RedundantAssignment
_ = ConsumeReader(proc.StandardError);
async Task ConsumeReader(TextReader reader)
{
string text;
while ((text = await reader.ReadLineAsync()) != null)
Console.WriteLine(text);
}
proc.WaitForExit(30000);
}
When I am running relog command from command prompt, I am getting the output without any issue.
Now when I am trying to run command using C# code, I am not getting any output. What could be the issue?
public static string Bash()
{
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
WorkingDirectory = #"C:\blgs",
Arguments = "relog.exe sample.blg",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return result;
}
I want to call cmd.exe using C#.
And I want to write multiple cmd commands in C#.
the most important keys is that:
I want to interact with cmd window.the next command is typed according to the last command output.
But now I have tried ,it can input multiple commands but only one output or one outputErr.
I want to achieve one command one output,and the next command is also the same cmd window rather than a new cmd window?
How to solve this problem.
the example code is like this
string[] message = new string[2];
ProcessStartInfo info = new ProcessStartInfo();
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.FileName = "cmd.exe";
info.CreateNoWindow = true;
Process proc = new Process();
proc.StartInfo = info;
proc.Start();
using (StreamWriter writer = proc.StandardInput)
{
if (writer.BaseStream.CanWrite)
{
foreach (string q in command)
{
writer.WriteLine(q);
}
writer.WriteLine("exit");
}
}
message[0] = proc.StandardError.ReadToEnd();
if (output)
{
message[1] = proc.StandardOutput.ReadToEnd();
}
return message;
The problem is that cmd is a cli application, so proc.StandardOutput.ReadToEnd() will block your thread, you can't simply put the ReadToEnd() in your loop (to execute multiple command).
In my demo, I start a new thread to handle the output.so that i won't block my command input.
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true
}
};
proc.Start();
StringBuilder sb = new StringBuilder();
var outStream = proc.StandardOutput;
var inStream = proc.StandardInput;
inStream.WriteLine("mkdir test");
Task.Run(() =>
{
while (true)
{
Console.WriteLine(outStream.ReadLine());
}
});
Console.WriteLine("dir");
inStream.WriteLine("dir");
Console.WriteLine("mkdir test");
inStream.WriteLine("mkdir test");
Console.WriteLine("dir");
inStream.WriteLine("dir");
Console.ReadLine();
}
forgive my poor english,
Can I start a process (using C# Process.Start()) in the same console as the calling program? This way no new window will be created and standard input/output/error will be the same as the calling console application. I tried setting process.StartInfo.CreateNoWindow = true; but the process still starts in a new window (and immediately closes after it finishes).
You shouldn't need to do anything other than set UseShellExecute = false, as the default behaviour for the Win32 CreateProcess function is for a console application to inherit its parent's console, unless you specify the CREATE_NEW_CONSOLE flag.
I tried the following program:
private static void Main()
{
Console.WriteLine( "Hello" );
var p = new Process();
p.StartInfo = new ProcessStartInfo( #"c:\windows\system32\netstat.exe", "-n" )
{
UseShellExecute = false
};
p.Start();
p.WaitForExit();
Console.WriteLine( "World" );
Console.ReadLine();
}
and it gave me this output:
You could try redirecting the output of this process and then printing it on the calling process console:
public class Program
{
static void Main()
{
var psi = new ProcessStartInfo
{
FileName = #"c:\windows\system32\netstat.exe",
Arguments = "-n",
RedirectStandardOutput = true,
UseShellExecute = false
};
var process = Process.Start(psi);
while (!process.HasExited)
{
Thread.Sleep(100);
}
Console.WriteLine(process.StandardOutput.ReadToEnd());
}
}
Alternative approach using the Exited event and a wait handle:
static void Main()
{
using (Process p = new Process())
{
p.StartInfo = new ProcessStartInfo
{
FileName = #"netstat.exe",
Arguments = "-n",
RedirectStandardOutput = true,
UseShellExecute = false
};
p.EnableRaisingEvents = true;
using (ManualResetEvent mre = new ManualResetEvent(false))
{
p.Exited += (s, e) => mre.Set();
p.Start();
mre.WaitOne();
}
Console.WriteLine(p.StandardOutput.ReadToEnd());
}
}