Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请教两个问题 #10

Open
litaying opened this issue May 11, 2023 · 4 comments
Open

请教两个问题 #10

litaying opened this issue May 11, 2023 · 4 comments

Comments

@litaying
Copy link

1、多个进程是有一个结束就暂停还是都结束后才会暂停?
2、电脑正常关机会自动暂停吗?Windows的进程关闭好像是无序的,怎么确保自动暂停程序一定在游戏之后关闭并且有足够的时间去检测和发送暂停请求?

@litaying
Copy link
Author

如果是无法控制的,比如说程序即使可以阻止关机,网络也可能在此之前被关闭,那么能不能把程序部署在云服务器或者Nas上不断通过ip检测电脑是否在线来暂停?

@6yy66yy
Copy link
Owner

6yy66yy commented May 11, 2023

第一个问题,之前有一个阶段是靠两个进程实现的,后来发现多线程就能完成。目前窗口(也就是托盘图标及相关菜单)是主线程,它调用检测程序。因此现在就一个进程,停了就全停。
第二个问题,我尝试过,能力有限,没找到Windows关机事件。我有一个想法就是可以模仿Word那种程序在关机前可以阻止关机,先发送暂停请求再关机,还得再学习一下。
最后一个问题,我之前在github上看到过类似的项目实现了你说的这种方式,不过我本人没有nas所以只考虑单机版了

@litaying
Copy link
Author

第一个问题,之前有一个阶段是靠两个进程实现的,后来发现多线程就能完成。目前窗口(也就是托盘图标及相关菜单)是主线程,它调用检测程序。因此现在就一个进程,停了就全停。 第二个问题,我尝试过,能力有限,没找到Windows关机事件。我有一个想法就是可以模仿Word那种程序在关机前可以阻止关机,先发送暂停请求再关机,还得再学习一下。 最后一个问题,我之前在github上看到过类似的项目实现了你说的这种方式,不过我本人没有nas所以只考虑单机版了

我觉得阻止关机发暂停是最好的,但是我没看到有类似的检测ip来暂停的,可以发一下项目地址之类的吗?

@SNWCreations
Copy link

SNWCreations commented Jun 13, 2024

第一个问题,之前有一个阶段是靠两个进程实现的,后来发现多线程就能完成。目前窗口(也就是托盘图标及相关菜单)是主线程,它调用检测程序。因此现在就一个进程,停了就全停。 第二个问题,我尝试过,能力有限,没找到Windows关机事件。我有一个想法就是可以模仿Word那种程序在关机前可以阻止关机,先发送暂停请求再关机,还得再学习一下。 最后一个问题,我之前在github上看到过类似的项目实现了你说的这种方式,不过我本人没有nas所以只考虑单机版了

首先感谢作者做的这个软件,很好用
第二个问题我今天研究了一整天,在我参考此软件代码后自行重写的版本中实现了关机自动暂停,美中不足的是其他代理软件会导致关机时暂停请求卡住 (说的就是你,Clash!)
大概思路是在初始化的 message_map 里添加上对 WM_QUERYENDSESSION 信号的回调方法,这个信号会在 Windows 关闭时向所有应用程序下发,我们在此时去请求暂停就可以了。
阻止关机再暂停也实现了,用了点 Win32 API 就行了。
抽象成代码大概是这样的 (以下代码复制自我的改版)
但是由于之前有开发者因为做这个被发了律师函,故我很大可能不会公开我的改版 :(
但在此再次感谢作者

  message_map = {
           win32con.WM_QUERYENDSESSION: self.__on_shutdown
  # ...
  }

class Application(object):
    # When it is called, there is no back
    @staticmethod
    def __start_force_kill(callback: Callable):
        def _force_kill_callback():
            logging.debug("Force kill thread started and waiting now")
            time.sleep(CONST_MAX_WAIT)
            callback()
            logging.debug("Force kill thread is terminating application")
            # We must use Win32 API magic there
            # Because sys.exit() does not work when Windows is shutting down
            # But why?
            # **** you Python, I had wasted an hour on this
            ctypes.windll.kernel32.ExitProcess(1)
        threading.Thread(target=_force_kill_callback).start()

def __on_shutdown(self, hwnd, msg, wparam, lparam):
        logging.debug("Windows is shutting down, running pause request")
        ctypes.windll.user32.ShutdownBlockReasonCreate(self.__hwnd, f"正在暂停加速器时长 ({CONST_MAX_WAIT} 秒内无响应为异常,此时请手动暂停)")
        logging.debug("Shutdown block reason created")

        # to prevent infinity blocking, use a callback to destroy block reason
        def _force_kill():
            logging.error("We cannot pause correctly, force stopping! :(")
            ctypes.windll.user32.ShutdownBlockReasonDestroy(self.__hwnd)
            logging.debug("Shutdown block reason destroyed by force kill thread")

        Application.__start_force_kill(_force_kill)

        res: str
        try:
            res = self.__user.pause()
        except InterruptedError or KeyboardInterrupt: # any interrupt to fail
            logging.error("Pause request interrupted")
            pass
        else:
            logging.debug(f"Pause requested, response: {res}")
            logging.debug("Windows can shut down now")
            ctypes.windll.user32.ShutdownBlockReasonDestroy(self.__hwnd)
            logging.debug("Shutdown block reason destroyed")
        return 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants