Reputation: 13
So basically I want to open and use the cmd.exe just like a manual user would. I tried some methods, but none could do all 4 items above.
Below code works but does not display the commands/outputs and terminates after completion. Any help?
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.CreateNoWindow = false;
info.Arguments = "/k";
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("dir");
sw.WriteLine("ipconfig");
}
}
Upvotes: 1
Views: 3987
Reputation: 16464
The RedirectStandard...
-properties are misleading. As soon as you set one of them, all three streams will be redirected. This is because the underlying Windows API only has a single flag to control redirection - STARTF_USESTDHANDLES
.
Because you didn't set the RedirectStandardOutput
property to true, the stdout streams isn't made available to your code, but instead will be redirected to the Console.Out
stream of your own process.
Thus, your code works fine as long as the parent process is a console application; but in a Windows application, the output gets redirected into nothingness.
An easy workaround is to temporarily turn your parent process into a console application:
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeConsole();
static void Main(string[] args)
{
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.CreateNoWindow = false;
p.StartInfo = info;
AllocConsole();
p.Start();
FreeConsole();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("dir");
sw.WriteLine("ipconfig");
}
}
}
As for keeping the console open: you could just remove the FreeConsole()
call so that the parent process keeps the console around even after cmd.exe exits. However this may be a problem if you need multiple consoles, as your parent process can't be associated with more than one console at a time.
Alternatively, don't close the input stream so that cmd.exe keeps running.
Upvotes: 4
Reputation: 10171
For seeing the out put insert Console.ReadLine();
(application stop until you send a key so you can see the result) after command executed.
static void Main(string[] args)
{
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.CreateNoWindow = false;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("dir");
sw.WriteLine("ipconfig");
}
}
Console.ReadLine();
}
Upvotes: 0