What I want to do is to kill the explorer.exe main process (which will result in killing the Windows gui programatically and then open the gui again. I can achieve that by manually killing and then starting the process through taskmanager, but I can't figure out how to do kill the main explorer process from a wpf visual C# program. Also, I tried killing it from taskmanager and then starting the windows gui again by:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = "",
UseShellExecute = true,
CreateNoWindow = true
}
};
proc.Start();
but it only starts a new explorer window, not the windows gui. Can someone help me to kill the win gui and start it again with some code, please?
You can get processes by name using:
var explorerProcesses = Process.GetProcessesByName("explorer");
Then you can loop through and kill them all:
foreach(var process in explorerProcesses)
{
process.Kill()
}
Your program may need to be running as Administrator to kill explorer, I'm not certain.
I finally managed to find out the solution: killing the explorer.exe by getting the process and using Kill() only restarted the gui. To completely shut it down, use
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "taskkill.exe",
Arguments = "/F /IM explorer.exe",
UseShellExecute = true,
CreateNoWindow = true
}
};
proc.Start();
Related
Hello so I'm currently developing a program to help me automate the functionality of a python script, after a lot of research I found a way to launch and read the output of the python script to a C# console window but I want to implement a time-based condition for it to stop (close process after 5 minutes for example). My code for opening the process is as followed (credits to the original writer):
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "C:\\Python27\\python.exe",
Arguments = cmd,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
process.ErrorDataReceived += Process_OutputDataReceived;
process.OutputDataReceived += Process_OutputDataReceived;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
Console.Read();
As you can see the process waits for it to be finished but the script can sometimes stall or not function correctly, I would like to add a time based condition to close the process if it's not completed after 5 minutes. I record the time by using the StopWatch class but having trouble targeting the process to close it, 5 different processes of the python script run at once so closing the python process would not be viable. I also use process.WaitForExit(); which waits until the process has finished but like I said above this isn't always the case so it's causing problems with processes never closing.
TL;DR: If process takes longer than 5 minutes to complete -> Force close
Any suggestions please?
I have created a management application that also allows to quickly access a remote desktop session to remote machines. I need to wait until the process ends, so I can close the VPN connection to the remote server. Everything works fine, except waiting for the process to end.
The following code is being used to start the MSTSC process and wait until it ends:
var process = new Process
{
StartInfo = new ProcessStartInfo("mstsc.exe"),
EnableRaisingEvents = true
};
process.Exited += (o, e) => Console.WriteLine("Process stopped.");
process.Start();
Console.ReadLine();
The Exited event is raised almost immediately after the program starts. When I replace mstsc.exe with notepad.exe everything works as expected. I thought that MSTSC might fork itself and abort the initial process.
But it is possible to wait for MSTSC to end using the following command (from the commandline):
start /wait mstsc.exe
This command doesn't return until I exit the remote desktop session. Given that information I replaced my code with this:
var process = new Process
{
StartInfo = new ProcessStartInfo("cmd.exe"),
Arguments = "/c start /wait mstsc.exe",
EnableRaisingEvents = true
};
process.Exited += (o, e) => Console.WriteLine("Process stopped.");
process.Start();
Console.ReadLine();
This would run CMD.exe and it will issue the start /wait mstsc.exe command. If that ends, the CMD process ends as well and I'm fine (with a nasty workaround, but okay). Unfortunately, this doesn't happen. The CMD process terminates immediately. Somebody knows what I am doing wrong?
process.WaitForExit();
Won't work because mstsc on start opens new copy of itself and closes original.
process.WaitForExit();
process = Process.GetProcessesByName(process.ProcessName).First();
process.WaitForExit();
Will work but it's awful workaround.
Update 1:
It seems that mstsc closes original process but NOT it's output stream!
So you can wait for process StandardOutput to close.
var process = new Process
{
StartInfo = new ProcessStartInfo("mstsc.exe") { UseShellExecute = false, RedirectStandardOutput = true }
};
process.Start();
process.StandardOutput.ReadToEnd(); //This will wait for stream to close.
Or if you don't want to block current thread:
var process = new Process
{
StartInfo = new ProcessStartInfo("mstsc.exe") { UseShellExecute = false, RedirectStandardOutput = true }
};
process.Start();
var outputResultPromise = process.StandardOutput.ReadToEndAsync();
outputResultPromise.ContinueWith(o=> Console.WriteLine("Stream closed"));
Console.ReadLine();
Here is the link at MSDN about starting mstsc,
It might be answer to your problem with mstsc closing immediately after running (raising Exited event). Try changing in Visual Studio target platform to AnyCPU.
Let's say your machine is 64bit Windows, your app is 32bit. The app runs 32bit mstsc. 32bit mstsc detects that Windows is 64bit, tries to close itself and run 64bit mstsc (Exited event is raised at that moment even though mstsc starts GUI window).
Changing target platform solved my issue.
There are multiple MSTSC processes running, so it's difficult to wait for one. What I don't understand is that CMD.EXE can do it when I use the start /wait command.
this worked with me:
process.Start();
Thread.Sleep(2000);
while(getNumProcesses() > 0)
process.WaitForExit();
private static int getNumProcesses()
{
Process[] myProcesses = Process.GetProcessesByName("mstsc");
return myProcesses.Length;
}
You cannot wait for mstsc.exe process. Say exactly, you cannot simply wait for end of remote desktop. When I observed mstsc.exe process by Process Monitor, mstsc passed his work to svchost, mstsc.exe ended, but remote desktop was still run.
But I wrote script for remoting application.
Script remoteCmd.cmd starts remoteApplication, remote machine creates a temp file ( \\tsclient\c..\temp\xxx) and remoteCmd.cmd waits until temp file exists.
See
https://github.com/turzik/WindowsScripts/tree/master/remoteApp
You need to call WaitForExit() after you call Start():
process.Start();
process.WaitForExit();
This overload causes the current thread to wait indefinitely to wait until the process exits. There's also an overload that allows you to specify the number of milliseconds you'd like to wait.
I've been working on a small piece that calls an external executable (ffmpeg in my case)
And then I wrote a test and used test runner in a debug mode, now if I stop debugging (terminate) it still runs ffmpeg. I tried to kill the process in the finalizer and with IDisposable - it still runs. How can I make sure that the process never will be left like that, and if the caller dies or fails or gets stopped by any means, the ffmpeg executable guaranteed to be killed.
I run the process as usual (nothing fancy)
var processInfo = new ProcessStartInfo(ffmpegPath)
{
UseShellExecute = false,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
};
using (var ffmpegProc = new Process())
{
ffmpegProc.EnableRaisingEvents = true;
ffmpegProc.StartInfo = processInfo;
ffmpegProc.Start();
ffmpegProc.WaitForExit();
}
You should use JobObject
With JobObject you can add child processes. So if the main process is killed or closed the os will terminate all child processes.
source: http://www.xtremevbtalk.com/showpost.php?p=1335552&postcount=22
Another solution is to pass to child object the parent PID.
Any child have to check for parent PID existence and if not found kill itself
There is nothing you can do when your process is terminated. There is no code run in your process after someone kills it with TerminateProcess call.
In case of more graceful cases (i.e. unhandled exception) you may have global handler that does something close to what you want.
I see several questions about how to launch processes and push data into stdin, but not how to control where their output goes.
First here is my current code, run from a console mode C# application:
// Prepare the process to run
ProcessStartInfo start = new ProcessStartInfo();
// Enter in the command line arguments, everything you would enter after the executable name itself
start.Arguments = " -";
// Enter the executable to run, including the complete path
start.FileName = "doxygen.exe";
// Do you want to show a console window?
start.WindowStyle = ProcessWindowStyle.Normal;
start.CreateNoWindow = false;
start.RedirectStandardInput = true;
start.UseShellExecute = false;
// Run the external process & wait for it to finish
using (Process proc = Process.Start(start))
{
//doxygenProperties is just a dictionary
foreach (string key in doxygenProperties.Keys)
proc.StandardInput.WriteLine(key+" = "+doxygenProperties[key]);
proc.StandardInput.Close();
proc.WaitForExit();
// Retrieve the app's exit code
int exitCode = proc.ExitCode;
}
What happens when I run this is I do not see any new window (though I think I should) and all of doxygen.exe's stdout is printed to my app's console window.
What I would like to happen is one of two things:
Doxygen is launched in a visible window, and I can see its stdout in that window, not in my app's window.
Doxygen is launched in a hidden window, and it's stdout is written to a log file.
How can I achieve these?
In addition, why am I not getting a separate window for the spawned process, and why is the spawned process writing output to my window not its own?
One thing that you can do is use RedirectStandardOutput and instead of using WaitForExit you can use ReadToEnd
ProcessStartInfo start = new ProcessStartInfo();
start.RedirectStandardOutput = true;
//make other adjustments to start
Process p = new Process();
p.StartInfo = start;
p.Start();
string output = p.StandardOutput.ReadToEnd();
and then you can use string output at your leisure
If you want to get output in real-time the p.StandardOutput property has methods that allow you to get the output asynchronously. I don't know all the details to it offhand, I've only used it once before, but there's plenty of literature out there if you search for it.
Also be careful when redirecting both StandardOutput and StandardError at the same time, If they're long enough, it is possible for that to cause deadlocks.
You need to do two things:
1) Indicate that you want the standard output of the process to be directed to your app by setting the RedirectStandardOuput property to true in the process.
2) BEFORE the call to WaitForExit, start capturing the output:
string sOutput = p.StandardOutput.ReadToEnd();
If you do not start reading the output before calling wait for exit, you can encounter a deadlock.
However, it is important to know that standard output will only capture output information, not anything written to the standard error stream of the app.
In order to capture both streams of information, you can hook the process's OutputDataReceived and ErrorDataReceived events and write the event data directly into a log file or store it in a class property for use after the process has completed.
This problem is bizarre. I have never encountered anything like it before.
I am trying to make my program extract a file using 7zip. I have done this before in other programs and it was never too difficult. So I copy and pasted my code in:
Process process = new Process
{
StartInfo =
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "7za.exe",
UseShellExecute = false,
ErrorDialog = false,
Arguments = "x -y -o\"" + outputPath +"\" \""+ inputFile +"\"",
RedirectStandardOutput = false,
}
};
process.Start();
Immediately after this code has run my application terminates. It just disappears. It's certainly not meant to! I used the step into function and ran it. As soon as process.Start(); had finished the program closed and returned me into Visual C#. It didn't run any Application.Exit(); or anything, it just went away. There was no error awaiting me in Visual C#.
So I tried adding a MessageBox.Show("Test"); to the end. Ran it in step mode. Did process.Start(); fine, as soon as it executed the MessageBox code it disappeared again. I didn't even click ok in the message box (which showed up for about 0.2 seconds before the application terminated)
Well if this code is in Main() then it will finish when your code is done executing. Can you post the full code where this snippet is contained?
You can wait for the process to finish by including
process.WaitForExit();
Checking the ExitCode might tell you if your process succeeded. And you can always redirect the StandardError to check the output of that too.
process.StartInfo.RedirectStandardError = true;
string error = process.StandardError.ReadToEnd();
Try process.WaitForExit() after process.Start() ...