Strange, but perhaps I am handling it the incorrect way - I need to quite simply check if explorer.exe is running, and if so kill it. However, the way I am currently achieving this, explorer.exe simply restarts after I kill it.
Normal taskkill through batch works fine though, does C# do something different?
private void Form1_Load(object sender, EventArgs e)
{
Process[] prcChecker = Process.GetProcessesByName("explorer");
if (prcChecker.Length > 0)
{
MessageBox.Show("Explorer running");
foreach (Process p in prcChecker)
{
p.Kill();
}
}
else
{
MessageBox.Show("Explorer is not running");
}
}
That's because Windows takes care of restarting explorer.exe if it happens to die.
It is possible to delay this behavior (the setup of tortoisegit does this, for example), but it's not recommended - users are going to be pissed.
Although not C# way but you can alternatively try to set the registry key HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoRestartShell to 0 to stop the auto restart.
EDIT:-
Try this in C#:-
RegistryKey ourKey = Registry.LocalMachine;
ourKey = ourKey.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
ourKey.SetValue("AutoRestartShell", 0);
Try to kill the Process with exit code 1 .
Sorry i dont have any example code because i am not a C# programmer but in my application it worked just fine.
I used the C++ Function:
TerminateProcess
Related
So I'm writing an app that needs to end explorer.exe before it installs. However, when using the following code Windows automatically restarts the process:
Dim proc() = System.Diagnostics.Process.GetProcessesByName("explorer.exe")
For Each item as Process in proc()
item.Kill()
Next
Due to this problem I found a way to kill explorer.exe using taskkill here's the code and it works perfectly fine:
Dim taskkill as New ProcessStartInfo
taskkill.FileName = "cmd.exe"
taskkill.Arguments = "/c taskkill /F /IM explorer.exe"
taskkill.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(taskkill)
But I don't want to depend on cmd.exe to do that task? Can somebody tell me how to do this using vb.net or c# code?
Thanks.
this may be not a good practice of posting others answers,so please forgive me,i just meant to guide you by providing a small light to your problem. this answer is actually from superuser provided by t3hn00b..All credits to him
to start with ,the windows (windows 7 and XP) use a registry key to automatically restart the explorer process.so to disable we have to programatically reset the value of that key,we can use the code.
Dim key As Microsoft.Win32.Registry
Dim ourkey As Microsoft.Win32.RegistryKey
ourkey = key.LocalMachine
ourkey = ourkey.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", True)
ourkey.SetValue("AutoRestartShell", 0)
' Kill the explorer by the way you've post and do your other work
ourKey.SetValue("AutoRestartShell", 1)
or in C#
RegistryKey ourKey = Registry.LocalMachine;
ourKey = ourKey.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
ourKey.SetValue("AutoRestartShell", 0);
// Kill the explorer by the way you've post and do your other work
ourKey.SetValue("AutoRestartShell", 1)
Anyway i dont recommend changing windows default settings for a problem which have alternatives(using cmd.exe).
the code will have errors,forgive me for that too.just tried to give your problem a little start.try and check it,it is proved to work well in win7 and XP. you can see more details in the superuser link above.Hope it will help.Thanks to the t3hn00b.
In vb.net to kill explorer.exe you can use
Try
Dim Processes() As Process = Process.GetProcessesByName("explorer")
For Each Process As Process In Processes
Process.Kill()
Next
Catch ex As Exception
End Try
This will only work if you put the code in a timer and starting the timer when you would like to kill explorer.exe.
In c# try make sure you also put it in a timer and start it when you would like to kill explorer.exe
try {
Process[] Processes = Process.GetProcessesByName("explorer");
foreach (Process Process in Processes) {
Process.Kill();
}
} catch (Exception ex) {
}
Hope this helps.
I am Working in Visual Studio 2008 Winforms Application project in Windows 7 (32 bit).I am doing the project in C#.
I have placed some buttons in a tab and added actions for that once it is clicked. While clicking the button am just running a .exe file in its action part.
My problem is that, i opened a window by clicking one button(so the .exe file is running), now while am clicking the button again it is opening same window again irrespective of checking that it is open or not. I want to solve this issue,as when a window is opened it must not open again on another click on same button. How to solve this issue. ?
Please help....
Thanks in advance..
You could check if the process is already running, when re-clicking the button:
private void btnStartExecutable_Click(object sender, EventArgs e)
{
Process[] processName = Process.GetProcessesByName("InsertProcessNameHere");
if (pname.Length == 0)
{
MessageBox.Show("Application isn't running yet.");
//Start application here
Process.Start("InsertProcessNameHere");
}
else
{
MessageBox.Show("Application is already running.");
//Don't start application, since it has been started already
}
}
You can try this:
bool processExited = true;
private void button1_Click(object sender, EventArgs e)
{
if (processExited)
{
Process process = new Process();
process.EnableRaisingEvents = true;
process.Exited += MyProcessExited;
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = "notepad.exe";
process.Start();
processExited = false;
}
else
{
MessageBox.Show("Still running");
}
}
void MyProcessExited(object sender, EventArgs e)
{
processExited = true;
}
The right answer here IMHO is that unless the two application shares a common resource or can talk to each other through some channel, there is no safe and efficient way to achieve what you want. Since the process is external, it could already be running before your calling app starts, or even while it's already running. You won't be able to tell if the process has been started from your app or not.
By the time I'm writing this your question does not yet state if you are in liberty to modify the external app you are calling. If you are however, using a Mutex would be a quick and easy way to solve your problem.
In your external app, whenever you want to make the other app aware of whatever condition you want (be it that the process is running or that a specific window is opened), have a Mutex instance created like this:
var mutex = new Threading.Mutex(true, "mutex unique identifier");
And in your calling app, try to create a Mutex instance with the same identifier:
bool alreadyExists;
var mutex = new Threading.Mutex(false, "mutex unique identifier", out alreadyExists);
Here the alreadyExists variable will tell you whether or not the external process is running or not. This is much safer than trying to identify it via its name, as other processes could have the same or a new version could be of a different name. Of course, the mutex identifier must be as unique as possible (like a Guid), otherwise you may encounter the same problem. ;)
Whenever you feel like the mutex must be released (at external app level), release it:
mutex.ReleaseMutex();
Note that if the process ends the mutex will be automatically released by the OS.
If the external app isn't a .NET based app, you can still create a mutex with Win32 API functions.
Thanks for the support.. I got the answer like this..
1) Creating an event'Exit' for the process in function button click
2) Define a function for the exit event where you set a flag
3) Check the flag is set or not everytime while opening the process in the function button click
Event for Exit: 'P' is the name of process:
p.Exited += new EventHandler(p_Exited);
p_Exited will be the function name where we will set the flag.
Thanks all...
If you know the name of the process that gets started or the path the .exe is run from you can use the Process class to check to see if it is currently running.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
I've been able to use a winforms application to open another winforms application using:
Rhino4.Application oRhino = (Rhino4.Application)Activator.CreateInstance(Type.GetTypeFromProgID("Rhino4.Application"));
But how do I check if it gets closed? Is it possible to create an event that will get fired when the user closes the application?
EDIT
Process[] pr = Process.GetProcessesByName("Rhino4");
for (int i = 0; i < pr.Length; i++)
{
if (pr[i].MainWindowTitle != null)
{
if (pr[i].MainWindowTitle.Length > 4)
{
if (pr[i].MainWindowTitle.Substring(0, 4) == "wall")
{
pr[i].Exited += new EventHandler(caseInfoMenu_Exited);
}
}
}
}
void caseInfoMenu_Exited(object sender, EventArgs e)
{
MessageBox.Show("Window closed");
}
I've managed to identify the process using this code. But the Exited-event doesn't fire when I close the program.
Its maybe not the most elegant solution but indirectly you could do this by checking if the process exist or not and then do this repeatable. This is of course if you do not already have a handle to the process.
void checkProcess()
{
Process[] processes = Process.GetProcessesByName("NameOfProcess");
if (processes.Length == 0)
{
// No such process
}
else
{
foreach (Process proc in processes)
{
// do something with proc
}
}
}
Edit: Some thoughts on this after reading the posts in Abdul's answer plus your own question. This is by no means an answer, but maybe it can help you on your quest.
Firstly, Activator.CreateInstance calls the best fitting constructor on the object type that you give to it and returns a handle to that object. It does create the threads/processes itself and thus it has not knowledge about them. The (9) processes you'll see in your list are probably created by the Rheno4 class itself. There is a discussion about this here.
Secondly, according to msdn the EnableRaisingEvents property should be set to true when the process is created for the Exited event to function correctly. This leaves me wondering what happens when you attach the event after the process is already created?
You could of course iterate over all matching processess before and after calling CreateInstance to extract all new instances of Rheno4 that has been created. But this is far from a bulletproof solution and the risk is that you are fetching processes that are created by someone else or that not all processes are retreived (in case there is a delay in creating the other object). Depending on your needs, however, this maybe is appliable.
Another thought. The processes returned from the GetProcessesByName has a rich set of properties. Maybe you can look though these and find a common denominator for the processes returned. The ones I would start to investigate are: Threads, StartInfo, MainModule.
What about catching Exited event
myProcess.Exited += new EventHandler(myProcess_Exited);
private void myProcess_Exited(object sender, System.EventArgs e)
{
eventHandled = true;
Console.WriteLine("Exit time: {0}\r\n" +
"Exit code: {1}\r\nElapsed time: {2}", myProcess.ExitTime, myProcess.ExitCode, elapsedTime);
}
Source msdn.
If you want to start the application again after closing then :-
I think you need to crearte a Windows Service which will keep checking the process running and if it is closed then start the application again
As far as events are concern then "Closing" and "Close" events are there in Windows App which fires when user shutdowns the app.
I just wanna ask your opinion/suggestion on how to 'terminate' a running application/process is C#
Right now, I do have the following codes:
Process myProcess;
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
DirectoryInfo di = new DirectoryInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.Programs));
myProcess = Process.Start(di + #"\Wosk\Wosk.appref-ms"); // opening a file coming for Startup Menu
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
myProcess.Kill(); // not working - Cannot process request because the process has exited
}
I also tried myProcess.Close(); but nothing's happening.
You should have a look at
Process.HasExited Property
A process can terminate independently
of your code. If you started the
process using this component, the
system updates the value of HasExited
automatically, even if the associated
process exits independently.
Based on your comment it looks like the Process instance has already exited when you hit the close button. This can happen at any time and it's something you need to guard against. The easiest way is to simply catch the exception that results from calling Kill on an already exited process.
try {
myProcess.Kill();
} catch ( InvalidOperationException ) {
// Process is already finished so nothing to do
}
You are starting a program that was installed with ClickOnce. The .appref-ms is executed by a helper program, rundll32.exe, that starts the process and quickly exits. To terminate the started process, you'll need to find the actual running .exe with Process.GetProcessesByName() and use the Kill method.
We can't tell you what the process name is, that's contained in the .appref-ms file. But it is easy for you to see with TaskMgr.exe.
Process[] islemler = Process.GetProcessesByName("osk");
foreach (Process islem in islemler)
islem.Kill();
First please replace:
di + #"\Wosk\Wosk.appref-ms"
with:
Path.Combine(di.FullName, #"Wosk\Wosk.appref-ms")
Now to the point: I don't know what Wosk.appref-ms is or how this process is started. If this is a file it will be opened with the default program associated with this file extension. The problem could be related to the fact that the process you start only starts another process and terminates immediately. That's why when you try to kill it it says that it has already exited, but the actual process it spawned is still running. In this case you will have to enumerate through the running processes with Process.GetProcesses(), find the process and stop it.
I want to kill a process programmatically in vista/windows 7 (I'm not sure if there's significant problems in the implementation of the UAC between the two to make a difference).
Right now, my code looks like:
if(killProcess){
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("MyProcessName");
// Before starting the new process make sure no other MyProcessName is running.
foreach (System.Diagnostics.Process p in process)
{
p.Kill();
}
myProcess = System.Diagnostics.Process.Start(psi);
}
I have to do this because I need to make sure that if the user crashes the program or exits abruptly, this secondary process is restarted when the application is restarted, or if the user wants to change the parameters for this secondary process.
The code works fine in XP, but fails in Windows 7 (and I assume in Vista) with an 'access is denied' message. From what the Almighty Google has told me, I need to run my killing program as administrator to get around this problem, but that's just weak sauce. The other potential answer is to use LinkDemand, but I don't understand the msdn page for LinkDemand as it pertains to processes.
I could move the code into a thread, but that has a whole host of other difficulties inherent to it that I really don't want to discover.
You are correct in that it's because you don't have administrative priveleges. You can solve this by installing a service under the local system user and running a custom command against it as needed.
In your windows form app:
private enum SimpleServiceCustomCommands { KillProcess = 128 };
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "SERVICE_NAME");
scp.Assert();
System.ServiceProcess.ServiceController serviceCon = new System.ServiceProcess.ServiceController("SERVICE_NAME", Environment.MachineName);
serviceCon.ExecuteCommand((int)SimpleServiceCustomCommands.KillProcess);
myProcess = System.Diagnostics.Process.Start(psi);
In your service:
private enum SimpleServiceCustomCommands { KillProcess = 128 };
protected override void OnCustomCommand(int command)
{
switch (command)
{
case (int)SimpleServiceCustomCommands.KillProcess:
if(killProcess)
{
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("MyProcessName");
// Before starting the new process make sure no other MyProcessName is running.
foreach (System.Diagnostics.Process p in process)
{
p.Kill();
}
}
break;
default:
break;
}
}
I'll add the code for Simon Buchan's suggestion. It makes sense and should work as well, assuming your windows form is what launched the process in the first place.
Here's where you create the process. Notice the variable myProc. That's your handle on it:
System.Diagnostics.Process myProc = new System.Diagnostics.Process();
myProc.EnableRaisingEvents=false;
myProc.StartInfo.FileName="PATH_TO_EXE";
myProc.Start();
Later, just kill it with:
myProc.Kill();