吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2453|回复: 71
收起左侧

[Python 原创] 监控网速定时关机工具

  [复制链接]
Timothys 发表于 2025-3-26 11:42
最近需要挂机下载东西,就需要一个下载完后关机的软件,然后在AI的帮助下写了一个
主要功能:
1、监控模式:监控网卡,设置网速大小,当网速小于设置的监控值时开始倒计时关机
2、普通模式:设置定时关机
界面如下:
关机2.png 关机1.png
exe打包文件链接:
下载:https://s2022.lanzoum.com/i5gEr2rnovpi 密码:3m8t


[Python] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
import tkinter as tk
from tkinter import ttk, messagebox
import psutil
import time
import os
import threading
import json
from datetime import datetime, timedelta
import ctypes
from threading import Lock
import sys
 
def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except Exception:
        return False
 
if not is_admin():
    # 以管理员权限重新运行程序
    ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, " ".join(sys.argv), None, 1)
    sys.exit()
 
CONFIG_FILE = "config.json"
 
class ShutdownManagerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("关机助手")
        self.root.geometry("900x800")
        self.lock = Lock()
        self.config = self.load_config()
        self.shutdown_scheduled = False  # 标记是否已安排关机
 
        # 设置主题和背景色
        self.style = ttk.Style()
        self.style.theme_use("clam")
        self.root.configure(bg="#ecf0f1")  # 淡雅灰蓝背景
 
        # 标题样式
        self.style.configure("Title.TLabel",
                             font=("Segoe UI", 16, "bold"),
                             foreground="#2c3e50",
                             background="#ecf0f1")
        # 速度显示样式
        self.style.configure("Speed.TLabel",
                             font=("Consolas", 28, "bold"),
                             foreground="#27ae60",
                             background="#ecf0f1",
                             padding=10)
        # 主要按钮样式
        self.style.configure("Primary.TButton",
                             font=("Segoe UI", 12, "bold"),
                             foreground="white",
                             background="#2980b9",
                             padding=6)
        self.style.map("Primary.TButton",
                       background=[("active", "#1f6391")])
        # 次要按钮样式
        self.style.configure("Secondary.TButton",
                             font=("Segoe UI", 12),
                             foreground="white",
                             background="#7f8c8d",
                             padding=6)
        self.style.map("Secondary.TButton",
                       background=[("active", "#606b6d")])
        # 危险按钮样式
        self.style.configure("Danger.TButton",
                             font=("Segoe UI", 12),
                             foreground="white",
                             background="#e74c3c",
                             padding=6)
        self.style.map("Danger.TButton",
                       background=[("active", "#c0392b")])
        # 警告按钮样式
        self.style.configure("Warning.TButton",
                             font=("Segoe UI", 12),
                             foreground="white",
                             background="#f39c12",
                             padding=6)
        self.style.map("Warning.TButton",
                       background=[("active", "#d35400")])
 
        self.create_widgets()
        self.setup_config()
        self.running_tasks = {"monitor": False, "timer": False}
        self.check_admin()
 
    # ------------------ 初始化方法 ------------------
    def check_admin(self):
        if not self.is_admin():
            messagebox.showwarning("权限提示", "请以管理员身份运行本程序以确保关机功能正常!")
 
    def is_admin(self):
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except Exception:
            return False
 
    def load_config(self):
        default_config = {
            "unit": "KB/s",
            "monitor": {"interface": "", "threshold": 10, "duration": 5, "interval": 5},
            "timer": {"time": "23:00"}
        }
        try:
            with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                user_config = json.load(f)
                return {**default_config, **user_config}
        except Exception:
            return default_config
 
    def save_config(self):
        with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
            json.dump(self.config, f, ensure_ascii=False, indent=4)
 
    def setup_config(self):
        if 'geometry' in self.config:
            self.root.geometry(self.config['geometry'])
        self.root.after(30000, self.auto_save_config)
 
    def auto_save_config(self):
        self.save_config()
        self.root.after(30000, self.auto_save_config)
 
    # ------------------ UI界面 ------------------
    def create_widgets(self):
        # 整体容器
        main_frame = ttk.Frame(self.root, padding=15)
        main_frame.pack(fill=tk.BOTH, expand=True)
 
        # 顶部控制区(备用扩展)
        control_frame = ttk.Frame(main_frame)
        control_frame.pack(fill=tk.X, pady=10)
 
        # 状态显示区
        status_frame = ttk.Frame(main_frame)
        status_frame.pack(fill=tk.BOTH, expand=True, pady=10)
 
        # 底部操作区
        action_frame = ttk.Frame(main_frame)
        action_frame.pack(fill=tk.X, pady=10)
 
        self.notebook = ttk.Notebook(status_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True)
 
        # 监控模式标签页
        self.monitor_tab = self.create_monitor_tab()
        self.notebook.add(self.monitor_tab, text="网卡监控模式")
 
        # 时间点关机标签页
        self.timer_tab = self.create_timer_tab()
        self.notebook.add(self.timer_tab, text="定时关机模式")
 
        # 状态栏
        self.status_bar = ttk.Label(action_frame, text="就绪", relief=tk.SUNKEN,
                                      anchor="w", background="#bdc3c7", foreground="#2c3e50", padding=5)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
 
    def create_monitor_tab(self):
        frame = ttk.Frame(self.notebook, padding=10)
 
        # 模块标题
        ttk.Label(frame, text="智能监控", style="Title.TLabel").grid(row=0, column=0, sticky=tk.W, columnspan=3, pady=(0,10))
 
        # 网卡选择
        ttk.Label(frame, text="监控接口:", background="#ecf0f1", font=("Segoe UI", 12)).grid(row=1, column=0, pady=5, sticky=tk.W)
        self.interface_var = tk.StringVar()
        self.interface_combobox = ttk.Combobox(frame, textvariable=self.interface_var, width=20, state="readonly")
        self.interface_combobox.grid(row=1, column=1, pady=5, sticky=tk.W)
        ttk.Button(frame, text="刷新", command=self.refresh_interfaces, style="Secondary.TButton").grid(row=1, column=2, padx=5)
 
        # 速度监控显示区域
        speed_frame = ttk.LabelFrame(frame, text="实时速度监控", padding=10)
        speed_frame.grid(row=2, column=0, columnspan=3, sticky=tk.EW, pady=10)
        self.speed_label = ttk.Label(speed_frame, text="0.00 KB/s", style="Speed.TLabel")
        self.speed_label.pack(pady=20)
 
        # 阈值设置区域
        threshold_frame = ttk.LabelFrame(frame, text="关机条件", padding=10)
        threshold_frame.grid(row=3, column=0, columnspan=3, sticky=tk.EW, pady=10)
        ttk.Label(threshold_frame, text="持续低速阈值(KB/s):", font=("Segoe UI", 11)).grid(row=0, column=0, pady=5, sticky=tk.W)
        self.threshold_entry = ttk.Entry(threshold_frame, width=10, font=("Segoe UI", 11))
        self.threshold_entry.insert(0, "10")
        self.threshold_entry.grid(row=0, column=1, pady=5, sticky=tk.W)
 
        ttk.Label(threshold_frame, text="持续时长(分钟):", font=("Segoe UI", 11)).grid(row=1, column=0, pady=5, sticky=tk.W)
        self.duration_entry = ttk.Entry(threshold_frame, width=10, font=("Segoe UI", 11))
        self.duration_entry.insert(0, "5")
        self.duration_entry.grid(row=1, column=1, pady=5, sticky=tk.W)
 
        ttk.Label(threshold_frame, text="采样间隔(秒):", font=("Segoe UI", 11)).grid(row=2, column=0, pady=5, sticky=tk.W)
        self.interval_entry = ttk.Entry(threshold_frame, width=10, font=("Segoe UI", 11))
        self.interval_entry.insert(0, "5")
        self.interval_entry.grid(row=2, column=1, pady=5, sticky=tk.W)
 
        # 开始/停止监控按钮
        self.monitor_btn = ttk.Button(frame, text="开始监控", style="Primary.TButton", command=self.toggle_monitor)
        self.monitor_btn.grid(row=4, column=0, pady=15, sticky=tk.W)
 
        # 日志显示区域,增加垂直滚动条并设置行权重保证初始显示
        log_frame = ttk.Frame(frame)
        log_frame.grid(row=5, column=0, columnspan=3, sticky="nsew", padx=10, pady=5)
        frame.rowconfigure(5, weight=1)
        frame.columnconfigure(0, weight=1)
        self.monitor_status = tk.Text(log_frame, height=8, state=tk.DISABLED, font=("Consolas", 10), bg="#ecf0f1", wrap="word")
        self.monitor_status.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        monitor_scroll = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.monitor_status.yview)
        monitor_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.monitor_status.config(yscrollcommand=monitor_scroll.set)
        return frame
 
    def create_timer_tab(self):
        frame = ttk.Frame(self.notebook, padding=10)
 
        # 模块标题
        ttk.Label(frame, text="定时关机", style="Title.TLabel").grid(row=0, column=0, sticky=tk.W, columnspan=3, pady=(0,10))
 
        # 时间输入区域
        ttk.Label(frame, text="关机时间(HH:MM):", background="#ecf0f1", font=("Segoe UI", 12)).grid(row=1, column=0, pady=10, sticky=tk.W)
        self.time_entry = ttk.Entry(frame, width=15, font=("Segoe UI", 11))
        self.time_entry.insert(0, self.config['timer']['time'])
        self.time_entry.grid(row=1, column=1, pady=10, sticky=tk.W)
 
        # 快速设置按钮
        quick_frame = ttk.Frame(frame)
        quick_frame.grid(row=1, column=2, pady=10, sticky=tk.W)
        ttk.Button(quick_frame, text="1小时后", style="Secondary.TButton", command=lambda: self.set_quick_time(1)).grid(row=0, column=0, padx=5)
        ttk.Button(quick_frame, text="2小时后", style="Secondary.TButton", command=lambda: self.set_quick_time(2)).grid(row=0, column=1, padx=5)
 
        # 操作按钮:设置定时和关机/取消关机放在同一行
        action_frame = ttk.Frame(frame)
        action_frame.grid(row=2, column=0, columnspan=3, pady=15)
        self.timer_btn = ttk.Button(action_frame, text="设置定时", style="Primary.TButton", command=self.toggle_timer)
        self.timer_btn.grid(row=0, column=0, padx=10)
        self.shutdown_timer_btn = ttk.Button(action_frame, text="立即关机", style="Danger.TButton", command=self.toggle_shutdown_timer)
        self.shutdown_timer_btn.grid(row=0, column=1, padx=10)
 
        # 日志显示区域
        log_frame = ttk.Frame(frame)
        log_frame.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=10, pady=5)
        frame.rowconfigure(3, weight=1)
        frame.columnconfigure(0, weight=1)
        self.timer_status = tk.Text(log_frame, height=8, state=tk.DISABLED, font=("Consolas", 10), bg="#ecf0f1", wrap="word")
        self.timer_status.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        timer_scroll = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.timer_status.yview)
        timer_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.timer_status.config(yscrollcommand=timer_scroll.set)
        return frame
 
    def set_quick_time(self, hours):
        now = datetime.now()
        target = now + timedelta(hours=hours)
        self.time_entry.delete(0, tk.END)
        self.time_entry.insert(0, target.strftime("%H:%M"))
 
    # ------------------ 核心功能 ------------------
    def refresh_interfaces(self):
        interfaces = psutil.net_io_counters(pernic=True).keys()
        self.interface_combobox['values'] = list(interfaces)
        if interfaces and not self.interface_var.get():
            self.interface_var.set(next(iter(interfaces)))
 
    def toggle_monitor(self):
        with self.lock:
            if not self.running_tasks['monitor']:
                try:
                    interface = self.interface_var.get()
                    threshold = float(self.threshold_entry.get())
                    duration = float(self.duration_entry.get()) * 60
                    interval = float(self.interval_entry.get())
                except Exception as e:
                    messagebox.showerror("输入错误", f"无效参数: {str(e)}")
                    return
 
                self.running_tasks['monitor'] = True
                self.monitor_btn.config(text="停止监控")
                self.log_monitor("=== 监控模式启动 ===")
                self.log_monitor(f"网卡: {interface}")
                self.log_monitor(f"阈值: {threshold:.2f} KB/s")
                self.log_monitor(f"持续时长: {duration / 60} 分钟")
 
                threading.Thread(
                    target=self.monitor_loop,
                    args=(interface, threshold, duration, interval),
                    daemon=True
                ).start()
            else:
                self.running_tasks['monitor'] = False
                self.monitor_btn.config(text="开始监控")
                self.log_monitor("监控已停止")
 
    def monitor_loop(self, interface, threshold, duration, interval):
        try:
            last_bytes = psutil.net_io_counters(pernic=True)[interface].bytes_recv
            start_time = None
 
            while self.running_tasks['monitor']:
                current_bytes = psutil.net_io_counters(pernic=True)[interface].bytes_recv
                speed = (current_bytes - last_bytes) / interval / 1024
                last_bytes = current_bytes
 
                self.root.after(0, lambda s=speed: self.speed_label.config(text=f"{s:.2f} KB/s"))
 
                status_msg = f"{datetime.now().strftime('%H:%M:%S')} - 速度: {speed:.2f} KB/s | "
                if speed < threshold:
                    if start_time is None:
                        start_time = time.time()
                    elapsed = time.time() - start_time
                    status_msg += f"倒计时: {max(duration - elapsed, 0):.0f}s"
                    if elapsed >= duration:
                        self.log_monitor("== 达到关机条件 ==")
                        self.log_monitor(f"速度连续 {duration / 60} 分钟低于阈值")
                        self.execute_shutdown(60)
                        break
                else:
                    start_time = None
                    status_msg += "状态: 正常"
 
                self.log_monitor(status_msg)
                time.sleep(interval)
        except KeyError:
            self.log_monitor(f"错误:网卡 {interface} 不存在或已断开!")
        except Exception as e:
            self.log_monitor(f"监控错误: {str(e)}")
        finally:
            self.running_tasks['monitor'] = False
            self.root.after(0, lambda: self.monitor_btn.config(text="开始监控"))
 
    def toggle_timer(self):
        with self.lock:
            if not self.running_tasks['timer']:
                time_str = self.time_entry.get()
                try:
                    shutdown_time = datetime.strptime(time_str, "%H:%M")
                    now = datetime.now()
                    target = now.replace(hour=shutdown_time.hour, minute=shutdown_time.minute, second=0)
                    if target < now:
                        target += timedelta(days=1)
                    delay = (target - now).total_seconds()
                    if delay < 60:
                        raise ValueError("关机时间必须大于当前时间至少1分钟")
                except Exception as e:
                    messagebox.showerror("输入错误", f"无效时间格式: {str(e)}\n请输入HH:MM格式(24小时制)")
                    return
 
                self.running_tasks['timer'] = True
                self.timer_btn.config(text="取消定时")
                self.log_timer("=== 定时关机设置 ===")
                self.log_timer(f"目标时间: {target.strftime('%Y-%m-%d %H:%M')}")
                self.log_timer(f"当前时间: {now.strftime('%H:%M:%S')}")
                threading.Thread(
                    target=self.timer_loop,
                    args=(delay,),
                    daemon=True
                ).start()
            else:
                self.running_tasks['timer'] = False
                self.timer_btn.config(text="设置定时")
                self.log_timer("定时已取消")
 
    def timer_loop(self, delay):
        start_time = time.time()
        while self.running_tasks['timer'] and (time.time() - start_time) < delay:
            remaining = delay - (time.time() - start_time)
            self.log_timer(f"剩余时间: {str(timedelta(seconds=int(remaining)))}")
            time.sleep(1)
        if self.running_tasks['timer']:
            self.log_timer("== 定时关机时间到 ==")
            self.execute_shutdown(0)
        self.running_tasks['timer'] = False
 
    def toggle_shutdown_timer(self):
        # 如果当前未安排关机,则立即安排关机并更新按钮文本
        if not self.shutdown_scheduled:
            os.system("shutdown -s -t 60")
            self.log_timer("已安排关机,60秒后关机")
            self.shutdown_timer_btn.config(text="取消关机")
            self.shutdown_scheduled = True
            self.status_bar.config(text="60秒后关机(输入 shutdown -a 可取消)")
        else:
            os.system("shutdown -a")
            self.log_timer("已取消关机计划")
            self.shutdown_timer_btn.config(text="立即关机")
            self.shutdown_scheduled = False
            self.status_bar.config(text="关机计划已取消")
 
    def execute_shutdown(self, delay=60):
        try:
            self.log_monitor(f"准备关机,{delay}秒后关闭系统...")
            self.log_timer(f"系统将在{delay}秒后关闭")
            # 采用非阻塞方式执行关机命令
            os.system(f"shutdown -s -t {max(delay, 10)}")
            self.status_bar.config(text=f"{delay}秒后关机(输入 shutdown -a 可取消)")
        except Exception as e:
            self.log_monitor(f"关机失败: {str(e)}")
 
    def cancel_shutdown(self):
        result = os.system("shutdown -a")
        if result == 0:
            self.log_timer("已取消关机计划")
        else:
            self.log_timer("无活动的关机计划")
        self.status_bar.config(text="关机计划已取消")
 
    # ------------------ 辅助方法 ------------------
    def log_monitor(self, msg):
        self.monitor_status.config(state=tk.NORMAL)
        if int(self.monitor_status.index('end-1c').split('.')[0]) > 500:
            self.monitor_status.delete("1.0", "3.0")
        self.monitor_status.insert(tk.END, msg + "\n")
        self.monitor_status.yview_moveto(1.0)
        self.monitor_status.config(state=tk.DISABLED)
        print(f"[MONITOR] {msg}")
 
    def log_timer(self, msg):
        self.timer_status.config(state=tk.NORMAL)
        self.timer_status.insert(tk.END, msg + "\n")
        self.timer_status.yview_moveto(1.0)
        self.timer_status.config(state=tk.DISABLED)
        print(f"[TIMER] {msg}")
 
    def on_closing(self):
        self.config['geometry'] = self.root.geometry()
        self.save_config()
        self.root.destroy()
 
if __name__ == "__main__":
    root = tk.Tk()
    app = ShutdownManagerApp(root)
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()

免费评分

参与人数 12吾爱币 +15 热心值 +10 收起 理由
dongrgg + 1 + 1 我很赞同!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
www52pojiee + 1 我很赞同!
Shenjingb + 1 + 1 热心回复!
wanfon + 1 + 1 热心回复!
tommybaby + 1 + 1 我很赞同!
木鱼水心 + 1 + 1 我很赞同!
caituaner + 1 我很赞同!
xingkongz + 1 + 1 我很赞同!
zylz9941 + 1 + 1 谢谢@Thanks!
a19900531 + 1 我很赞同!
powehi + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Timothys 发表于 2025-3-26 14:39
simmtech 发表于 2025-3-26 12:55
能不能,监控鼠标和键盘,设置多长时间没动作了,自动关机。谢谢

应该也可以 你可以让AI帮你写一个
因为我的需求是下载完毕需要的东西自动关机,下载期间我都不在电脑旁边,所以鼠标键盘都是没有操作的
 楼主| Timothys 发表于 2025-3-26 14:42
暗之守护 发表于 2025-3-26 14:29
下载软件都会提供这个功能的吧,如果只是为了使用方便完全没必要另觅蹊径

是的 大部分下载软件都有
但是目前我的需求多个软件同时在下载不同的资源,一个下载完其他的可能还在下载。
所以没办法用软件自带的。
dysunb 发表于 2025-3-26 12:03
assuller 发表于 2025-3-26 12:11
dysunb 发表于 2025-3-26 12:03
如果计算机处于睡眠状态,还能定时关机吗

你睡觉都睡着了再喊起来重新睡吗
dysunb 发表于 2025-3-26 12:19
assuller 发表于 2025-3-26 12:11
你睡觉都睡着了再喊起来重新睡吗

那就是不能了,我的计算机设置了睡眠,有时不知机器是在睡眠还是关机了
samson12138 发表于 2025-3-26 12:19
会不会网卡了一下就开始自动关机了
Msr365 发表于 2025-3-26 12:23
没什么作用
assuller 发表于 2025-3-26 12:25
dysunb 发表于 2025-3-26 12:19
那就是不能了,我的计算机设置了睡眠,有时不知机器是在睡眠还是关机了

睡眠和关机差不多,主要功能都不工作了,电源里面可以设置过多久是休眠还是睡眠,还是关屏
simmtech 发表于 2025-3-26 12:55
能不能,监控鼠标和键盘,设置多长时间没动作了,自动关机。谢谢
younger4862 发表于 2025-3-26 12:56
哈哈,有点意思
kexin123 发表于 2025-3-26 12:56
我感觉挺好的啊,不错,支持
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-8 00:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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