Close Console Window Upon Starting A New Build In Main - c#

In main of my console application I am running an elevated version of my application if the user requests to run it elevated.
the code is doing this
elevated.exe myexe.exe //a /elevated
This code is being run in main so what happens when myexe is ran it opens a console window hits the code below and creates another console window with the new instance.
How do I close the initial window programmatically without closing the new one?
Environment.Exit(0) //closes the entire application THIS WONT WORK
enter code here
public void Run(string[] args) //myexe.exe
{
if (args[0] == "/elevated")
{
_command.RunElevated(path, arguments);
return;
}
}
Here is the meat of the RunElevated code pretty standard..
var process = new Process();
if (workingDirectory != null) process.StartInfo.WorkingDirectory = workingDirectory;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.Start();
// deal with output
standardOutput = process.StandardOutput.ReadToEnd();
standardError = process.StandardError.ReadToEnd();
// wait til the process exits
process.WaitForExit();
int exitCode = process.ExitCode;

OK maybe I know what's going on now. When you use UseShellExecute = false, then the program runs in the same command window, which you are closing with Environment.Exit(0).
So change to this:
var process = new Process();
if (workingDirectory != null) process.StartInfo.WorkingDirectory = workingDirectory;
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.Start();
Do no redirect output because 1) you can't with UseShellExecute=true, and 2) you are closing your main application anyway so why redirect things to an app that is exiting in a couple milliseconds.
With these changes you spawn your app in its own, hidden, window, then just Environment.Exit(0) your main application which will kill the non-elevated one but won't touch the process you spawned.
Here's an entirely working example:
using System;
using System.Diagnostics;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
if (args.Length > 0 && args[0] == "/elevated")
{
var process = new Process();
/*process.StartInfo.WorkingDirectory = */
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.FileName = "ConsoleApplication4.exe";
process.StartInfo.Arguments = "startedThroughElevatedCodePath";
process.Start();
Environment.Exit(0);
}
if (args.Length > 0 && args[0] == "startedThroughElevatedCodePath")
{
Console.WriteLine("Hello from elevated");
}
else
{
Console.WriteLine("Hello from not elevated");
}
Console.Read();
}
}
}

Related

Does process close itself?

Edit: I am running netsh with args (e.g. wlan show network).
public static string Run(string cmd, string args = null) {
var process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = cmd;
process.StartInfo.Arguments = args;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return output;
}
Does process close itself?
I am afraid of these Console Window Hosts, that they are no closed processes.

Run a C# exe with parameters that is to start another application and get output from console

I have an exe which has some parameters- path of another application and some files to be opened from that application. There would be an output as part of that application which would be displayed in the console of my exe.
But i am unable to get the output from the console.
I have the code:
ProcessStartInfo psi = new ProcessStartInfo("\"" + dllpath + "\\newapplication.exe" + "\"");
Process p = new Process();
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
p.Start();
The process starts successfully, and then i have to open a file in the process which happens through another class. So after the file opened, some extraction happens and the result is displayed on the console.
When i give p.WaitForExit(); nothing happens other than starting the application! How do i acheive to retreive the output on StandardOutput as per my code? Need Help!
This is the correct way to do it:
string outputProcess = "";
string errorProcess = "";
using (Process process = new Process())
{
process.StartInfo.FileName = path;
process.StartInfo.Arguments = arguments;
process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
outputProcess = process.StandardOutput.ReadToEnd();
errorProcess = process.StandardError.ReadToEnd();
process.WaitForExit();
}
Remember to use the using statement when you have an IDisposable object

How to call docker run from c# application

I've got a WPF application that whilst processing a file needs to use a docker process. The docker container is built on the box, currently after processing a file with the WPF application the user has to start a command prompt and type in
docker run --it --rm -v folderdedirect process parameters_including_filePath
to do further processing.
I want to include that in the WPF application. I could presumably use system.diagnostics.process with cmd.exe? I looked at the Docker.dotnet but couldn't for the life of me work out how it's supposed to just run a local container.
Here's how I did it in the end but there may be a better way.
var processInfo = new ProcessStartInfo("docker", $"run -it --rm blahblahblah");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
int exitCode;
using (var process = new Process())
{
process.StartInfo = processInfo;
process.OutputDataReceived += new DataReceivedEventHandler(logOrWhatever());
process.ErrorDataReceived += new DataReceivedEventHandler(logOrWhatever());
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit(1200000);
if (!process.HasExited)
{
process.Kill();
}
exitCode = process.ExitCode;
process.Close();
}
Adapted the code above for my context. The hardest part is determining how you want to monitor if your process finished. You can try setting up event listeners as shown here. Having other conditions to verify (if client sends a kill signal), I decided to just continually monitor process.HasExited value.
private static void RunDockerImage(ContainerData containerData)
{
var processInfo = new ProcessStartInfo("docker", $"run "+containerData.ImageName);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
int exitCode;
using (var process = new Process())
{
process.StartInfo = processInfo;
// indicate process is started
StartUpdateOrch(containerData);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
while(!process.HasExited)
{
// continually check if kill signal is set
if (getKillSignal())
{
process.Kill();
}
Thread.Sleep(2000);
}
exitCode = process.ExitCode;
containerData.exitCode = exitCode;
// indicate process is done
FinishUpdateOrch(containerData);
process.Close();
}
}

Run command line command passing STDIN [duplicate]

This question already has answers here:
Capturing console output from a .NET application (C#)
(8 answers)
Closed 6 years ago.
I need to spawn a child process that is a console application, and capture its output.
I wrote up the following code for a method:
string retMessage = String.Empty;
ProcessStartInfo startInfo = new ProcessStartInfo();
Process p = new Process();
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = command;
startInfo.FileName = exec;
p.StartInfo = startInfo;
p.Start();
p.OutputDataReceived += new DataReceivedEventHandler
(
delegate(object sender, DataReceivedEventArgs e)
{
using (StreamReader output = p.StandardOutput)
{
retMessage = output.ReadToEnd();
}
}
);
p.WaitForExit();
return retMessage;
However, this does not return anything. I don't believe the OutputDataReceived event is being called back, or the WaitForExit() command may be blocking the thread so it will never callback.
Any advice?
EDIT: Looks like I was trying too hard with the callback. Doing:
return p.StandardOutput.ReadToEnd();
Appears to work fine.
Here's code that I've verified to work. I use it for spawning MSBuild and listening to its output:
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => Console.WriteLine("received output: {0}", args.Data);
process.Start();
process.BeginOutputReadLine();
I just tried this very thing and the following worked for me:
StringBuilder outputBuilder;
ProcessStartInfo processStartInfo;
Process process;
outputBuilder = new StringBuilder();
processStartInfo = new ProcessStartInfo();
processStartInfo.CreateNoWindow = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.UseShellExecute = false;
processStartInfo.Arguments = "<insert command line arguments here>";
processStartInfo.FileName = "<insert tool path here>";
process = new Process();
process.StartInfo = processStartInfo;
// enable raising events because Process does not raise events by default
process.EnableRaisingEvents = true;
// attach the event handler for OutputDataReceived before starting the process
process.OutputDataReceived += new DataReceivedEventHandler
(
delegate(object sender, DataReceivedEventArgs e)
{
// append the new data to the data already read-in
outputBuilder.Append(e.Data);
}
);
// start the process
// then begin asynchronously reading the output
// then wait for the process to exit
// then cancel asynchronously reading the output
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
process.CancelOutputRead();
// use the output
string output = outputBuilder.ToString();
Here's some full and simple code to do this. This worked fine when I used it.
var processStartInfo = new ProcessStartInfo
{
FileName = #"C:\SomeProgram",
Arguments = "Arguments",
RedirectStandardOutput = true,
UseShellExecute = false
};
var process = Process.Start(processStartInfo);
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
Note that this only captures standard output; it doesn't capture standard error. If you want both, use this technique for each stream.
I needed to capture both stdout and stderr and have it timeout if the process didn't exit when expected. I came up with this:
Process process = new Process();
StringBuilder outputStringBuilder = new StringBuilder();
try
{
process.StartInfo.FileName = exeFileName;
process.StartInfo.WorkingDirectory = args.ExeDirectory;
process.StartInfo.Arguments = args;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.EnableRaisingEvents = false;
process.OutputDataReceived += (sender, eventArgs) => outputStringBuilder.AppendLine(eventArgs.Data);
process.ErrorDataReceived += (sender, eventArgs) => outputStringBuilder.AppendLine(eventArgs.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var processExited = process.WaitForExit(PROCESS_TIMEOUT);
if (processExited == false) // we timed out...
{
process.Kill();
throw new Exception("ERROR: Process took too long to finish");
}
else if (process.ExitCode != 0)
{
var output = outputStringBuilder.ToString();
var prefixMessage = "";
throw new Exception("Process exited with non-zero exit code of: " + process.ExitCode + Environment.NewLine +
"Output from process: " + outputStringBuilder.ToString());
}
}
finally
{
process.Close();
}
I am piping the stdout and stderr into the same string, but you could keep it separate if needed. It uses events, so it should handle them as they come (I believe). I have run this successfully, and will be volume testing it soon.
It looks like two of your lines are out of order. You start the process before setting up an event handler to capture the output. It's possible the process is just finishing before the event handler is added.
Switch the lines like so.
p.OutputDataReceived += ...
p.Start();
Redirecting the stream is asynchronous and will potentially continue after the process has terminated. It is mentioned by Umar to cancel after process termination process.CancelOutputRead(). However that has data loss potential.
This is working reliably for me:
process.WaitForExit(...);
...
while (process.StandardOutput.EndOfStream == false)
{
Thread.Sleep(100);
}
I didn't try this approach but I like the suggestion from Sly:
if (process.WaitForExit(timeout))
{
process.WaitForExit();
}
You need to call p.Start() to actually run the process after you set the StartInfo. As it is, your function is probably hanging on the WaitForExit() call because the process was never actually started.
The answer from Judah did not work for me (or is not complete) as the application was exiting after the first BeginOutputReadLine();
This works for me as a complete snippet, reading the constant output of a ping:
var process = new Process();
process.StartInfo.FileName = "ping";
process.StartInfo.Arguments = "google.com -t";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.OutputDataReceived += (sender, a) => Console.WriteLine(a.Data);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
Here's a method that I use to run a process and gets its output and errors :
public static string ShellExecute(this string path, string command, TextWriter writer, params string[] arguments)
{
using (var process = Process.Start(new ProcessStartInfo { WorkingDirectory = path, FileName = command, Arguments = string.Join(" ", arguments), UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }))
{
using (process.StandardOutput)
{
writer.WriteLine(process.StandardOutput.ReadToEnd());
}
using (process.StandardError)
{
writer.WriteLine(process.StandardError.ReadToEnd());
}
}
return path;
}
For example :
#"E:\Temp\MyWorkingDirectory".ShellExecute(#"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\svcutil.exe", Console.Out);

How do i start a process in c# calling net.exe without having a window pop open?

I am starting a process to disconnect a network drive, but it always pops up a command prompt window. It just flashes by quickly and disappears, but i would like to configure it so the window doesn't open at all. Any ideas?
Here is the c# code I'm currently using:
private void btnDisconnectNetwork_Click(object sender, EventArgs e)
{
Process DisconnectDrive = new Process();
DisconnectDrive.StartInfo.FileName = "Net.exe";
DisconnectDrive.StartInfo.Arguments = #" Use /d Q:";
DisconnectDrive.StartInfo.CreateNoWindow = true;
DisconnectDrive.Start();
}
I believe the following will also work:
using System.Diagnostics;
namespace processexample {
class Program {
static void Main(string[] args) {
ProcessStartInfo si = new ProcessStartInfo();
si.CreateNoWindow = true;
si.UseShellExecute = false;
si.FileName = #"C:\Windows\System32\net.exe";
si.Arguments = #"/help";
Process p = new Process();
p.StartInfo = si;
p.Start();
}
}
}
You have to set the CreateNoWindow and UseShellExecute in StartInfo.

Categories

Resources