开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1531|回复: 2
收起左侧

[图文教程] 如何“干净地”终止Win32中的应用程序

[复制链接]
结帖率:50% (2/4)
发表于 2012-7-2 15:16:32 | 显示全部楼层 |阅读模式   湖南省长沙市
在理想环境中,某一进程可能会通过某种形式的进程间通信要求另一进程关闭。不过,如果你对希望其关闭的应用程序没有源代码级控制权,可能就没有办法做这样的选择。尽管没有哪种方法能保证“干净地”关闭 Win32 中的应用程序,但你可以采取一些步骤来确保应用程序使用最佳方法清除资源。
32 位进程(和 Windows 95 下的 16 位进程)
在 Win32 下,操作系统可保证在进程关闭时清除进程所拥有的资源。但是,这并不意味着进程本身将有机会对磁盘执行任何最后的信息刷新或通过远程连接执行任何最后的通信,也不意味着进程的 DLL 将有机会执行其 PROCESS_DETACH 代码。这就是通常最好避免在 Windows 95 和 Windows NT 下终止应用程序的原因。
如果你必须关闭进程,请按照下列步骤操作:
向你打算关闭的进程所拥有的所有顶级窗口发送一条 WM_CLOSE 消息。许多 Windows 应用程序会通过关闭它自身来响应此消息。
注意:控制台应用程序对 WM_CLOSE 的响应取决于它是否安装了控制处理程序。
使用 EnumWindows() 找到目标窗口的句柄。在回调函数中,检查该窗口的进程 ID 是否与要关闭的进程相匹配。你可以通过调用 GetWindowThreadProcessId() 来执行此操作。确定匹配项后,使用 PostMessage() 或 SendMessageTimeout() 向该窗口发送 WM_CLOSE 消息。
使用 WaitForSingleObject() 等待进程的句柄。确保你使用超时值等待,因为在很多情况下 WM_CLOSE 不会关闭应用程序。记住,应使超时值足够长(通过 WaitForSingleObject() 或 SendMessageTimeout()),以便用户可以响应为了 处理 WM_CLOSE 消息而创建的任何对话框。
如果返回值为 WAIT_OBJECT_0,则应用程序已干净地将其自身关闭。如果返回值为 WAIT_TIMEOUT,则必须使用 TerminateProcess() 关闭应用程序。
注意:如果从 WaitForSingleObject() 得到的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,则应使用 GetLastError() 找出原因。 通过执行上述这些步骤,你便完全有可能干净地关闭应用程序(无需 IPC 或用户干预)。
16 位问题(在 Windows NT 下)
上述步骤适用于 Windows 95 下的 16 位应用程序,而 Windows NT 下的 16 位应用程序与 Windows 95 下的 16 位应用程序的工作方式差别非常大。
在 Windows NT 下,所有 16 位应用程序都在虚拟 DOS 机 (VDM) 中运行。此 VDM 是作为 Windows NT 下的一个 Win32 进程 (NTVDM) 运行的。NTVDM 进程具有进程 ID。你可以通过 OpenProcess() 获取该进程的句柄,就像处理其它任何 Win32 进程一样。不过,在 VDM 中运行的 16 位应用程序都没有进程 ID,因此你无法从 OpenProcess() 获取进程句柄。VDM 中的每个 16 位应用程序都有一个 16 位任务句柄和一个 32 位执行线程。可通过调用函数 VDMEnumTaskWOWEx() 找到该任务句柄和线程 ID。有关这方面的其它信息,请参见:“如何用 Win32 APIs 枚举应用程序窗口和进程”。
关闭 Windows NT 下的 16 位应用程序的首选和最直接的方法是关闭整个 NTVDM 进程。你可以通过执行前面所描述的步骤来完成此操作。你只需知道 NTVDM 的进程 ID 即可,参考“如何用 Win32 APIs 枚举应用程序窗口和进程”所讲的方法来查找 NTVDM 的进程 ID。此方法的缺点是它会关闭在该 VDM 中运行的所有 16 位应用程序。如果这不是你想要的结果,则需要采取其它方法。
如果你希望关闭 NTVDM 进程中的单个 16 位应用程序,需要按照下列步骤操作:
向该进程所拥有的以及与你要关闭的 16 位任务具有相同线程 ID 的所有顶级窗口发送一条 WM_CLOSE 消息。执行此操作最有效的方法是使用 EnumWindows()。在回调函数中,检查窗口的进程 ID 和线程 ID 是否与要关闭的 16 位任务相匹配。请记住,该进程 ID 将成为在其中运行 16 位应用程序的 NTVDM 的进程 ID。
尽管你有线程 ID,但无法等待 16 位进程的终止。因此,你必须等待任意时间长度(以允许干净关闭),然后尝试关闭应用程序。如果应用程序已关闭,则此操作无效。如果应用程序尚未关闭,则它将终止应用程序。
使用称为 VDMTerminateTaskWOW() 的函数终止应用程序,该函数可在 Vdmdbg.dll 中找到。它采用 VDM 的进程 ID 和 16 位任务的任务编号。
此方法允许你关闭 Windows NT 下 VDM 中的单个 16 位应用程序。不过,16 位 Windows 以及 VDM 中运行的 WOWExec 都不能有效地清除已终止任务的资源。如果你要寻找最有可能干净地终止 Windows NT 下的 16 位应用程序的方法,应考虑终止整个 VDM 进程。注意:如果你要启动以后可能会终止的 16 位应用程序,请将 CREATE_SEPARATE_WOW_VDM 与 CreateProcess() 结合使用

结帖率:61% (35/57)
发表于 2012-7-5 13:32:52 | 显示全部楼层   海南省海口市
这样的文章都没有人看,很可惜。。。

我来占头领。哈哈
回复 支持 反对

使用道具 举报

结帖率:50% (2/4)
 楼主| 发表于 2012-7-5 13:34:26 | 显示全部楼层   湖南省长沙市
{:3_231:}{:3_231:}欢迎~!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表