前言
Process类在System.Diagnostics命名空间中,用于启动和管理系统进程。
主要方法和属性如下:
- Start() - 启动进程
- Kill() - 终止进程
- Close() - 仅仅是强制关闭了进程的标准流,但并没有停止进程的运行。
- ExitCode - 获取进程退出代码
- StartInfo - 设置启动进程的相关属性,如文件名、参数、工作目录等
- StandardInput - 进程的标准输入流
- StandardOutput - 进程的标准输出流
- StandardError - 进程的标准错误流
示例代码:
1 | Process process = new Process(); |
此代码启动cmd.exe,执行dir命令,并获取输出,输出目录列表信息。
StartInfo的主要属性:
- FileName - 可执行文件的文件名
- Arguments - 传递给可执行文件的命令行参数
- WorkingDirectory - 进程工作目录
- CreateNoWindow - 无窗口启动进程等等。使用Process类可以很方便的启动和管理系统进程。
- UseShellExecute - 是否使用操作系统外壳启动
- RedirectStandardInput / RedirectStandardOutput / RedirectStandardError - 重定向标准输入/输出/错误流
打开文件
使用系统的文件关联方式打开文件,如果没有关联的打开方式会抛出异常,要进行异常捕获。
1 | private void OpenFile(string filepath) |
打开文件夹 选中文件
1 | Process.Start("explorer.exe", $"/select,\"{mp4Path}\""); |
启动文件并等待安装
1 | Process.Start(microsoftEdgeWebview2Setup, " /install")?.WaitForExit(); |
打开本程序
1 | Process.Start(Application.ResourceAssembly.Location); |
应用更新
下面两种方式生效的前提是:
程序必须以管理员身份运行。
可参考 https://www.psvmc.cn/article/2020-07-31-wpf-run-admin.html 配置。
新进程中打开
注意:
程序安装升级包建议用这种方式
示例代码:
1 | try |
子进程中打开
子进程打开进行更新的时候一定要等待一下,在关闭程序,否则会导致更新程序还没打开就退出了。
1 | try |
获取错误码
如果我们需要获取进程的 ExitCode
,应该使用 Process.WaitForExit()
方法来等待进程结束。
1 | public static bool LoadDll(string dllPath) |
如果要调用Close,并且要获取 ExitCode
,怎么办呢?
要确保 WaitForExit 方法在调用 Close 方法之后能够正确工作,你可以在调用 Close 方法之前先设置 Process 对象的 EnableRaisingEvents 属性为 true,并订阅 Process 对象的 Exited 事件。然后,在事件处理程序中调用 WaitForExit 方法以等待进程退出。
1 | Process myProcess = new Process(); |
执行程序的几种方式
示例
1 | using (Process process = new Process()) |
参数说明:
CreateNoWindow
CreateNoWindow
为true
时不显示窗口。
UseShellExecute
程序中大多情况都是false
。
当
UseShellExecute
为true
时,可以使用文件关联来启动应用程序。例如,直接打开文本文件或图像文件,系统会使用默认关联的程序打开相应的文件。
如果要指定工作目录、传递命令行参数、重定向标准输入输出等。
需要将
UseShellExecute
设置为false
,这样,Process类将直接创建一个新进程来执行指定的应用程序,而不依赖操作系统的 Shell。
RedirectStandardInput
默认为false
。
重定向输入,需要在执行程序的时候进行输入的时候设置为true
。
RedirectStandardOutput
默认为false
。
重定向标准输出,需要获取标准输出的时候设置为true
。
RedirectStandardError
默认为false
。
重定向标准错误,需要获取标准错误的时候设置为true
。
不重定向
1 | /// <summary> |
这里不用输出的结果,所以都不重定向。
重定向标准输出
1 | private static void AddFirewallRule() |
重定向标准错误
1 | /// <summary> |
这里重定向错误,因为时长信息在错误中。
重定向输入
1 | _recordProcess = new Process |
结束
1 | if (_recordProcess != null) |
退出方法对比
相关方法
对于Process的方法WaitForExit、Close、Kill、Dispose的作用
- WaitForExit(): 等待关联进程退出为止。
- Kill(): 结束关联进程,不会执行任何清理工作。
- Close(): 关闭与进程的连接,但不会终止关联进程。调用Close()后,Process对象不再能够访问或控制该进程。
- Dispose(): 释放与Process关联的资源。不会结束关联进程。
通常情况下,你不需要显式调用 Close() 或 Dispose() 方法。
当你调用 Process 类的 WaitForExit() 方法等待进程完成时,会自动释放进程相关的资源。
在进程完成后,相关的资源会被自动释放。
然而,如果你在代码中创建了很多进程对象,并且你希望在使用完之后尽快释放相关资源,可以考虑在适当的时机手动调用 Dispose() 方法。
例如,在一个处理大量进程的循环中,你可以在每次迭代结束后调用 Dispose() 方法来释放资源。
总而言之,大多数情况下不需要显式调用 Close() 方法,而是依靠自动资源释放机制。
如果需要手动释放资源,应该使用 Dispose() 方法。
注意
WaitForExit
及Kill
都能使进程关闭,关闭后要调用Dispose
释放资源。
Close()
和Dispose()
并不能关闭关联的进程。
WaitForExit
后不用调用Close
。
常用的方式
正常退出并释放资源
1 | process?.WaitForExit(); |
等待退出并释放资源
注意
使用
WaitForExit
的时候建议添加超时时间,返回值为超时的时候进程是否退出了,如果没有退出我们就要杀掉进程。设置超时时间后,一定要根据返回值处理进程,否则可能导致进程不退出的情况!
设置超时时间后,一定要根据返回值处理进程,否则可能导致进程不退出的情况!
设置超时时间后,一定要根据返回值处理进程,否则可能导致进程不退出的情况!
示例
1 | bool exited = process.WaitForExit(5000); |
强制杀进程并释放资源
1 | process?.Kill(); |
结束关联并释放资源
这种方式并不能结束关联进程
1 | process?.Close(); |
注意
在调用
Close()
或Kill()
之后,强烈建议对关联的Process
对象调用Dispose()
方法,以释放相关资源。
也可以使用using
自动Dispose()
1 | using (Process process = new Process()) |
Close和Dispose
Close()
和Dispose()
方法都可用于关闭进程。
Close()
方法是Process
类的一个实例方法,用于关闭关联的进程和释放与之关联的资源,包括释放由进程打开的内部句柄和操作系统资源。
调用Close()
方法后,进程将被关闭,并且不再可用。
Dispose()
方法是Process
类的一个公开实现的IDisposable
接口方法,用于释放进程及其关联资源。调用Dispose()
方法将会关闭关联的进程,并释放与之关联的资源,包括通过进程打开的任何文件、管道或其他资源。使用Dispose()
方法可以确保资源被立即释放,而不等待垃圾回收器的回收。
区别在于,
Close()
方法主要用于关闭进程,释放资源的工作将由垃圾回收器完成。
而Dispose()
方法会立即关闭进程,并手动释放与之关联的资源。