So my computer has a lot of errors. 99% of the time, they're caused by explorer.exe being stupid. I can manually stop them, but I was thinking that I may be able to set up a schedule that automatically stops and starts it every 10 or so minutes, so I never have any problems with it any more. The code I have doesn't work, but I'll put it anyway:
foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
{
if (myProc.ProcessName == "explorer.exe")
{
myProc.Kill();
}
}
When I run it, absolutely nothing happens. Visual studio doesn't give an error, the program doesn't crash, etc. It just does nothing.
Please avoid use of the for-if anti-pattern:
var explorers = Process.GetProcessesByName("explorer");
foreach (var thisExplorer in explorers)
{
thisExplorer.Kill();
}
edit: as charmander noted in comments.
It's usually a good idea to look at the output of a partucular method/property before assuming you know what it contains.
In this case, myProc.ProcessName does not contain the extension of the process. So compare to "explorer".
Additionally, modifying a collection whilst foreaching over it usually results in a runtime error.
The process name is just "explorer"
EDIT:
This did the trick on my box:
foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
{
if (myProc.ProcessName == "explorer")
{
myProc.Kill();
}
}
You can do it the Linq way too
List<Process> processes = Process.GetProcesses().Where(p => p.ProcessName == "explorer").ToList();
foreach (var process in processes)
{
process.Kill();
}
Related
I am enumerating processes to find if excel.exe is running (for example).
I get a lot of Win32Exception from system services and such.
Process[] pps = Process.GetProcesses();
foreach (var process in pps)
{
string module = null;
try
{
module = process.MainModule?.FileName;
}
catch (Win32Exception)
{
continue;
}
which make enumeration to run 500ms instead of 10ms.
Is there a way to figure if a process has main module without triggering the exception? Or any other way to find process exe path?
This exception occurs when you're trying to do something which your OS doesn't allow. You can check the NativeErrorCode property to see more details about the exception.
You can find a solution here to deal with that issue.
As mentioned by #steeeve in comment, you can use GetProcessByName, if performance is the only criteria for you.
i have this piece of code to detect a Process:
private Boolean IsGameRunning()
{
Process[] game = Process.GetProcesses();
foreach (Process process in game)
{
if (process.ProcessName.Contains("GameWindow"))
{
return true;
}
}
return false;
}
Since the code has to run a lot of times because it is inside a Timer, is there any way to improve the speed of the process?
I do not have any control over the game.
This code is inside a timer always enabled with an interval of 2000-3000 ms:
if (IsGameRunning())
{
Do stuff
}
else
{
Status("Waiting for game to start");
}
Given that the process is launched by another, in this case Steam, we can narrow the list to search to only child processes.
First, need to get the parent process id (PID).
var parentProcess = Process.GetProcesses().FirstOrDefault(x => x.ProcessName == "Steam");
Then using the Windows Management Instrumentation (accessed using the System.Management.dll), you can then search only the child processes.
bool IsGameRunning(int parentProcess, string childExecutableName)
{
var query = string.Format("SELECT * FROM Win32_Process WHERE ParentProcessId = {0} AND Name = '{1}'", parentProcess, childExecutableName);
using (var searcher = new ManagementObjectSearcher(query))
using (var results = searcher.Get())
{
return (results.Count > 0);
}
}
e.g. IsGameRunning(parentProcess.Id, "SuperMeatBoy.exe")
No guarantee that this is faster as I haven't done any comparative testing, however from prior experience using the WMI is more performant than iterating a list of processes.
If you want to go further, a more advanced solution would be to hook up events to tell you process is created and deleted using a ManagementEventWatcher as shown in this blog post http://weblogs.asp.net/whaggard/438006.
WMI gives you a visible performance hit with noticeable recurring CPU spikes when looking at it run in task manager. The way I made my process hunting work was to use a linq statement on Process.GetProcessByName, which I've never seen go above 0% when scanning for processes every .3 seconds. I store the processes I already know about in the memory, and filter them out in the linq statement.
If your EXE has enough permission (or is elevated), you can set EnableRaisingEvents = true, and attach to the Exited event to know exactly when the process dies.
I have a foreach loop that starts a process within a try/catch. In the finally section of my try/catch/finally I am trying to ensure the the process does not have a handle on any files. I have to delete files that were being processed.
Nothing I have tried seems to be working. I continue to get System.IO exceptions. "The file is currently in use by another process."
You can see in the finally I am using the WaitForExit() before returning from this method. The very next method call is one to delete files. Why would the process still be open or have a handle on any of these file after this?
Thanks!
try
{
foreach (var fileInfo in jsFiles)
{
//removed for clarity
_process.StartInfo.FileName = "\"C:\\Program Files\\Java\\jre6\\bin\\java\"";
_process.StartInfo.Arguments = stringBuilder.ToString();
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardOutput = true;
_process.Start();
}
}
catch (Exception e)
{
BuildMessageEventArgs args = new BuildMessageEventArgs("Compression Error: " + e.Message,
string.Empty, "JSMin", MessageImportance.High);
BuildEngine.LogMessageEvent(args);
}
finally
{
_process.WaitForExit();
_process.Close();
}
There's something seriously wrong here. You're starting a bunch of processes, but only waiting for the last spawned one to exit.
Are you sure you don't want the foreach outside the try block?
If you tell us more about what exactly you're trying to do, we could provide better suggestions.
I think you need to restructure your code. As it stands a failure for any of the processes in the foreach will cause an exit from the loop. Even if everything does succeed then your WaitForExit and Close calls in the finally block will only address the last process from the loop above.
You need to deal with each process and its success and/or failure individually. Create a method that accepts a fileInfo parameter and spawns and waits on each process. Move your loop into the client code that will be calling the suggested method.
Is the process a Console application or a GUI application?
For a GUI application, you will have to do Process.CloseMainWindow.
foreach (var fileInfo in jsFiles)
{
using (Process process = new Process())
{
try
{
//Other stuff
process.Start();
}
catch (...)
{
//Exception Handling goes here...
}
finally
{
try
{
process.WaitForExit();
}
catch (...)
{
}
}
}
}
Process.WaitForExit() might throw an exception, so it needs a try/catch of it's own.
If you create the process in the using statement, you don't have to worry about closing it, .NET will dispose of it properly.
It's usually better to not precede local variables with an underscore character. Most people just use that for their fields.
I'm using the Process Class to start processes, but don't ever want more than one instance of any program to be running.
Looking at the documentation, there are lots of likely-looking properties, but nothing that stands out as the most obvious.
What's the best way to determine if a process is running?
Edit: John Fisher is right: it's an existing application that I'm starting and I'm unable to modify it.
You can call this method
Process.GetProcesses()
and loop through the result (a collection of type Process) to see if the name matches. Something like this:
foreach (Process prc in Process.GetProcesses())
{
if (prc.ProcessName.Contains(MyProcessName))
{
//Process is running
}
}
I guess that all depends on what you mean by "best way"? Do you mean the fastest, the most accurate, or one that will handle some odd circumstances?
The way I would start is by listing the processes and checking the executable file name against the one I'm trying to start. If they match (case insensitive), it's probably running.
You should use the Singleton application pattern for that:
bool createdNew = true;
using (var mutex = new Mutex(true, "YourProcessName", out createdNew))
{
if (createdNew)
{
// Run application
}
}
I'm quite familiar with the System.Diagnostics.Process class. But, I'm wondering about how I can monitor a specific process (i.e. Check to see if it's running every XX mins/secs). I need to be able to checking whether a process is running and if it is, continue with initialising the rest of the program.
Thanks,
-Zack
Checking if it's still running is easy: Process.HasExited.
Rather than polling this periodically, however, you could set EnableRaisingEvents to true, and attach a handler to the Exited event.
EDIT: To answer the question in the comment about "fetching" the process - that depends on what you already know. If you know its process ID, you could use Process.GetProcessById. If you only know its name, you would have to use Process.GetProcessesByName and work out what to do if you get multiple results. If you don't know the exact name, you could use Process.GetProcesses and look for whatever you do know about it. Those options are effectively in order of preference :)
If you didn't start the process yourself, you get find the Process object associated with a process by looking through the list returned by Process.GetProcessesByName(...) or Process.GetProcesses(...)
Once you have the process, you can listen read its properties (including HasExited) and (as Jon mentions in his response) if you set EnableRaisingEvents you can listen to its events (including Exited).
Something like this, maybe?
Process[] processlist = Process.GetProcesses();
bool found = false;
foreach (Process theprocess in processlist)
{
if(theprocess.ProcessName == "YourProcessName")
{
found = true;
break;
}
}
if (!found)
{
return;
}