15.2 进程的启动与终止
在了解了有关进程和线程的许多知识之后,就可以进入开发实践了。本节介绍在.NET应用程序中创建和终止进程的基本方法。
15.2.1 进程启动
Process类
.NET应用程序控制进程的核心是Process类,它所处的继承层次如图15-10所示。
如图15-10所示,Process类继承自Component类,所以,通常又称其为“Process组件”。Process组件代表一个托管进程,底层封装的是操作系统的本地进程。
另一个重要的类是ProcessStartInfo类,顾名思义,这个类封装了进程启动时的各种控制参数。我们马上就会在下面的例子中看到这个类的作用。
提示
继承自Component的类称为“组件”,类似地,继承自“Container”的类称为“容器”,组件放在容器中,容器通过一个实现了ISite接口的类管理组件之间以及组件和容器之间的通信关系。这个实现了ISite接口的类被称为组件的“站点”。
请读者自行在Visual Studio文档中了解详情。
图15-10 Process组件的继承树
使用Process.Start方法启动进程
Process类的Start静态方法用于启动一个进程,例如以下代码将会运行一个IE浏览器的实例:
Process.Start("IExplore.exe");
Start方法有多个重载的版本,以下这个版本可能是比较常用的,它可以向进程提供一个启动参数:
Process.Start("IExplore.exe","www.baidu.com");
提示
如果要启动的EXE文件路径不在Windows的环境变量中,则必须指明其绝对路径。
读者一定很熟悉这样的操作:在资源管理器中直接双击一个后缀名为“.docx”的文件,Windows会自动启动Word程序来编辑这个文件。“.docx”文件与Word应用程序之间的这种关系称为“文件关联”。可以在资源管理器中重新定义这种关联关系,其方法是:
在资源管理器中点击选中此文件,右击,从弹出菜单中选“打开方式”→“选择默认程序”命令(见图15-11)。
如图15-11所示,从列表中选择一个程序,选中“始终使用选择的程序打开这种文件”复选框,单击“确定”,就建立好了文件关联。以后在资源管理器中双击此类文件时,打开的程序就是用户所选择的程序。
这种通过双击“.docx”文件启动Word应用程序的方法称为“使用操作系统外壳程序启动相应进程打开特定类型的文件”。
默认情况下,Process组件的Start方法支持使用操作系统外壳程序启动进程:
Process.Start("c:\\面向对象编程漫谈目录.docx");
以上代码将自动使用Word打开并编辑C盘根目录下的“面向对象编程漫谈目录.docx”文档。
图15-11 修改文件关联
向要启动的进程传送信息
在某些情况下,我们可能希望向进程传送一些控制信息,比如希望此进程启动时窗体自动最小化,可以通过向进程传送一个ProcessStartInfo控制信息对象完成此功能,示例代码如下:
ProcessStartInfo startInfo=new ProcessStartInfo("IExplore.exe");startInfo.WindowStyle=ProcessWindowStyle.Minimized;//启动后最小化
startInfo.Arguments="www.sina.com.cn";//自动访问新浪网
Process.Start(startInfo);//启动进程
事实上,使用ProcessStartInfo对象还可以干更多的事,请看示例程序ProcessInfo中的启动进程窗体(见图15-12)。
图15-12 启动新进程
如图15-12所示,选择一个“.docx”文档之后,可以让启动的Word进程自动最大化窗体,并且通过指定一个“谓词(Verb)”,让Word自动打印此文件。
每个应用程序都可以添加一到多个Verb,用于指定要执行的功能,可以通过ProcessStartInfo对象的Verbs属性知道某程序拥有哪些Verb:
ProcessStartInfo si=new ProcessStartInfo("应用程序名或关联的文档名");
foreach(string verb in si.Verbs)//可以获取此应用程序所支持的所有谓词
{...}
知道了进程支持的Verb之后,便可以使用此Verb要求进程执行特定的功能。示例程序使用以下代码通知Word打印指定的文档:
ProcessStartInfo startInfo=new ProcessStartInfo("Word文档名");
startInfo.Verb="Print";
Process.Start(startInfo);
15.2.2 中止一个进程
可以使用两种方法中止一个进程,调用相应Process组件的CloseMainWindow方法和Kill方法。
请求关闭进程
对于拥有可视化用户界面的Windows应用程序,其主线程创建的窗体称为主窗体。在主线程所属的进程对象上调用CloseMainWindow方法,将会请求关闭主窗体并结束进程。
通过调用CloseMainWindow方法发出的结束进程运行的请求不会强制应用程序立即退出,它相当于用户直接点击主窗口上的“关闭”按钮。应用程序可以在退出前请求用户确认,也可以拒绝退出。
在ProcessInfo示例程序中,CloseProcess函数完成关闭一个进程的工作:
private void CloseProcess()
{
Process curProc=……;//获取要关闭进程所对应的Process对象的引用
bool ret=curProc.CloseMainWindow();//关闭主窗体
curProc.Close();//释放进程所占用的资源
if(ret)//如果关闭请求成功发送到指定的进程
//……(后继代码略)
}
CloseMainWindow方法是非阻塞调用,这就是说,向指定进程发出一个关闭请求之后,并不等待这一进程真正结束就马上执行下一条语句。
当成功地向指定进程发送了“请求关闭”消息之后,CloseMainWindow方法返回true。如果指定进程没有主窗体,或者不能响应此消息(比如指定的进程可能打开了一个模式对话框,在这种情况下,只有等用户点击相应按钮关闭此对话框后指定的进程才能继续运行),CloseMainWindow方法返回false。
强制关闭进程
可以使用Process类的Kill方法强制关闭一个进程:
private void KillProcess()
{
Process curProc=……;//获取要关闭进程所对应的Process对象的引用
curProc.Kill();
//……
}
与CloseMainWindow方法不同,Kill方法实际上是请求操作系统直接结束进程,它不给要关闭的进程保存数据的机会,因此除非要结束的进程没有任何数据需要保存,否则不要采用Kill方法直接结束某个进程。