How to get information about process (cpu, memory, disk & network usage) in C# application?
P.S. System.Diagnostics.Process and System.Diagnostics.PerformanceCounter doesn't provide information about disk and network usage. I don't use it.
System.Text.StringBuilder sb = new System.Text.StringBuilder();
var currentProcess = System.Diagnostics.Process.GetCurrentProcess();
sb.AppendLine("Process information");
sb.AppendLine("-------------------");
sb.AppendLine("CPU time");
sb.AppendLine(string.Format("\tTotal {0}",
currentProcess.TotalProcessorTime));
sb.AppendLine(string.Format("\tUser {0}",
currentProcess.UserProcessorTime));
sb.AppendLine(string.Format("\tPrivileged {0}",
currentProcess.PrivilegedProcessorTime));
sb.AppendLine("Memory usage");
sb.AppendLine(string.Format("\tCurrent {0:N0} B", currentProcess.WorkingSet64));
sb.AppendLine(string.Format("\tPeak {0:N0} B", currentProcess.PeakWorkingSet64));
sb.AppendLine(string.Format("Active threads {0:N0}", currentProcess.Threads.Count));
etc.
As a starter this get a list of all processes and loop over it:
using System.Diagnostics;
//...
Process[] all = Process.GetProcesses();
foreach (Process thisProc in all) {
string Name = thisProc.ProcessName;
//...
}
Add this line to your using list:
using System.Diagnostics;
Now you can get a list of the processes with the Process.GetProcesses() method, as seen in this example:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist)
{
Console.WriteLine(“Process: {0} ID: {1}”, theprocess.ProcessName, theprocess.Id);
}
In System.Diagnostics there is a class called Process which allows you to statically get Processess by name, ID,etc. So you can do something like
Process p = Process.GetCurrentProcess();
int pageMemSize = p.PagedMemorySize;
There are a lot of different properties of the class. Look at the Process class here
Related
I've build a Windows service with C# which get all running applications on my computer (Notepad,...). I've tryed this following code but it doesn't work :
Thank you all for your help!
Process[] processes = Process.GetProcesses();
using (TextWriter tw = new StreamWriter(#"C:\Users\Public\Documents\Info.txt"))
{
foreach(Process p in processes)
{
if(!String.IsNullOrEmpty(p.MainWindowTitle))
{
tw.WriteLine(p.MainWindowTitle);
}
}
}
That's why you are checking MainWindowTitle on your code. You have to know MainWindowTitle has value just for those processes which they have GUI like notepad or skype or ...
To identify all the process name it's better to check ProcessName property to get the process name.
So I recommend you to change your code like this:
using (TextWriter tw = new StreamWriter(#"C:\Users\Public\Documents\Info.txt"))
{
foreach (Process p in processes)
{
if (!String.IsNullOrEmpty(p.ProcessName))
{
var processTitle= !string.IsNullOrEmpty(p.MainWindowTitle) ? p.MainWindowTitle: "N/A";
tw.WriteLine(string.Format("Process Name: {0} \t\t Process GUI Title:{1}",p.ProcessName, processTitle));
}
}
}
I write my app in C# and I have one problem. I have some executable file for example "spotify.exe". This app is running and i have to get title of window.
I am new in C# and I can't do this.
Could you help me?
Use the MainWindowTitle property of the Process class :
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
if (!string.IsNullOrEmpty(process.MainWindowTitle))
{
Console.WriteLine("Window title of {0} : {1}", process.ProcessName, process.MainWindowTitle);
}
}
EDIT:
Note that processes without a Form (e.g. console applications, background processes) will return an empty string for their MainWindowTitle .
Get the process - Process [] localByName = Process.GetProcessesByName("notepad");
Get the title - string Title = process.MainWindowTitle
As an example, to get the Spotify window title;
var procs = Process.GetProcessesByName("Spotify");
foreach (var p in procs)
{
if (!string.IsNullOrEmpty(p.MainWindowTitle))
{
Label1.Text = p.MainWindowTitle;
}
}
I write an application that starts a 3rd party program that downloads a media stream from a tv channel on my program. The program I am using is rtmpdump.exe. They run as independent processes like this:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = path + rtmpdump;
startInfo.Arguments = rtmpdump_argument;
startInfo.WorkingDirectory = path;
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process p = Process.Start(startInfo);
But I would like to name these processes, so if my program crashes or has to be restarted, then I can check the names of the current processes to see if for example there is one called "BBC World - News at 7". Something like that to identify which has already been started and is currently running. Is it possible? I can't find a way to set a friendly name.
Extending what Alexei said - you could create a Dictionary< int, string > to keep track of the process ID / descriptive name that you create. Maybe you should write this out to a file in case your program crashes - but you'd need some special startup handling to deal with processes exiting.
On startup you'd want to read in the file, and check current processes to see if they match with what you have, and remove any processes that no longer exist (wrong process id or exe name). You might want to do that every time you create a new process and write to the file.
You can't change process names, but instead you can:
use Process.Id to identify processes (Id: "...system-generated unique identifier of the process...")
get process command line and see if there anything interesting (may need some PInvoke / WMI for that - How to read command line arguments of another process in C#?).
Here is some code that you could use.
public class ProcessTracker {
public Dictionary<int, string> Processes { get; set; }
public ProcessTracker() {
Processes = new Dictionary<int, string>();
}
public void AddProcess(Process process, string name) {
Processes.Add(process.Id, name);
}
//Check if what processes are still open after crash.
public void UpdateProcesses() {
List<Process> runningProcesses =
Process.GetProcesses().ToList();
Processes = Processes
.Where(pair => runningProcesses
.Any(process => process.Id == pair.Key))
.ToDictionary(pair => pair.Key, pair => pair.Value);
}
//Use this to see if you have to restart a process.
public bool HasProcess(string name) {
return Processes.Any(pair => pair.Value != name);
}
//Write the file on crash.
public void ReadFile(string path) {
if (!(new FileInfo(path).Exists))
return;
using (StreamReader reader = new StreamReader(path)) {
foreach (string line in reader.ReadToEnd()
.Split(new[] {"\n"}, StringSplitOptions.RemoveEmptyEntries)) {
string[] keyPair = line.Split(',');
Processes.Add(int.Parse(keyPair[0]), keyPair[1]);
}
}
}
//Read the file on startup.
public void SaveFile(string path) {
using (StreamWriter writer = new StreamWriter(path, false)) {
foreach (KeyValuePair<int, string> process in Processes) {
writer.WriteLine("{0},{1}",
process.Key, process.Value);
}
}
}
}
Writing the process information to a file (or a memory mapped file) might be the way to go;
However, you could also look into windows messaging. i.e. send a message to each process; and have them reply with their "internal name".
Basically you have everything listen in on that queue; You first send a command that orders the other process to report their internal name, which they then dump into the message queue along with their own process id;
See MSMQ
I had the same question to myself, for my solution created a new class -
MyProcess which inherits from Process and added a property - ProcessId.
In my case I store the ProcessId on a db which is acossiated to other data. Based on the status of the other data I decide to kill the process.
Then I store process on a dictionary which can be passed to other classes if needed where can be access to kill a process.
So when I decide to kill a process, I pull the process from the dictionary by ProcessId and then kill it.
Sample below:
public class Program
{
private static Dictionary<string, MyProcess> _processes;
private static void Main()
{
// can store this to file or db
var processId = Guid.NewGuid().ToString();
var myProcess = new MyProcess
{
StartInfo = { FileName = #"C:\HelloWorld.exe" },
ProcessId = processId
};
_processes = new Dictionary<string, MyProcess> {{processId, myProcess}};
myProcess.Start();
Thread.Sleep(5000);
// read id from file or db or another
var pr = _processes[processId];
pr.Kill();
Console.ReadKey();
}
}
public class MyProcess : Process
{
public string ProcessId { get; set; }
}
I have to 2 process excel. For example:
1) example1.xlsx
2) example2.xlsx
How to kill first "example1.xlsx"?
I use this code:
foreach (Process clsProcess in Process.GetProcesses())
if (clsProcess.ProcessName.Equals("EXCEL")) //Process Excel?
clsProcess.Kill();
That kill a both.
I wanna kill just one...
Thank you.
The ProcessMainWindow Title will do it for you, it appends "Microsoft Excel - " to the name of the file:
So essentially (quick code):
private void KillSpecificExcelFileProcess(string excelFileName)
{
var processes = from p in Process.GetProcessesByName("EXCEL")
select p;
foreach (var process in processes)
{
if (process.MainWindowTitle == "Microsoft Excel - " + excelFileName)
process.Kill();
}
}
Use:
KillSpecificExcelFileProcess("example1.xlsx");
Edit: Tested and verified to work.
kd7's post is an awesome answer and works well, just two things to add,
MainWindowTitle format is - "Filename.xlsx - Excel"
If your excel document is not visible then your MainWindowTitle will be ""
using the "" for MainWindowTitle will kill all zombie excel process'.
If your current code is working, this amendment should kill the first process it finds with the name "EXCEL".
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL"))
{
clsProcess.Kill();
break;
}
}
If you want to kill a specific process, you're going to have to give a bit more information.
Excel will always be a single process, AFAIK. The same process/windows opens multiple documents inside it. What you want to do is use Excel automation to CLOSE the document you want to. Perhaps this will get you started. http://support.microsoft.com/kb/302084
Hope this helps.
Copy and paste this. Its done!
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
You need to check file handles, that are opened by process and then kill it.
How to check which file handles process is holding: How do I get the list of open file handles by process in C#?
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL") && HasFileHandle(fileName, clsProcess))
{
clsProcess.Kill();
break;
}
}
Try getting the main window title
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Equals("EXCEL")&& clsProcess.MainWindowTitle =="example")
{
clsProcess.CloseMainWindow();
break;
}
}
just did a quick search on Google, try Process.MainWindowTitle() to get the title of the Excel process, and decide which one is that you want to kill.
I am not sure about this method, but hope this will help:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowtitle.aspx
Use below logic to prevent Zombie Excel processes in Task Manager
List<int> GetAllExcelProcessID()
{
List<int> ProcessID = new List<int>();
if (currentExcelProcessID == -1)
{
List<System.Diagnostics.Process> currentExcelProcessList = System.Diagnostics.Process.GetProcessesByName("EXCEL").ToList();
foreach(var item in currentExcelProcessList)
{
ProcessID.Add(item.Id);
}
}
return ProcessID;
}
int GetApplicationExcelProcessID(List<int> ProcessID1, List<int> ProcessID2)
{
foreach(var processid in ProcessID2)
{
if (!ProcessID1.Contains(processid)) { currentExcelProcessID = processid; }
}
return currentExcelProcessID;
}
void KillExcel()
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetProcessById(currentExcelProcessID);
process.Kill();
}
List<int> ProcessID1 = GetAllExcelProcessID();
excel = new Excel.Application();
List<int> ProcessID2 = GetAllExcelProcessID();
currentExcelProcessID = GetApplicationExcelProcessID(ProcessID1, ProcessID2);
In the namespace section add this using statement.
using System.Diagnostics;
This example instantiated Excel with this:
_Application excel = new _Excel.Application();
This method kills the right Excel task by using the window handle.
public void Kill()
{
Int32 ExcelHwnd = excel.Hwnd;
Process[] localExcel = Process.GetProcessesByName("EXCEL");
foreach (Process Pgm in localExcel)
{
// xlMinimized keeps the screen from flashing when the user interface is made
// visible with the excel.visible needed to set the MainWindowHandle
excel.WindowState = XlWindowState.xlMinimized;
excel.Visible = true;
if ((Pgm.ProcessName == "EXCEL") && (ExcelHwnd == Pgm.MainWindowHandle.ToInt32()))
{
Pgm.Kill();
}
}
}
This worked without fail.
How to kill specific process running under specific user account. using C#?
Thanks,
var processes = from p in Process.GetProcessesByName(nameOfTheProcess)
where p.StartInfo.UserName == nameOfTheUser
select p;
foreach(Process p in processes) p.Kill();
EDIT: as Fredrik pointed out, the UserName property is not set for processes obtained by GetProcesses. Here's a modified version that uses WMI to get the username (GetProcessOwner method found here) :
static void KillProcessByNameAndUserName(string processName, string userName)
{
var processes = from p in Process.GetProcessesByName(processName)
where GetProcessOwner(p.Id) == userName
select p;
foreach(Process p in processes) p.Kill();
}
static string GetProcessOwner(int processId)
{
string query = “Select * From Win32_Process Where ProcessID = “ + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod(“GetOwner”, argList));
if (returnVal == 0)
return argList[0];
}
return “NO OWNER”;
}
In order to get the username, you have to grab the security context of the process from the Win32 API.
Call the OpenProcessToken() function via P/Invoke using the process handle found in the .Net Process class from the code you already have above. You will obtain a structure that contains a SID for the owner of the process. Be prepared for errors such as Access Denied, since you may not have access rights to obtain this information for all processes, such as those that are not yours. From there, you have to convert the SID to a name. There are a few ways to do this, but LookupAccountSid() function (again, via P/Invoke) will get the username for you.
In framework 2.0, a bunch of stuff was added to help with dealing with security descriptors (System.Security.AccessControl namespace), however, I don't see anything that will help you in dealing with the P/Invoke complexities there.
See pinvoke.net for information on using the Win32 API from C#.