【问题标题】:A kinder way than TerminateProcess?比 TerminateProcess 更友好的方式?
【发布时间】:2011-09-17 13:16:02
【问题描述】:

我有一个备份应用程序,它会在备份之前关闭用户定义的正在运行的程序,以便在备份之前关闭和刷新打开的数据文件。备份完成后,它会重新启动列表中的程序。

使用 Caption 和 PostMessage(AppHandle,WM_CLOSE,0,0); 获取窗口句柄没有问题这适用于大多数应用程序,但不适用于在通知区域(系统托盘)中运行的应用程序

目前我正在使用 TerminateProcess( 它适用于那些通知区域应用程序,但它会使文件保持打开状态,因为 Windows 会绕过任何关闭指令并直接关闭这些应用程序。

我已经搜索了很长时间,但找不到更好的方法来关闭通知区域应用程序。有人可以帮忙吗?

谢谢

【问题讨论】:

  • TerminateProcess 不会让文件保持打开状态。当拥有进程关闭时,所有打开的句柄都将关闭。此外,如果你想备份打开的文件,操作系统已经为此提供了一个 API:Shadow Copy。
  • @Rob:尝试备份打开的文件可能会导致您在文件处于不一致状态时拍摄快照。
  • @Gabe,不比意外关闭程序更糟糕......
  • @bdonlan:是的,这就是问题的重点。

标签: delphi terminate


【解决方案1】:

为了优雅地关闭程序,您需要了解该程序预期如何关闭。如果关闭主窗口就完成了,那么你需要知道如何识别“主”窗口。

程序不会在通知区域“内”运行。他们在那里显示图标。任何带有通知图标的程序也必须有一个窗口(因为外壳程序通过向窗口发送消息来告诉程序该图标已被单击)。即使窗口不可见,它仍然必须存在。如果您可以确定一组属性来标识与特定通知图标关联的窗口,那么您可以关闭它。但是,没有要查找的标准属性集;每个程序都可以做不同的事情。

即使您找到了您正在寻找的窗口,关闭它也可能不是程序预期的终止方式。它可能会期望通知图标菜单中的某个命令,或者程序显示的对话框发送的某些消息。

【讨论】:

  • +1。您不知道什么会触发程序执行其清理操作。当然,您可以向其隐藏窗口发送 WM_QUIT 或其他内容,但这可能会像使用 TerminateProcess 一样跳过所有清理
  • 我意识到这一点,但至少使用 wm_Close 比使用 TerminateProcess 将其关闭要好。温和的关闭更有可能涵盖所有需要的清理工作。如果没有,至少我的应用程序试图轻轻地关闭事物。请参阅下面的其他评论。
【解决方案2】:

如果您的应用程序在 Windows Vista 或 Windows 7 上运行,请不要关闭程序 - 而是使用 Volume Shadow Copy service 访问仍在使用的文件的快照。这就是 Windows 7 内置备份程序的作用。

如果您使用的是早期版本的 Windows,则没有万无一失的解决方案。如果程序有系统托盘图标,它也会有一个隐藏窗口,您可以尝试发送WM_QUERYENDSESSIONWM_ENDSESSION 给它。但是,不能保证程序会关闭,如果它确实关闭了,由于您可能绕过了其正常关闭过程的一部分,它可能无法完成其正常清理。也可能有一些程序在运行时根本没有关联的窗口。最好的方法可能是简单地注销用户,并从服务进程执行备份。当然,您仍然会遇到与其他服务打开的文件共享的问题...

【讨论】:

  • 谢谢大家,但首先提醒我注意问题的是 Shadow Copy。使用影子复制,任何在运行时解密文件以供独占使用,然后在关闭时加密的程序都以“清除”状态复制。我所有的密码都被复制并备份在 Clear!! {gasp} 这就是为什么我想友好地关闭并让应用程序完成其 Terminate 不会执行的关闭过程。
  • 那些程序就坏了;这里的所有都是它的。您可以尝试跳过临时目录,但如果密码程序正在解密其密码数据库并将其留在磁盘上,它已经使加密无用(攻击者可以扫描磁盘以查找已删除的文件!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
相关资源
最近更新 更多