窗口“捕获”应用程序在意外终止时允许捕获的窗口消失,我该如何预防/解决此问题?
Posted
技术标签:
【中文标题】窗口“捕获”应用程序在意外终止时允许捕获的窗口消失,我该如何预防/解决此问题?【英文标题】:Window "capture" application, upon unexpected termination, allows captured windows to disappear, how can I prevent/fix this issue? 【发布时间】:2019-02-17 10:53:08 【问题描述】:我有一个应用程序 (C# + WPF),它试图控制作为输入传递给它的任何进程的图形界面的控制权,并为我自己的目的调整大小/重新定位。
我认为它的工作做得相当好。在预期终止时(基类继承自 IDisposable),“捕获”进程被释放——它的父进程被设置为原始进程,它的窗口样式被重置,等等。
事实上,在测试中,我可以捕获、释放、重新捕获等等,与我想要的许多次相同的过程,没有任何问题。
但是,在意外终止时(比如另一个进程强行杀死它),该进程永远不会恢复其图形界面!我可以说它仍在运行,但我永远无法将该进程设置回其原始状态。
似乎该进程不再响应设置特定窗口功能的基于窗口的 Win32 API 调用(例如,我可以使用 GetParent、GetWindowThreadProcessId 等获取信息,但调用 ShowWindow 或相关结果没有任何结果)。
关于为什么会发生这种情况的任何建议?我猜是因为我将进程的父进程设置为我的 WPF 应用程序(然后意外关闭)它会导致尝试恢复初始界面时出现一些问题?
This 是它发生的原因(或者,至少说明了为什么我自己很难找到问题所在);我可以从中恢复吗?如果有,怎么做?
编辑 -
IInspectable 在 cmets 中提出了一个很好的观点,对问题进行了调整以使这个特定应用程序更有意义。
【问题讨论】:
这个问题(或其道德等价物)不断出现。您尝试做的不是受支持的方案。请阅读Is it legal to have a cross-process parent/child or owner/owned window relationship? 这是一个很好的观点,并且直指我的问题的根源。很棒的发现。我想我的问题不应该是如何“预防它”,而是我可以从它中恢复而不杀死进程以及如何? 确实没有什么可恢复的,因为您已经处于不受支持的领域,当您使用不同线程拥有的窗口句柄调用SetParent
时。这没有在文档中明确指出,但这样做会为您调用AttachThreadInput。从那里开始,它走下坡路,例如AttachThreadInput is like taking two threads and pooling their money into a joint bank account [...].
【参考方案1】:
看来我已经得到答案了;所以,为了完整起见,我会发布我在这里得到的内容,以防其他人有类似的问题。
根据IInspectable 在here 和here 中提供的信息(在cmets 中有更多上下文),看来我在这里要做的(分配一个新的父跨进程)是本质上不受支持的行为。
我的解决方案:
恢复(至少在我所说的这一点 - 即意外崩溃或退出)可能是不可行的,因为我们已经以未确定/未知的行为结束了。所以我决定走预防路线。
我们当前的项目已经使用Nancy 框架在服务器/进程之间进行通信,因此我将为我的部分程序“改进”我们的关闭过程,使其能够更优雅地退出。
在真正意外终止的情况下,我仍然不知所措。我可以重新启动进程(在我们的例子中,实际上是带有控制台输出的服务,但是 w/e),但我的应用程序只是一个 GUI/接口,与功能相比并不是很重要这些过程服务。我可能会制作某种信号量文件来指示是否发生成功关闭并将我的代码分支,以便它表明进程在下次重新启动之前不再可见。
【讨论】:
以上是关于窗口“捕获”应用程序在意外终止时允许捕获的窗口消失,我该如何预防/解决此问题?的主要内容,如果未能解决你的问题,请参考以下文章
Tkinter Canvas Postscript 未捕获屏幕框架外的 Window 元素