.Net中对进程的操作
IT商界
认识进程
在《.Net中的多线编程》中我们讲了与线程相关的编程方法,在这一节中我们就来谈谈上次没讲到的方面──进程。进程的英文表示是Proccss,所以凡是类名中含有Proccss的都是与进程有关的类。用最简短的话来说,进程就是当前运行的应用程序。运行的应用程序包括EXE、DLL这两种文件。文件和进程的差别在于,文件是保存在磁盘上的,是静止的。而进程是非静止的,正是由于这个原因,所以计算机每调用一个进程就需要一定的资源。这些资源包括内存、虚拟页面、GDI等资源。
VB.Net中进程
在VB.Net中我们可以用Process类,即进程类来对计算机上运行的进程进行访问。它包括下面两个方面。
1.使用Process类,可以获取计算机中当前运行的进程的列表(包括后台进程),或者启动一个新的进程。
2.可使用该类来获取当前运行的进程的相关信息。此类信息包括此进程中包括的线程、此进程在运行时调用的模块(.dll和.exe文件)和性能信息(如进程当前使用的内存量等)。
除了Process类外,与进程有关的类还包括下面两个重要的类ProcessThread和ProcessModule。这两个类可以说是Process的辅助类,它们分别表示与进程相关的线程类和与进程相关的模块类。使用这两个类我们就可以实现2中所说的功能了。在下面的这个代码中,我们会看见这两个类所发挥的作用。
现在我们就通过一个实际的例子来看看如何在.Net中进行进程的编程。这个例子将模仿Win NT、Win 2000、Win XP的任务管理器,并且这个程序所查看的信息比Win NT、Win 2000、Win XP的任务管理器的信息更多。
做个任务管理器
首先在VB.Net建立一个窗口,在窗口上加上一个TabControl分页控件,在第一页加上label1,label2,listbox1,listbox2,button1。在第二页上加上label4,label6,listbox3,listbox4,在第三页上加上label5,label7,listbox5,listbox6。将所有的listbox控件的HorizontalScrollbar属性设置为true。Button1的text属性为“查看本机进程”,其于控件保持默认属性。在代码中将给出详细的注释。
添加进程到列表框
在代码的开头声明对象,使其在整个程序段中可用
Public Class Form1
Inherits System.Windows.Forms.Form
Public zj'用来获得在listbox1中进程的编号,此变量在整个程序段中都有用
Public myProcesses() As Process'声明一个进程数组来存放检查到的进程
Public myProcess As Process'声明一个进程对象来检查有哪些进程在运行,并且将找到的进程放入进程数组中
双击Button1控件在Click事件添加如下代码:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ListBox1.Items.Clear()'清空listbox1
myProcesses = Process.GetProcesses()'创建刚才声明的进程数组,使它可用
For Each myProcess In myProcesses
ListBox1.Items.Add(myProcess.ProcessName)'此循环开始检查计算机中有多少个进程在运行,并将找到的进程名加入到列表框中
Next
Label1.Text = ""'将label清空
Label1.Text = "本机共有" & ListBox1.Items.Count & "个进程在运行"'在label中显示
End Sub
程序说明:本段代码通过一个循环将找到的进程添加到列表框中,从而显示计算机中到底有多少个进程在运行。在这段代码中重点是FOR循环,它不同于记次循环,他是通过一种称为迭代的方法进行有条件的循环。即首先检查是否有一个进程在运行,如有则加入列表框中,再检查是否有第二个进程在运行,如有再加入列表框中,依此类推,直到检查到计算机中没有进程在运行时,才停止循环。
获取系统信息
双击ListBox1控件在DoubleClick事件添加如下代码:
Private Sub ListBox1_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.DoubleClick
Dim i:Dim f As Integer:Dim h As Integer
ListBox2.Items.Clear()'清空ListBox2的内容
zj = ListBox1.SelectedIndex'在双击ListBox1中的进程名时将此进程的编号传递给zj这个变量进行保存
Label2.Text = "进程" & ListBox1.Items.Item(zj) & "的相关信息"
With ListBox2.Items'将下面的内容显示在ListBox2中,zj表示要显示相关进程的编号
If myProcesses(zj).MainWindowTitle = "" Then'此分支用来判断进程是否有窗口,因为有的进程是没有主窗口的,如有就将它显示在ListBox2中,反之显示“无相关主窗口”的文字
.Add("无相关主窗口")
Else
.Add(myProcesses(zj).MainWindowTitle)
End If
.Add(myProcesses(zj).BasePriority & "进程的基本优先级")
.Add(myProcesses(zj).Handle.ToString & "进程的本机句柄")
.Add(myProcesses(zj).HandleCount & "进程打开的句柄数")
.Add(myProcesses(zj).Id & "进程的唯一标志符")
.Add(myProcesses(zj).MachineName & "进程正在其上运行的计算机的名称")
.Add(myProcesses(zj).MainModule.ToString & "进程的主模块")
.Add(myProcesses(zj).MainWindowHandle.ToString & "进程主窗口的句柄")
'.Add(myProcesses(zj).Modules & "")
.Add(myProcesses(zj).NonpagedSystemMemorySize &
"分配给此进程的未分页的系统内存大小")
.Add(myProcesses(zj).PagedMemorySize & "分页的内存大小")
.Add(myProcesses(zj).PagedSystemMemorySize & "分页的系统内存大小")
.Add(myProcesses(zj).PeakPagedMemorySize & "峰值分页内存大小")
.Add(myProcesses(zj).PeakVirtualMemorySize & "峰值虚拟内存大小")
.Add(myProcesses(zj).PrivateMemorySize & "专用内存大小")
.Add(myProcesses(zj).StartTime & "进程启动的时间")
.Add(myProcesses(zj).TotalProcessorTime.Seconds & "进程的总的处理器时间")
.Add(myProcesses(zj).UserProcessorTime.Seconds & "进程的用户处理器时间")
.Add(myProcesses(zj).VirtualMemorySize & "进程的虚拟内存大小")
End With
ListBox3.Items.Clear()
'((((((((((((TabPage的标签上显示相应的内容
TabPage1.Text = "进程" & ListBox1.Items.Item(zj) & "的基本信息"
TabPage2.Text = "进程" & ListBox1.Items.Item(zj) & "相关的线程信息"
TabPage3.Text = "进程" & ListBox1.Items.Item(zj) & "相关的模块信息"
')))))))))))))))))))))))))
'/////////////////////////////////////////////
f = myProcesses(zj).Threads.Count'获得相关进程共有多少个线程
Label4.Text = "进程" & ListBox1.Items.Item(zj) & "共有" & f &
"个相关的线程,线程ID信息如下:"
Dim int, pk, m, n
For n = 0 To f - 1
ListBox3.Items.Add(myProcesses(zj).Threads(n).Id)'获得线程ID
Next
'///////////////////////////////////////
ListBox5.Items.Clear()
Dim zha, kl
zha = myProcesses(zj).Modules.Count'获得有多少个与此进程相关的模块在运行,即有多少个exe和dll文件在运行
Label5.Text = "与进程" & ListBox1.Items.Item(zj) & "共有" & zha &
"个相关的模块,模块位置信息如下:"
For kl = 0 To zha - 1
ListBox5.Items.Add(myProcesses(zj).Modules(kl).FileName)'获得相关的模块的文件名
Next
End Sub
程序说明:这段代码比较长但是并不很难,关键是要读者仔细看看代码中的注释就很容易明白。至于代码中With段中的内容不一定全部都要,这里主要是为了大家理解.Net中与进程相关的一些编程而列举出来的。
显示进程
另外这段代码是这个程序的主要代码,在此代码中我们将与进程相关的线程显示在ListBox3中,相关的模块显示在ListBox5中。
双击ListBox3控件在DoubleClick事件添加如下代码:
Private Sub ListBox3_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox3.DoubleClick
ListBox4.Items.Clear()
Dim f, n
f = myProcesses(zj).Threads.Count'获得相关进程的的线程总数
n = ListBox3.SelectedIndex'在双击ListBox3中的线程ID时将此线程在ListBox3中的编号传递给n这个变量进行保存
Label6.Text = "线程" & ListBox3.Items.Item(n) & "相关信息"
With ListBox4.Items'获得此线程的详细信息
.Add(myProcesses(zj).Threads(n).BasePriority)
.Add(myProcesses(zj).Threads(n).CurrentPriority)
.Add(myProcesses(zj).Threads(n).PriorityLevel)
.Add(myProcesses(zj).Threads(n).PrivilegedProcessorTime)
.Add(myProcesses(zj).Threads(n).StartTime)
.Add(myProcesses(zj).Threads(n).ThreadState.ToString)
.Add(myProcesses(zj).Threads(n).TotalProcessorTime.Seconds)
.Add(myProcesses(zj).Threads(n).UserProcessorTime.Seconds)
.Add(myProcesses(zj).Threads(n).WaitReason.ToString)
End With
End Sub
程序说明:通过从ListBox3中获得相关进程的线程ID在ListBox3中的编号,并将它传递Threads从而获得了与它相关的线程信息。
获得进程
双击ListBox5控件在DoubleClick事件添加如下代码:
Private Sub ListBox5_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox5.DoubleClick
ListBox6.Items.Clear()
Dim f, n, m
f = myProcesses(zj).Modules.Count'获得与此进程相关的模块总数
n = ListBox5.SelectedIndex
Label7.Text = "模块" & ListBox5.Items.Item(n) & "相关信息"
With ListBox6.Items'获得与此进程相关的模块信息
m = Hex(myProcesses(zj).Modules(n).BaseAddress.ToInt32)'转换成十六进制
.Add(m)
m = Hex(myProcesses(zj).Modules(n).EntryPointAddress.ToInt32)
.Add(m)
.Add(myProcesses(zj).Modules(n).FileVersionInfo)
.Add(myProcesses(zj).Modules(n).ModuleMemorySize)
.Add(myProcesses(zj).Modules(n).ModuleName)
End With
End Sub
End Class
程序说明:通过从ListBox5中获得相关进程的模块在ListBox5中的编号,并将它传递给Modules从而获得了与它相关的模块信息。
总结
本文通过编写一个进程查看器,对.Net中的Process类进行了讲解,而且还对与之相关的ProcessModule类和ProcessThread类进行了讲解,但是这里要注意一点的是在本文中我们并没有直接使用这两个类而是使用Thread和Modules属性返回这两个类来完成的。其实这两个类如果离开Process类是无法使用的,所以以后要使用这两个类一定要记住与Process类一起使用。