自己的笔记本被自己改成了win server服务器,外加来电自启+小爱同学控制开关机,可以说很好了,但是笔记本却没有断电自动关机这个东西,原本想把电池扣了,换上usp的,但是有一点成本在的,果断放弃。 后来更改电源计划,99%的时候进行关机,但是盖上盖子,断开远程的时候,睡眠状态了就,不会进行关机操作。索性写了这个python代码 ```python import sys import win32api import win32gui import win32con import pythoncom import psutil import threading import time import subprocess SHUTDOWN_DELAY_SECONDS = 60 class PowerListenerWindow: def __init__(self): self.is_plugged_in = True # 初始假设为连接电源 self.shutdown_timer = None self.last_unplugged_time = None wc = win32gui.WNDCLASS() wc.lpfnWndProc = self.wnd_proc wc.lpszClassName = 'MyPowerListenerClass' wc.hInstance = win32api.GetModuleHandle(None) class_atom = win32gui.RegisterClass(wc) # Create a hidden window self.hwnd = win32gui.CreateWindow( class_atom, 'PowerListener', 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None ) def wnd_proc(self, hwnd, msg, wparam, lparam): if msg == win32con.WM_POWERBROADCAST: if wparam == win32con.PBT_APMPOWERSTATUSCHANGE: # print("[WM_POWERBROADCAST] 电源状态可能已更改 (PBT_APMPOWERSTATUSCHANGE)") # 简化日志 self.check_and_print_status() # 调用更新后的检查函数 elif wparam == win32con.PBT_ACPIRESUMEAUTOMATIC or wparam == win32con.PBT_ACPIRESUMESUSPEND: # print(f"[WM_POWERBROADCAST] 系统从睡眠/休眠恢复 (wParam={wparam})") # 简化日志 pass # 可根据需要添加恢复逻辑 elif wparam == win32con.PBT_APMSUSPEND: # print("[WM_POWERBROADCAST] 系统即将进入睡眠/休眠 (PBT_APMSUSPEND)") # 简化日志 pass # 可根据需要添加休眠前逻辑 return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) def cancel_pending_shutdown(self): """取消任何待定的关机操作""" if self.shutdown_timer and self.shutdown_timer.is_alive(): self.shutdown_timer.cancel() self.shutdown_timer = None def schedule_shutdown(self): """在指定延迟后执行关机""" print(f"警告:设备未充电,将在 {SHUTDOWN_DELAY_SECONDS} 秒后关机!") self.execute_shutdown() def execute_shutdown(self): """实际执行关机操作""" # 再次确认是否仍然未充电,避免在检查间隙插上了电源 try: battery_check = psutil.sensors_battery() if battery_check and not battery_check.power_plugged: print("--- 执行关机 ---") # 使用 subprocess 调用 Windows 关机命令 # /s 关机, /t 5 延迟5秒, /c 添加消息 subprocess.run(["shutdown", "/s", "/t", "5", "/c", "Battery low and not charging. Shutting down in 5 seconds..."], check=True) # 等待一下,让关机命令生效 time.sleep(10) sys.exit(0) # 正常退出监听器 else: print("--- 电源状态已恢复,取消关机 ---") except psutil.Error as e: print(f"查询电源状态失败: {e}") # 查询失败,出于安全考虑,可以选择不关机或记录日志 except subprocess.CalledProcessError as e: print(f"执行关机命令失败: {e}") except Exception as e: print(f"执行关机时发生未知错误: {e}") def check_and_print_status(self): """Helper function to query and print current status and manage shutdown timer""" try: battery = psutil.sensors_battery() was_plugged_in = self.is_plugged_in # 记录之前的状态 if battery: self.is_plugged_in = battery.power_plugged # 简化状态打印,仅在状态变化时提示 # plugged_status_str = "已充电/接入电源" if self.is_plugged_in else "未在充电" # print(f"当前电源状态: {plugged_status_str}, 电量: {battery.percent}%") if not self.is_plugged_in: # 检测到未充电 if was_plugged_in or self.shutdown_timer is None: # 如果之前是充电的,或者是第一次检测到未充电且无定时器 print(f"提示:笔记本电脑当前未在充电! 电量: {battery.percent}%. 将在 {SHUTDOWN_DELAY_SECONDS} 秒后关机.") self.cancel_pending_shutdown() # 先取消旧的(理论上不应该有) # 启动新的 60 秒关机定时器 self.shutdown_timer = threading.Timer(SHUTDOWN_DELAY_SECONDS, self.schedule_shutdown) self.shutdown_timer.start() # else: 已经在倒计时中,无需重复启动 else: # 检测到已充电 if not was_plugged_in: # 如果之前是未充电的 print("提示:电源已连接,取消关机计划。") # 取消任何待定的关机 self.cancel_pending_shutdown() else: # print("无法获取电池信息,可能不是笔记本电脑或传感器不可用。") # 简化日志 self.is_plugged_in = True # 默认为连接(安全起见) self.cancel_pending_shutdown() # 取消关机 except Exception as e: print(f"查询电源状态时出错: {e}") # 出错时也应取消关机以防万一 self.cancel_pending_shutdown() def start_message_loop(self): print("Windows 电源监听器已启动...") print("请插拔电源测试功能。按 Ctrl+C 退出。") # 初始检查一次状态 self.check_and_print_status() try: while True: pythoncom.PumpWaitingMessages() win32api.Sleep(5000) # 每5秒处理一次消息队列 except KeyboardInterrupt: print("\n收到退出指令,正在关闭...") finally: self.cancel_pending_shutdown() # 确保退出时取消定时器 win32gui.DestroyWindow(self.hwnd) print("监听器已关闭。") # 编译 # pyinstaller --noconfirm --onefile --hidden-import=win32timezone powerOffShutDown.py if __name__ == "__main__": listener = PowerListenerWindow() listener.start_message_loop() ``` Loading... 自己的笔记本被自己改成了win server服务器,外加来电自启+小爱同学控制开关机,可以说很好了,但是笔记本却没有断电自动关机这个东西,原本想把电池扣了,换上usp的,但是有一点成本在的,果断放弃。 后来更改电源计划,99%的时候进行关机,但是盖上盖子,断开远程的时候,睡眠状态了就,不会进行关机操作。索性写了这个python代码 ```python import sys import win32api import win32gui import win32con import pythoncom import psutil import threading import time import subprocess SHUTDOWN_DELAY_SECONDS = 60 class PowerListenerWindow: def __init__(self): self.is_plugged_in = True # 初始假设为连接电源 self.shutdown_timer = None self.last_unplugged_time = None wc = win32gui.WNDCLASS() wc.lpfnWndProc = self.wnd_proc wc.lpszClassName = 'MyPowerListenerClass' wc.hInstance = win32api.GetModuleHandle(None) class_atom = win32gui.RegisterClass(wc) # Create a hidden window self.hwnd = win32gui.CreateWindow( class_atom, 'PowerListener', 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None ) def wnd_proc(self, hwnd, msg, wparam, lparam): if msg == win32con.WM_POWERBROADCAST: if wparam == win32con.PBT_APMPOWERSTATUSCHANGE: # print("[WM_POWERBROADCAST] 电源状态可能已更改 (PBT_APMPOWERSTATUSCHANGE)") # 简化日志 self.check_and_print_status() # 调用更新后的检查函数 elif wparam == win32con.PBT_ACPIRESUMEAUTOMATIC or wparam == win32con.PBT_ACPIRESUMESUSPEND: # print(f"[WM_POWERBROADCAST] 系统从睡眠/休眠恢复 (wParam={wparam})") # 简化日志 pass # 可根据需要添加恢复逻辑 elif wparam == win32con.PBT_APMSUSPEND: # print("[WM_POWERBROADCAST] 系统即将进入睡眠/休眠 (PBT_APMSUSPEND)") # 简化日志 pass # 可根据需要添加休眠前逻辑 return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) def cancel_pending_shutdown(self): """取消任何待定的关机操作""" if self.shutdown_timer and self.shutdown_timer.is_alive(): self.shutdown_timer.cancel() self.shutdown_timer = None def schedule_shutdown(self): """在指定延迟后执行关机""" print(f"警告:设备未充电,将在 {SHUTDOWN_DELAY_SECONDS} 秒后关机!") self.execute_shutdown() def execute_shutdown(self): """实际执行关机操作""" # 再次确认是否仍然未充电,避免在检查间隙插上了电源 try: battery_check = psutil.sensors_battery() if battery_check and not battery_check.power_plugged: print("--- 执行关机 ---") # 使用 subprocess 调用 Windows 关机命令 # /s 关机, /t 5 延迟5秒, /c 添加消息 subprocess.run(["shutdown", "/s", "/t", "5", "/c", "Battery low and not charging. Shutting down in 5 seconds..."], check=True) # 等待一下,让关机命令生效 time.sleep(10) sys.exit(0) # 正常退出监听器 else: print("--- 电源状态已恢复,取消关机 ---") except psutil.Error as e: print(f"查询电源状态失败: {e}") # 查询失败,出于安全考虑,可以选择不关机或记录日志 except subprocess.CalledProcessError as e: print(f"执行关机命令失败: {e}") except Exception as e: print(f"执行关机时发生未知错误: {e}") def check_and_print_status(self): """Helper function to query and print current status and manage shutdown timer""" try: battery = psutil.sensors_battery() was_plugged_in = self.is_plugged_in # 记录之前的状态 if battery: self.is_plugged_in = battery.power_plugged # 简化状态打印,仅在状态变化时提示 # plugged_status_str = "已充电/接入电源" if self.is_plugged_in else "未在充电" # print(f"当前电源状态: {plugged_status_str}, 电量: {battery.percent}%") if not self.is_plugged_in: # 检测到未充电 if was_plugged_in or self.shutdown_timer is None: # 如果之前是充电的,或者是第一次检测到未充电且无定时器 print(f"提示:笔记本电脑当前未在充电! 电量: {battery.percent}%. 将在 {SHUTDOWN_DELAY_SECONDS} 秒后关机.") self.cancel_pending_shutdown() # 先取消旧的(理论上不应该有) # 启动新的 60 秒关机定时器 self.shutdown_timer = threading.Timer(SHUTDOWN_DELAY_SECONDS, self.schedule_shutdown) self.shutdown_timer.start() # else: 已经在倒计时中,无需重复启动 else: # 检测到已充电 if not was_plugged_in: # 如果之前是未充电的 print("提示:电源已连接,取消关机计划。") # 取消任何待定的关机 self.cancel_pending_shutdown() else: # print("无法获取电池信息,可能不是笔记本电脑或传感器不可用。") # 简化日志 self.is_plugged_in = True # 默认为连接(安全起见) self.cancel_pending_shutdown() # 取消关机 except Exception as e: print(f"查询电源状态时出错: {e}") # 出错时也应取消关机以防万一 self.cancel_pending_shutdown() def start_message_loop(self): print("Windows 电源监听器已启动...") print("请插拔电源测试功能。按 Ctrl+C 退出。") # 初始检查一次状态 self.check_and_print_status() try: while True: pythoncom.PumpWaitingMessages() win32api.Sleep(5000) # 每5秒处理一次消息队列 except KeyboardInterrupt: print("\n收到退出指令,正在关闭...") finally: self.cancel_pending_shutdown() # 确保退出时取消定时器 win32gui.DestroyWindow(self.hwnd) print("监听器已关闭。") # 编译 # pyinstaller --noconfirm --onefile --hidden-import=win32timezone powerOffShutDown.py if __name__ == "__main__": listener = PowerListenerWindow() listener.start_message_loop() ``` 最后修改:2025 年 12 月 16 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏