版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
通常开发时想要获得进程是比较困难的事,必须要调用CreateToolhelpSnapshot、ProcessFirst、ProcessNext等API或者诸如 ZwQueryVirtualMemory这样的API,是非常繁琐的事。而在C#中,使用Process类就可以获得系统中运行的进程信息。Process类是在System.Diagnostics命名空间下,使用时可以先加入:
using System.Diagnostics;
【例 15.1】【项目:code15-001】枚举计算机中的进程。
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
foreach (Process pro in Process.GetProcesses())
listBox1.Items.Add(pro.ProcessName);
}
使用Process类一个循环就可以完成对进程的枚举。运行结果如下图所示:
图15-1 枚举计算机中的进程
Process常用属性:
- Id:获取进程的唯一标识符。
- MainModule:获取进程的主模块。
- MainWindowTitle:获取进程的主窗口标题。注意:只有当进程具有图形界面的情况下,才有与之关联的主窗口。
- MainWindowHandle:获取进程主窗口的窗口句柄。
- Modules:获取已由进程加载的模块。
- ProcessName:获取该进程的名称。
- StartInfo:要传递给 Process 的 Start 方法的属性。
- StartTime:获取进程启动的时间。
- HasExited :指示进程是否已终止。
- ExitTime:进程退出的时间。注意:只有进程退出后才能调用此属性,否则会产生错误,请先用HasExited属性判断进程是否已经终止。
- Threads:获取在进程中运行的一组线程。
- PriorityClass:进程的总体优先级类别。
- BasePriority:获取进程的基本优先级。
- EnableRaisingEvents:在进程终止时是否应引发 Exited 事件。
- MachineName:获取进程正在其上运行的计算机的名称。
- NonpagedSystemMemorySize64:获取为进程分配的非分页系统内存量。
- PagedMemorySize64:获取为进程分配的分页内存量。
- PagedSystemMemorySize64:获取为进程分配的可分页系统内存量。
- PeakPagedMemorySize64:获取进程使用的虚拟内存分页文件中的最大内存量。
- PeakVirtualMemorySize64:获取进程使用的最大虚拟内存量。
- PeakWorkingSet64:获取进程使用的最大物理内存量。
- PriorityBoostEnabled:指示主窗口拥有焦点时是否应由操作系统暂时提升关联进程优先级。
- PrivateMemorySize64:获取为进程分配的专用内存量。
- PrivilegedProcessorTime:获取进程的特权处理器时间。
- Responding:获取指示进程的用户界面当前是否响应的值。
- TotalProcessorTime:获取进程的总的处理器时间。
- UserProcessorTime:获取进程的用户处理器时间。
- VirtualMemorySize64:获取为进程分配的虚拟内存量。
- WorkingSet64:获取为进程分配的物理内存量。
Process常用方法:
- Start:启动进程资源。通常情况下,参数可以直接传递文件路径或网址的字符串,进程会调用关联的程序打开参数指定的文件或网址。例如:
默认程序(通常是记事本)打开文本文件:
Process.Start("C:\\lessons\\将进酒.txt");
或者默认浏览器打开网址:
Process.Start("http://www.csdn.net");
- Kill:强制终止进程。注意:不建议使用此方法终止进程,因为此方法会导致进程立即终止,导致进程不能处理退出前的必要工作(比如有些程序会在退出前保存当前设置),导致进程异常终止。通常情况下应使用CloseMainWindow来结束进程。
- GetProcesses:创建新的 Process 组件的数组,并将它们与现有进程资源关联。
- GetProcessesByName:创建新的 Process 组件的数组,并将它们与共享指定的进程名称的所有现有进程资源关联。
- Process.GetProcessById:创建新的 Process 组件,并将其与您指定的现有进程资源关联。
- GetCurrentProcess:获取新的 Process 组件并将其与当前活动的进程关联。
- Close:释放与此组件关联的所有资源。
- CloseMainWindow:通过向进程的主窗口发送关闭消息来关闭拥有用户界面的进程。
15.1.1 获得进程信息
获得进程信息先是通过GetProcesses方法获得所有的进程,然后使用GetProcessById方法获得Process实例,然后获得Process的属性
【例 15.2】【项目:code15-002】获得进程详细信息。
在窗体上防止一个Button控件、一个ListView控件、TextBox控件。
ListView控件用于显示当前系统中的进程,TextBox控件用于显示进程对应的信息。
具体代码如下:
//将系统中的进程及对应Id显示于ListView1中
private void button1_Click(object sender, EventArgs e)
{
listView1.Items.Clear();
foreach(Process pro in Process.GetProcesses())
{
ListViewItem lvPro = new ListViewItem(pro.ProcessName);
lvPro.SubItems.Add(pro.Id.ToString());
listView1.Items.Add(lvPro);
}
}
//单击listView1中的项时,显示进程相关信息
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count != 1)
return;
ListViewItem lvpro = new ListViewItem();
lvpro = listView1.SelectedItems[0];
int proid = int.Parse(lvpro.SubItems[1].Text);
//由于进程Id是唯一标识,所以使用GetProcessById来获得进程
Process pro = Process.GetProcessById(proid);
string proinfo = "";
//进程相关信息:Process类相关属性
proinfo += "进程的名称:" + pro.ProcessName + "\r\n";
proinfo += "物理内存量:" + pro.WorkingSet64 + "\r\n";
proinfo += "最大物理内存:" + pro.PeakWorkingSet64 + "\r\n";
proinfo += "虚拟内存量:" + pro.VirtualMemorySize64 + "\r\n";
proinfo += "最大虚拟内存:" + pro.PeakVirtualMemorySize64 + "\r\n";
proinfo += "优先级:" + pro.BasePriority + "\r\n";
try
{
proinfo += "进程启动的时间:" + pro.StartTime.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n";
}
catch (Exception ex)
{
proinfo += "进程启动的时间:-" + "\r\n";
}
try
{
proinfo += "总的处理器时间:" + pro.TotalProcessorTime.ToString() + "\r\n";
}
catch (Exception ex)
{
proinfo += "总的处理器时间:-" + "\r\n";
}
try
{
proinfo += "总的处理器时间:" + pro.TotalProcessorTime.ToString() + "\r\n";
}
catch (Exception ex)
{
proinfo += "总的处理器时间:-" + "\r\n";
}
proinfo += "主窗口句柄:" + pro.MainWindowHandle.ToString() + "\r\n";
try
{
proinfo += "主窗口标题:" + pro.MainWindowTitle + "\r\n";
}
catch (Exception ex)
{
proinfo += "主窗口标题:-" + "\r\n";
}
textBox1.Text = proinfo;
}
为了防止出错,在代码中加入了try...catch语句。造成错误的原因和如何解决错误,请看第15.2节。
运行结果如下图所示:
图15-2 计算机进程及相关信息
15.1.2 进程加载的模块
进程加载的模块是加载到特定进程的.dll或.exe文件,每个进程包含一个或多个模块,为进程提供不同的功能。
获得进程加载的模块主要使用到了Process类的MainModule和Modules属性。MainModule就是一个ProcessModule类,而Process.Modules是包含了多个ProcessModule类的数组(ProcessModuleCollection)。ProcessModule类允许查看相关模块,包括模块名称、对应文件名和内存等详细信息。
ProcessModule常用属性:
- BaseAddress:加载模块的内存地址。
- FileName:模块的完整路径。
- FileVersionInfo:获取模块的版本信息。
- ModuleMemorySize:获取加载模块所需内存大小。
- ModuleName:获取模块的名称。
【例 15.3】【项目:code15-003】获得进程加载模块信息。
请在【例 15.2】基础上增加一个ListView2控件。当在ListView1中选中一个进程的时候,同时获得记载的模块信息。具体代码如下:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
……
textBox1.Text = proinfo;
listView2.Items.Clear();
ProcessModule mainMod=null;
ListViewItem lvMod;
//增加主模块的信息
try
{
mainMod = pro.MainModule;
//模块名称
lvMod = new ListViewItem(mainMod.ModuleName);
//内存地址
lvMod.SubItems.Add(mainMod.BaseAddress.ToString()); //不能用ToInt32
//版本信息
lvMod.SubItems.Add(mainMod.FileVersionInfo.FileVersion);
//内存大小
lvMod.SubItems.Add(mainMod.ModuleMemorySize.ToString());
//完整路径
lvMod.SubItems.Add(mainMod.FileName);
listView2.Items.Add(lvMod);
}
catch (Exception ex)
{
//不处理错误
}
try
{
foreach(ProcessModule proMod in pro.Modules)
{
//注意:主模块也在Modules里面,必须要排除开。
if ((proMod.ModuleName == mainMod.ModuleName) && (proMod.BaseAddress == mainMod.BaseAddress))
continue;
lvMod =new ListViewItem(proMod.ModuleName);
lvMod.SubItems.Add(proMod.BaseAddress.ToString());
lvMod.SubItems.Add(proMod.FileVersionInfo.FileVersion);
lvMod.SubItems.Add(proMod.ModuleMemorySize.ToString());
lvMod.SubItems.Add(proMod.FileName);
listView2.Items.Add(lvMod);
}
}
catch (Exception ex)
{
//不处理错误
}
}
注意:代码先是在listview2中列出了主模块的信息,由于Modules属性将会再次获得主模块,所以加了一句判断模块名称是否与主模块名称一致,如果一致就不再列出。
运行结果如下图所示:
图15-3 获取进程相关信息和相关模块
发生错误,因为默认编译为32位程序,无法访问64位进程的模块,请参看第13.3节,修改成编译为64位程序后,运行结果如下图所示:
图15-4 获取进程相关信息和相关模块
学习更多vb.net知识,请参看vb.net 教程 目录
学习更多C#知识,请参看C#教程 目录