How can I get a list of long running services on my current machine?
I can list all processes but how can I add to filter long running ones?
private void ListProcesses()
{
Process[] processCollection = Process.GetProcesses();
foreach (Process p in processCollection)
{
Console.WriteLine(p.ProcessName);
}
}
The Process class has a datetime property Process.StartTime that gets the time that the associated process was started.
You could use it to figure out which ones that run for longer.
I can list all processes but how can I add to filter long running ones?
Something like (assuming you are asking for wall time):
foreach (var p in processCollection.Where(n => (DateTime.Now - p.StartTime) > someThresholdInterval))
{
//...long running
}
There are other properties you could also use like TotalProcessorTime which would give you the total amount of time that the process has actually been using the processor (versus sleeping) which might be more interesting in some cases.
If you actually want services, rather than processes, then there is a different method to get those. To get services use ServiceController.GetServices however, I don't think there's a way to get when they started.
for running services only, we must use ServiceController and ManagementObject . here is my code for "long" running services :
static public void Main()
{
TimeSpan Interval = new TimeSpan(5,0,10); // as exemple
var scServices= ServiceController.GetServices();
foreach (ServiceController scTemp in scServices)
{
if (scTemp.Status == ServiceControllerStatus.Running)
{
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" + scTemp.ServiceName + "'");
wmiService.Get();
var id = Convert.ToInt32(wmiService.Properties["ProcessId"].Value);
Process p = Process.GetProcessById(id);
if ((DateTime.Now.Subtract(p.StartTime)) > Interval)
{
Console.WriteLine(" Service : {0}", scTemp.ServiceName);
Console.WriteLine(" Display name: {0}", scTemp.DisplayName);
Console.WriteLine(" StartTime: {0}", p.StartTime);
}
}
}
Console.ReadLine();
}
Related
From a C# service, how I can check whether another app is dead or not?
I tried to use Process.Responding, it returns true but the app is died.
This is the code:
private List<string> getListStringGAppPath()
{
List<string> listGAppPaths = new List<string>();
Process[] processes = Process.GetProcessesByName("MyApp");
if (processes.Length > 0)
{
for (int i = 0; i < processes.Length; i++) {
listGAppPaths.Add(processes[i].Responding.ToString() + "######" + processes[i].MainModule.FileName);
//processes[i].Responding.ToString() always return True
}
return listGAppPaths;
}
else
{
return null;
}
}
When process dies, windows seems to toggles its state to Suspended, you can try checking its state first. Also here: Detecting process crash in .NET
You can check if the process is responding:
foreach (var process in System.Diagnostics.Process.GetProcesses())
{
Console.WriteLine("Process Name: {0}, Responding: {1}", process.ProcessName, process.Responding);
}
Similar to this answer:
Check status of process
You can use the methods in System.Diagnostics.Process to get process information.
GetProcessesByName(String)
Creates an array of new Process components and associates them with all the process resources on the local computer that share the specified process name.
GetProcessById(Int32)
Returns a new Process component, given the identifier of a process on the local computer.
GetProcesses()
Creates a new Process component for each process resource on the local computer.
If the process does not exist, then it must have died?
This question already has answers here:
How to check if process is idle? C#
(2 answers)
Closed 4 years ago.
I have several programs that are already released. I want to create new program to read the released running programs - wheather they are idle or not for about 5 minutes. If they are in the idle condition, I want to terminate them.
IDLE means the user not use mouse and keyboard or no process in that program.
As an example, these are my several released programs:
pgrA.exe - Running - Idle 3 Minutes
pgrB.exe - Stopped
pgrC.exe - Running - Idle 7 Minutes
pgrD.exe - Running - not Idle
pgrE.exe - Running - Idle 11 Minutes
My program to terminate idle programs (on single PC):
IdleReader.exe (will terminate pgrC.exe and pgrE.exe)
that all running in 1 PC.
this some codes of the new program to terminate idle Program:
private void refresh_PrgList()
{
using (var con = new SqlConnection(ConfigurationManager.AppSettings["ConnectionStr"]))
using (var cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = "select ProgramID, ProgramName from MKTPrograms";
var reader = cmd.ExecuteReader();
var yy = false;
dgvPrgList.Rows.Clear();
while (reader.Read())
{
yy = false;
foreach (var xx in Process.GetProcesses())
if (xx.ProcessName.Replace(".exe", string.Empty).ToUpper() == reader[0].ToString().Replace(" ", string.Empty).ToUpper())
{
//----- I want to Detect the Idle Program here -----//
//--------------------------------------------------//
dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[0].ToString(), "Running", xx.StartTime, System.DateTime.Now - xx.StartTime });
yy = true;
}
if (yy == false)
dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[1].ToString(), "Stopped", "" });
}
for (int x = 1 ; x < dgvPrgList.Columns.Count ; x++ )
{
dgvPrgList.Columns[x-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
}
}
}
Thanks,
Sure, there are tons of ways to do that.
Look at the processing time (UserProcessorTime,TotalProcessorTime), store it and compare it; you'd get a good feeling about "idle" after some time.
Then just call Kill on the System.Diagnostics.Process class to terminate it.
In .net one can do:
var processName= "yourApp";
if (Process.GetProcessesByName(processName) == null)
Assert.Inconclusive("Skipped: {processName} is not running");
The above code is a unit test, and it can be used to get a specific process, you can find the name you are looking for in your resource monitor:
To see if an application is installed one would simulate the call to start that application, you'd do that like this:
/// <summary>
/// Determines whether the specified application executable is installed.
/// </summary>
/// <param name="name">The command line name.</param>
/// <returns><c>true</c> if the specified name is installed; otherwise, <c>false</c>.</returns>
public static bool IsInstalled(string name)
{
using (var key = Registry.ClassesRoot.OpenSubKey($"{name}\\shell\\open\\command"))
return key != null;
}
One can check if an application is having the right state by looking at the main window. you do this by getting the process as shown before
what I do to see if the application has started but the user is still at his login is:
if (MyAppProcess.MainWindowTitle.Contains("Login"))
return true;
I use:
if (!TCP.IsListing(login.ServerName, login.Port))
Assert.Inconclusive($"Skipped: TWS not accepting connection port {login.Port}");
To see if a method is accepting connections without actually creating a connection, no all applications like it when you just open a socket port, some crash, some corrupt.
The code that does that is listed below, only works locally, you can't do this remote. I use the host as my servers have more than 1 IP and failing to listen will cause my application to fire up a fallback instance and update the DNS server. Easy to create an application failover cluster without having to have enterprise licenses for all your multi-socket multi-core servers ;-)
public static bool IsListing(string hostUri, int portNumber, int millisecondTimeOut=500)
{
try
{
var info = new ProcessStartInfo() {
Arguments = "-a -p TCP",
CreateNoWindow=false,
FileName="netstat",
WindowStyle= ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (var p = Process.Start(info))
using (StreamReader reader = p.StandardOutput)
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.Contains($":{portNumber}"))
{
return true;
}
}
}
return false;
}
catch (SocketException)
{
return false;
}
}
You can see if a host (remote or local) can be reached using a ping. You can do that using:
public static async Task<bool> IsOnline(string hostUri)
{
try
{
object token = Guid.NewGuid().ToString();
using (var p = new Ping())
{
var result= await p.SendPingAsync(hostNameOrAddress: hostUri, timeout: 1000);
return result.Status == IPStatus.Success;
}
}
catch (Exception)
{
return false;
}
}
I am using Selenium WebDriver in an application and I have code to kill the webdrivers and browser instances. However, I am thinking that if the user had any IE browsers open before running the application that this code will kill not only the IE processes spawned by my application but also the IE instances that user had open prior to running the application.
Is there a way to track the processes started by my application so I can filter this method to kill only IE processes spawned by my application, or determine that IE driver and browser instance was spawned by my application, or perhaps both?
public void KillAllBrowsersAndWebDrivers()
{
var webDrivers = Process.GetProcessesByName("IEDriverServer").Select(p => p.Id);
var browsers = Process.GetProcessesByName("iexplore").Select(p => p.Id);
var processIds = webDrivers.Concat(browsers);
// do some stuff with PID, if you want to kill them, do the following
foreach (var pid in processIds)
{
try
{
Process.GetProcessById(pid).Kill();
Logger.Log(Loglevel.Debug, "Kill Process:{0}", pid);
}
catch (Exception)
{
Logger.Log(Loglevel.Error, "Error killing process: {0}", pid);
}
}
}
All you would have to do is keep a list of all the processes you've created.
this is a very simple process manager. This code is error prone, and there is no exception handling
private static List<Process> processes = new List<Process>();
static void Main(string[] args)
{
int PID = StoreProcess (yourProcess);
KillProcess(PID);
}
/// <summary>
/// Stores the process in a list
/// </summary>
/// <returns>The PID</returns>
/// <param name="prc">The process to be stored</param>
public static int StoreProcess(Process prc)
{
int PID = prc.Id; // Get the process PID and store it in an int called PID
processes.Add (prc); // Add this to our list of processes to be kept track of
return PID; // Return the PID so that the process can be killed/changed at a later time
}
/// <summary>
/// Kills a process
/// </summary>
/// <param name="PID">The PID of the process to be killed.</param>
public static void KillProcess(int PID)
{
// Search through the countless processes we have and try and find our process
for (int i = 0; i <= processes.Count; i++) {
if (processes [i] == null)
{
continue; // This segment of code prevents NullPointerExceptions by checking if the process is null before doing anything with it
}
if (processes [i].Id == PID) { // Is this our process?
processes [i].Kill (); // It is! Lets kill it
while (!processes [i].HasExited) { } // Wait until the process exits
processes [i] = null; // Mark this process to be skipped the next time around
return;
}
}
// Couldn't find our process!!!
throw new Exception ("Process not found!");
}
Advantages:
You can keep track of all the processes you've initialized, and terminate them one by one at any time
Drawbacks:
I don't believe there is any
Another possible solution is to get a list of the processes running BEFORE spawning any new processes. Then just kill the ones that are not in the list of previously running processes.
public void KillOnlyProcessesSpawnedBySelenium()
{
// get a list of the internet explorer processes running before spawning new processes
var pidsBefore = Process.GetProcessesByName("iexplore").Select(p => p.Id).ToList();
var driver = new Driver(Settings);
var driver1 = driver.InitiateDriver(); // this method creates new InternetExplorerDriver
var driver2 = driver.InitiateDriver();
var driver3 = driver.InitiateDriver();
driver1.Navigate().GoToUrl("http://google.com");
driver2.Navigate().GoToUrl("http://yahoo.com");
driver3.Navigate().GoToUrl("http://bing.com");
var pidsAfter = Process.GetProcessesByName("iexplore").Select(p => p.Id);
var newInternetExplorerPids = pidsAfter.Except(pidsBefore);
// do some stuff with PID, if you want to kill them, do the following
foreach (var pid in newInternetExplorerPids)
{
Debug.WriteLine("Killing pid: {0}", pid);
Process.GetProcessById(pid).Kill();
}
Assert.IsTrue(pidsBefore.Count > 0);
// determine if each process before the drivers spawned are running
foreach (var running in pidsBefore.Select(pid => Process.GetProcessById(pid).IsRunning()))
{
Assert.IsTrue(running);
}
}
Here is an extension method to use to determine if a process is still running or not...
public static bool IsRunning(this Process process)
{
if (process == null)
throw new ArgumentNullException("process");
try
{
Process.GetProcessById(process.Id);
}
catch (ArgumentException)
{
return false;
}
return true;
}
I have the following function:
private void TakeOverAllScreens()
{
int i = 0;
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
i++;
Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y + "|" + i);
}
}
}
As you can see it creates a separate instance of my application for each screen on the pc.
How can I create an exit function that closes all of them?
The function needs to work on any instance of the app, not just my "Main" instance.
You can terminate all processes with the same name:
var current = Process.GetCurrentProcess();
Process.GetProcessesByName(current.ProcessName)
.Where(t => t.Id != current.Id)
.ToList()
.ForEach(t => t.Kill());
current.Kill();
Just you have to keep track of opened processes:
List<Process> opened = new List<Process>();
private void TakeOverAllScreens()
{
int i = 0;
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
i++;
opened.Add(Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y + "|" + i));
}
}
}
Then:
private void terminateAll()
{
foreach (var p in opened) p.Kill();
}
How can you close an application?
There are three general options:
Kill it outright
Assuming that it has a main window and that it behaves conventionally, send a WM_CLOSE message to that window by P/Invoking SendMessage
Assuming that it wants to cooperate, use a custom communication channel to tell it to terminate itself
How should you close an application?
Killing a process outright is heavy-handed and should never be attempted unless you know that the process won't be doing anything sensitive when it's terminated. Typically this is used as a last resort.
Telling it to close its main window requires that you first learn what that window's HWND is somehow; you can do that by walking the list of top-level windows or by having the spawned process somehow communicate it to you. It also assumes that the other process will decide to terminate itself when you ask that its main window be closed (in reality it could decide to do anything, including completely ignore the message). This approach is a reasonable first attempt and it usually works fine with processes which are not under your control -- although you have to find the window yourself.
Using a custom communication channel allows you to completely control what happens and how plus it can be implemented in lots of ways, but it's an approach that involves writing the most code and needs you to have source access to both applications.
Conclusion
It depends. If you are 1000% sure that killing the process won't disrupt anything then that would be a quick and dirty solution; otherwise you need to use one of the two "polite" approaches.
Put all opened process in list, so you can kill the process one by one. Look code bellow:
private void TakeOverAllScreens()
{
int i = 0;
List<Process> allProcesses = new List<Process>();
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
i++;
allProcesses.Add(Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y + "|" + i));
}
}
foreach (Process proc in allProcesses)
{
proc.Kill();
}
}
I always execute command
tskill notepad // to kill all instances of notepad
From within App, it can be done like
Process.Start("cmd /k tskill " + Process.GetCurrentProcess().ProcessName)
Try this function:
void ExitAll(string processName)
{
foreach(Process p in Process.GetProcesses())
{
if (p.ProcessName.ToLower().Equals(processName.ToLower()))
p.Kill();
}
}
How can I kill some active processes by searching for their .exe filenames in C# .NET or C++?
Quick Answer:
foreach (var process in Process.GetProcessesByName("whatever"))
{
process.Kill();
}
(leave off .exe from process name)
My solution is to use Process.GetProcess() for listing all the processes.
By filtering them to contain the processes I want, I can then run Process.Kill() method to stop them:
var chromeDriverProcesses = Process.GetProcesses().
Where(pr => pr.ProcessName == "chromedriver"); // without '.exe'
foreach (var process in chromeDriverProcesses)
{
process.Kill();
}
Update:
In case if you want to do the same in an asynchronous way (using the C# 8 Async Enumerables), check this out:
const string processName = "chromedriver"; // without '.exe'
await Process.GetProcesses()
.Where(pr => pr.ProcessName == processName)
.ToAsyncEnumerable()
.ForEachAsync(p => p.Kill());
Note: using async methods doesn't always mean code will run faster.
The main benefit is that the foreground thread will be released while operating.
You can use Process.GetProcesses() to get the currently running processes, then Process.Kill() to kill a process.
If you have the process ID (PID) you can kill this process as follow:
Process processToKill = Process.GetProcessById(pid);
processToKill.Kill();
You can Kill a specific instance of MS Word.
foreach (var process in Process.GetProcessesByName("WINWORD"))
{
// Temp is a document which you need to kill.
if (process.MainWindowTitle.Contains("Temp"))
process.Kill();
}
Depending on how many processes there are to kill (e.g. when its hundreds like in my case), foreaching over all of them might take quite a while. (interesting sidenote: while Kill() was usually quite quick in .NET FW 4.8 , somehow in NET 6.0 Windows its a lot slower - seeing multiple Win32Exceptions in the debug/trace until the target process is finally done)
Anyway back to topic:
In case of an app shutdown, where u need to make sure every process is is gone, consider using the TAP library - particulary the Parallel shortcuts, hundreds of processes killed within a glimpse.
Usage example:
var procs = Process.GetProcessByName("mydirtyprocesses");
if (procs.Length == 0) return;
procs.AsParallel().ForAll(process =>
{
try
{
process.Kill();
// No process linked to the process comp (mostly because the process died in
// the short timespan between invoking GetProcess() and the effective
// initialization of the props/fields of the component. -OR- Process has
// already exited (when the exit happened after the process component has
// beenpopulated (difference is, in case 1 you cannot even get the Process
// ID from // the component, in case 2 you see data like Id and get the true
// for HasExited // - so always be prepared for that.
// catch (InvalidOperationException)
{
// Process is gone, no further action required
return;
}
// Ensuring process is gone (otherwise try again or fail or whatever)
if (!process.HasExited)
{
// Handle it
}
}
In this particular scenario just wrap it properly in try/catch , as with such a number of processes the probability for an exception is quite increased
static void Main()
{
string processName = Process.GetCurrentProcess().ProcessName;
int processId = Process.GetCurrentProcess().Id;
Process[] oProcesses = Process.GetProcessesByName(processName);
if (oProcesses.Length > 1)
{
if ((MessageBox.Show("Application is opened!", "",MessageBoxButtons.YesNo) == DialogResult.Yes)) ;
{
foreach (var process in Process.GetProcessesByName(processName))
{
if (process.Id != processId)
{
process.Kill();
}
}
}
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmLogin());
}
}
public void EndTask(string taskname)
{
string processName = taskname.Replace(".exe", "");
foreach (Process process in Process.GetProcessesByName(processName))
{
process.Kill();
}
}
//EndTask("notepad");
Summary: no matter if the name contains .exe, the process will end. You don't need to "leave off .exe from process name", It works 100%.