進程(Process)是Windows系統中的一個基本概念,它包含着一個運行程序所需要的資源。進程之間是相對獨立的,一個進程無法直接訪問另一個進程的數據(除非分布式),一個進程運行的失敗也不會影響其他進程的運行,Windows系統就是利用進程把工作划分為多個獨立的區域的。
進程可以理解為一個程序的基本邊界。
一、Process的常用屬性與方法
在System.Diagnostics命名空間當中存在Process類,專門用於管理進程的開始、結束,訪問進程中的模塊,獲取進程中的線程,設定進程的優先級別等。
Process類常用屬性:
屬性 | 說明 |
BasePriority | 獲取關聯進程的基本優先級。 |
ExitCode | 獲取關聯進程終止時指定的值。 |
ExitTime | 獲取關聯進程退出的時間。 |
Handle | 返回關聯進程的本機句柄。 |
HandleCount | 獲取由進程打開的句柄數。 |
HasExited | 獲取指示關聯進程是否已終止的值。 |
Id | 獲取關聯進程的唯一標識符。 |
MachineName | 獲取關聯進程正在其上運行的計算機的名稱。 |
MainModule | 獲取關聯進程的主模塊。 |
Modules | 獲取已由關聯進程加載的模塊。 |
PriorityClass | 獲取或設置關聯進程的總體優先級類別。 |
ProcessName | 獲取該進程的名稱。 |
StartInfo | 獲取或設置要傳遞給Process的Start方法的屬性。 |
StartTime | 獲取關聯進程啟動的時間。 |
SynchronizingObject | 獲取或設置用於封送由於進程退出事件而發出的事件處理程序調用的對象。 |
Threads | 獲取在關聯進程中運行的一組線程 |
Process類常用方法:
方法 | 說明 |
GetProcessById | 創建新的 Process 組件,並將其與您指定的現有進程資源關聯。 |
GetProcessByName | 創建多個新的 Process 組件,並將其與您指定的現有進程資源關聯。 |
GetCurrentProcess | 獲取新的 Process 組件並將其與當前活動的進程關聯。 |
GetProcesses | 獲取本地計算機上正在運行的每一個進程列表。 |
Start | 啟動一個進程。 |
Kill | 立即停止關聯的進程。 |
Close | 釋放與此組件關聯的所有資源。 |
WaitForExit | 指示 Process 組件無限期地等待關聯進程退出。 |
Microsoft關於Process的說明:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.aspx
二、信息傳遞
StartInfo這個屬性專門用於傳遞信息到被調用的程序。
其類型是:System.Diagnostics.ProcessStartInfo,MSDN地址為:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.processstartinfo.aspx。
其屬性也很多,無法一一詳述。
為了展示其作用,我設計了兩個控制台程序。
第一個控制台程序代碼如下:
static void Main(string[] args) { foreach(string arg in args) { Console.WriteLine(arg); } Console.ReadKey(); }
然后生成,然后將其生成的exe文件的路徑作為參數,放在第二個控制台程序中。
static void Main(string[] args) { Process process = new Process(); process.StartInfo.FileName = @"C:\Users\ChenZhuo\Desktop\MyConsoleApplication\MyConsoleApplication\bin\Debug\MyConsoleApplication.exe"; process.StartInfo.Arguments = string.Format("姓名:劉備 年齡:26"); process.Start(); Console.ReadKey(); }
啟動時輸出如下:
可以看到StartInfo這個屬性主要用於調用程序向被調用程序傳遞信息。
被調用程序的參數在Main(string[] args)這里接收,默認是通過空格分隔。
三、建立與銷毀進程
利用Start與Kill方法可以簡單建立或者銷毀進程,下面以一個例子:用Start方法啟動記事本的進程,並打開File.txt文件。2秒鍾以后使用Kill方法銷毀進程並關閉記事本。然后又用google瀏覽器打開百度首頁兩秒后關閉。
public class Program { static void Main(string[] args) { //打開記事本 Process process = Process.Start("notepad.exe", "D:123.txt"); Thread.Sleep(2000); process.Kill(); //打開google瀏覽器,並打開百度 Process process2 = Process.Start("chrome.exe", "http://www.baidu.com"); Thread.Sleep(20000); process.Kill(); Console.ReadKey(); } }
顯示如下:
四、顯示計算機運行中的進程
使用 GetProcesses 方法可以獲取本地計算機上正在運行的每一個進程列表。而進程的 Id 屬性是每個進程的唯一標志,通過下面的方法,可以顯示當前計算機運行的所有進程信息。
public class Program { static void Main(string[] args) { var processList = Process.GetProcesses(); foreach (var process in processList) { Console.WriteLine(string.Format("ProcessId is:{0} \t ProcessName is:{1}", process.Id, process.ProcessName)); } Console.ReadKey(); } }
輸出結果如下:
如果已經知道了進程的Id,就可以通過GetProcessId方法獲取對應的進程:
public class Program { static void Main(string[] args) { try { Process p = Process.GetProcessById(6888); Console.WriteLine(p.ProcessName); //輸出 QQExternal } catch(Exception e) { Console.WriteLine(e.Message); } Console.ReadKey(); } }
同樣地,你也可能通過GetProcessByName方法獲取多個對應名稱的進程:
static void Main(string[] args) { Process[] pArr = Process.GetProcessesByName("QQExternal"); Console.WriteLine(pArr[0].Id); //輸出 6888 Console.ReadKey(); }
注意:如果不能找到當前ID的進程,系統就會拋出ArgumentException異常。所以使用方法 GetProcessById 獲取進程時應該包含在 try{...} catch{..} 之內。
五、獲取進程中的多個模塊
Process類中有一個Modules屬性,通過此屬性可能獲取進程中的多個模塊。
這些模塊可以是以*.dll結尾的程序集,也可以使*.exe結尾的可執行程序。
通過Process的GetCurrentProcess方法可以獲取當前運行的進程信息,然后顯示當前進程的多個模塊信息。
class Program { static void Main(string[] args) { var modulelist = Process.GetCurrentProcess().Modules; foreach (ProcessModule pm in modulelist) { Console.WriteLine("模塊名:" + pm.ModuleName + "文件名:" + pm.FileName + "版本號:" + pm.FileVersionInfo.FileVersion); } Console.ReadKey(); } }
輸出結果如下:
六、綜合示例,進程管理器
Process用於管理計算機的進程,下面給出一個C#進程管理器的DEMO。
namespace ProcessManager { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { listView1.FullRowSelect = true; GetProcess(); } private void GetProcess() { listView1.Items.Clear(); Process[] proList = Process.GetProcesses(".");//獲得本機的進程 lblNumber.Text = proList.Length.ToString(); //當前進程數量 foreach (Process p in proList) { ListViewItem lvi = new ListViewItem(); lvi.Text = p.ProcessName; lvi.SubItems.AddRange(new string[] { p.Id.ToString(), p.PrivateMemorySize64.ToString() }); //進程ID 使用內存 listView1.Items.Add(lvi); } } private void btnStop_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count > 0) { try { string proName = listView1.SelectedItems[0].Text; Process[] p = Process.GetProcessesByName(proName); //根據進程命獲得指定的進程 p[0].Kill(); //殺死該進程 MessageBox.Show("進程關閉成功!"); GetProcess(); } catch { MessageBox.Show("無法關閉此進程!"); } } else { MessageBox.Show("請選擇要終止的進程!"); } } private void btnStart_Click(object sender, EventArgs e) { if (txtProcess.Text != string.Empty) { Process.Start(txtProcess.Text); //啟動一個進程 } else { MessageBox.Show("請輸入啟動項"); txtProcess.Focus(); } } } }
顯示如下: