分享一个定时重启电脑小工具,用Python 写的
====更新====8.15更新内容:
1.增加了关机、重启、休眠三种状态切换,三种状态定时任务互不干扰。
2.可设置程序开机自启动,附带状态提示。
3.可以选择开机时候自动运行的程序(部分应用可能是路径问题,兼容不到位。支持bat文件,可用bat文件开启)
4.优化了倒计时部分,由分钟后执行[输入框]改为 [输入框]后执行,更符合阅读体验。
5.优化了[小时]、[分钟]默认为0会导致设置0:00问题。
5.倒计时最后五秒有变色显示。
6.使用互斥锁禁止重复开启软件。
7.任务逻辑优化、UI体验还有些一时想不起哈哈自行发现吧
V2版本
ps: bat 命令 start "" "C:\Users\scr\AppData\Local\Programs\Microsoft VS Code\Code.exe"
支持文件类型
https://ghbseymour.lanzoum.com/b00od8195c
密码:52pj
=====原=====
一个定时重启电脑的小工具,可选择每日、每周、每月某个时间点自动重启电脑。
打包的时候把所有依赖的 Python 库 都打包了,所以体积可能有些大。
win10和win11都测试过,有问题可以留言讨论。
有需要可自取。
欢迎讨论优化内容。
在线查毒
收藏了,辛苦楼主
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import time
import threading
import os
import subprocess
import winreg
import sys
from datetime import datetime, timedelta
import msvcrt
class TimedTaskTool:
def __init__(self, root):
# 检查是否已经有实例在运行
self.check_single_instance()
self.root = root
self.root.title("定时任务工具")
self.root.geometry("500x720")# 增加宽度以显示所有星期
self.root.resizable(False, False)
# 设置中文字体,适当缩小
self.style = ttk.Style()
self.style.configure("TLabel", font=("SimHei", 8))
self.style.configure("TRadiobutton", font=("SimHei", 8))
self.style.configure("TButton", font=("SimHei", 8))
self.style.configure("TCheckbutton", font=("SimHei", 8))
# 操作模式
self.operation_mode = tk.StringVar(value="重启")
self.create_operation_mode_frame()
# 日期设置
self.day_of_month = tk.IntVar(value=15)
self.week_days = {"周一": tk.BooleanVar(), "周二": tk.BooleanVar(),
"周三": tk.BooleanVar(), "周四": tk.BooleanVar(),
"周五": tk.BooleanVar(), "周六": tk.BooleanVar(),
"周日": tk.BooleanVar()}
self.create_date_frame()
# 时间设置
self.hour = tk.IntVar(value=12)
self.minute = tk.IntVar(value=0)
self.create_time_frame()
# 任务存储 - 支持多个定时任务
self.tasks = {}
self.task_threads = {}
self.task_statuses = {}
for mode in ["重启", "关机", "休眠"]:
self.tasks = None
self.task_threads = None
self.task_statuses = tk.StringVar(value=f"{mode}任务: 未设置")
# 重复频率
self.repeat_type = tk.StringVar(value="每日")
self.create_repeat_frame()
# 倒计时操作
self.countdown_minutes = tk.IntVar(value=1)
self.countdown_status = tk.StringVar(value="未启动")
self.countdown_label = None# 用于控制颜色
self.create_countdown_frame()
# 开机设置
self.startup_auto = tk.BooleanVar(value=False)
self.startup_program = tk.StringVar(value="未选择任何项目")
self.startup_check_var = tk.BooleanVar(value=False)
self.create_startup_frame()
# 任务按钮
self.create_task_buttons()
# 任务状态
self.create_status_label()
# 检查开机自启动状态
self.check_startup_status()
def check_single_instance(self):
# 使用文件锁实现单实例
self.lock_file = os.path.join(os.environ.get('TEMP', 'C:\\temp'), 'timed_task_tool.lock')
try:
# 尝试创建并锁定文件
self.lock = open(self.lock_file, 'w')
msvcrt.locking(self.lock.fileno(), msvcrt.LK_NBLCK, 1)
except:
messagebox.showerror("错误", "程序已经在运行中!")
sys.exit(1)
def create_operation_mode_frame(self):
frame = ttk.LabelFrame(self.root, text="操作模式", padding="10")
frame.pack(fill="x", padx=10, pady=5)
ttk.Radiobutton(frame, text="重启", variable=self.operation_mode, value="重启").pack(side="left", padx=3)
ttk.Radiobutton(frame, text="关机", variable=self.operation_mode, value="关机").pack(side="left", padx=3)
ttk.Radiobutton(frame, text="休眠", variable=self.operation_mode, value="休眠").pack(side="left", padx=3)
def create_date_frame(self):
frame = ttk.LabelFrame(self.root, text="日期设置", padding="10")
frame.pack(fill="x", padx=10, pady=5)
ttk.Label(frame, text="每月几号: ").grid(row=0, column=0, padx=5, pady=5)
day_spinbox = ttk.Spinbox(frame, from_=1, to=31, textvariable=self.day_of_month, width=5)
day_spinbox.grid(row=0, column=1, padx=5, pady=5)
ttk.Label(frame, text="(设置每月的操作日期,自动处理月份天数差异)").grid(row=0, column=2, padx=5, pady=5, sticky="w")
# 创建一个水平框架来放置星期选择,不使用网格布局
ttk.Label(frame, text="每周几: ").grid(row=1, column=0, padx=5, pady=2, sticky="w")
days_frame = ttk.Frame(frame)
days_frame.grid(row=1, column=1, columnspan=6, sticky="w")
days_order = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
# 所有星期放在同一行显示
for day in days_order:
# 使用pack布局,水平排列
ttk.Checkbutton(days_frame, text=day, variable=self.week_days).pack(side="left", padx=3, pady=2)
def create_time_frame(self):
frame = ttk.LabelFrame(self.root, text="操作时间设置 (24小时制)", padding="10")
frame.pack(fill="x", padx=10, pady=5)
ttk.Label(frame, text="小时: ").grid(row=0, column=0, padx=3, pady=3)
hour_spinbox = ttk.Spinbox(frame, from_=0, to=23, textvariable=self.hour, width=4)
hour_spinbox.grid(row=0, column=1, padx=3, pady=3)
ttk.Label(frame, text="分钟: ").grid(row=0, column=2, padx=3, pady=3)
minute_spinbox = ttk.Spinbox(frame, from_=0, to=59, textvariable=self.minute, width=4)
minute_spinbox.grid(row=0, column=3, padx=3, pady=3)
def create_repeat_frame(self):
frame = ttk.LabelFrame(self.root, text="重复频率", padding="10")
frame.pack(fill="x", padx=10, pady=5)
ttk.Radiobutton(frame, text="每日", variable=self.repeat_type, value="每日").pack(side="left", padx=3)
ttk.Radiobutton(frame, text="每周", variable=self.repeat_type, value="每周").pack(side="left", padx=3)
ttk.Radiobutton(frame, text="每月", variable=self.repeat_type, value="每月").pack(side="left", padx=3)
def create_countdown_frame(self):
frame = ttk.LabelFrame(self.root, text="倒计时操作", padding="10")
frame.pack(fill="x", padx=10, pady=5)
minute_spinbox = ttk.Spinbox(frame, from_=1, to=1440, textvariable=self.countdown_minutes, width=4)
minute_spinbox.grid(row=0, column=0, padx=3, pady=3)
ttk.Label(frame, text="后执行操作").grid(row=0, column=1, padx=3, pady=3)
self.countdown_label = ttk.Label(frame, textvariable=self.countdown_status, foreground="blue", width=10)
self.countdown_label.grid(row=0, column=2, padx=3, pady=3)
ttk.Button(frame, text="开始", command=self.start_countdown, width=6).grid(row=0, column=3, padx=2, pady=3)
ttk.Button(frame, text="取消", command=self.cancel_countdown, width=6).grid(row=0, column=4, padx=2, pady=3)
def create_startup_frame(self):
frame = ttk.LabelFrame(self.root, text="开机设置", padding="10")
frame.pack(fill="x", padx=10, pady=5)
self.startup_status_label = ttk.Label(frame, text="未开启", foreground="red", width=6)
ttk.Checkbutton(frame, text="程序开机自启动: ", variable=self.startup_auto, command=self.toggle_startup).grid(row=0, column=0, padx=3, pady=3, sticky="w")
self.startup_status_label.grid(row=0, column=1, padx=2, pady=3)
self.startup_check_var = tk.BooleanVar(value=False)
ttk.Checkbutton(frame, text="开机后自动运行: ", variable=self.startup_check_var).grid(row=1, column=0, padx=3, pady=3, sticky="w")
ttk.Label(frame, textvariable=self.startup_program, width=15).grid(row=1, column=1, padx=2, pady=3, sticky="w")
ttk.Button(frame, text="浏览...", command=self.browse_program, width=6).grid(row=1, column=2, padx=2, pady=3)
def create_task_buttons(self):
frame = ttk.Frame(self.root, padding="10")
frame.pack(fill="x", padx=10, pady=5)
ttk.Button(frame, text="设置定时任务", command=self.set_timed_task, width=10).pack(side="left", padx=5, pady=3)
ttk.Button(frame, text="取消定时任务", command=self.cancel_timed_task, width=10).pack(side="right", padx=5, pady=3)
def create_status_label(self):
frame = ttk.LabelFrame(self.root, text="系统状态", padding="10")
frame.pack(fill="x", padx=10, pady=5)
# 添加当前时间显示
self.current_time_var = tk.StringVar()
ttk.Label(frame, textvariable=self.current_time_var, foreground="gray").grid(row=0, column=0, padx=3, pady=1, sticky="w")
# 任务状态显示
status_frame = ttk.Frame(frame)
status_frame.grid(row=1, column=0, columnspan=3, sticky="ew", pady=2)
for i, mode in enumerate(["重启", "关机", "休眠"]):
ttk.Label(status_frame, textvariable=self.task_statuses, foreground="blue").grid(row=0, column=i, padx=5, pady=1, sticky="w")
# 程序状态显示
self.program_status_var = tk.StringVar(value="程序运行正常")
ttk.Label(frame, textvariable=self.program_status_var, foreground="green").grid(row=2, column=0, padx=3, pady=1, sticky="w")
# 更新时间的函数
def update_time():
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.current_time_var.set(f"当前时间: {current_time}")
# 每秒更新一次
self.root.after(1000, update_time)
# 启动时间更新
update_time()
def check_startup_status(self):
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_READ)
value, _ = winreg.QueryValueEx(key, 'TimedTaskTool')
winreg.CloseKey(key)
self.startup_auto.set(True)
self.startup_status_label.config(text="已开启", foreground="green")
except:
self.startup_auto.set(False)
self.startup_status_label.config(text="未开启", foreground="red")
def toggle_startup(self):
try:
if self.startup_auto.get():
# 开启开机自启动
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_WRITE)
winreg.SetValueEx(key, 'TimedTaskTool', 0, winreg.REG_SZ, sys.executable)
winreg.CloseKey(key)
self.startup_status_label.config(text="已开启", foreground="green")
else:
# 关闭开机自启动
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_WRITE)
winreg.DeleteValue(key, 'TimedTaskTool')
winreg.CloseKey(key)
self.startup_status_label.config(text="未开启", foreground="red")
except FileNotFoundError:
# 如果值不存在,依旧显示未开启
self.startup_status_label.config(text="未开启", foreground="red")
except Exception as e:
messagebox.showerror("错误", f"设置开机自启动失败: {str(e)}")
def browse_program(self):
filename = filedialog.askopenfilename(title="选择程序", filetypes=[("所有文件", "*.*")])
if filename:
self.startup_program.set(filename)
def start_countdown(self):
minutes = self.countdown_minutes.get()
seconds = minutes * 60
self.countdown_status.set(f"倒计时中 ({minutes}分钟)")
self.countdown_label.config(foreground="blue")
self.root.update()
# 创建倒计时线程
def countdown():
for i in range(seconds, 0, -1):
minutes_left = i // 60
seconds_left = i % 60
# 最后5秒变红
if i <= 5:
self.countdown_label.config(foreground="red")
self.countdown_status.set(f"即将执行 ({seconds_left}秒)")
else:
self.countdown_status.set(f"倒计时中 ({minutes_left}分{seconds_left}秒)")
time.sleep(1)
if self.countdown_status.get().startswith("未启动"):
break
if not self.countdown_status.get().startswith("未启动"):
self.countdown_status.set("执行中...")
self.execute_operation()
self.countdown_label.config(foreground="blue")
self.countdown_status.set("未启动")
threading.Thread(target=countdown, daemon=True).start()
def cancel_countdown(self):
self.countdown_status.set("未启动")
self.countdown_label.config(foreground="blue")
def set_timed_task(self):
# 获取设置
operation = self.operation_mode.get()
hour = self.hour.get()
minute = self.minute.get()
repeat_type = self.repeat_type.get()
# 验证设置
if repeat_type == "每周":
selected_days =
if not selected_days:
messagebox.showerror("错误", "请选择每周的至少一天")
return
# 取消该操作模式的现有任务
self.cancel_timed_task(operation)
# 创建新任务
self.tasks = {"hour": hour, "minute": minute, "repeat_type": repeat_type}
self.task_threads = threading.Thread(
target=self.task_runner,
args=(operation, hour, minute, repeat_type),
daemon=True
)
self.task_threads.start()
# 更新状态
if repeat_type == "每日":
status = f"每日 {hour:02d}:{minute:02d} 执行"
elif repeat_type == "每周":
selected_days =
days_str = ", ".join(selected_days)
status = f"每周 {days_str} {hour:02d}:{minute:02d} 执行"
else:# 每月
status = f"每月 {self.day_of_month.get()}号 {hour:02d}:{minute:02d} 执行"
self.task_statuses.set(f"{operation}任务: 已设置 ({status})")
messagebox.showinfo("成功", f"{operation}定时任务已设置:\n{status}")
def cancel_timed_task(self, operation=None):
if operation:
# 取消特定操作的任务
if self.task_threads and self.task_threads.is_alive():
# 通知线程结束
self.tasks = None
self.task_threads.join(1)# 等待线程结束,最多等待1秒
self.task_threads = None
self.task_statuses.set(f"{operation}任务: 未设置")
else:
# 取消所有任务
for mode in ["重启", "关机", "休眠"]:
self.cancel_timed_task(mode)
def task_runner(self, operation, hour, minute, repeat_type):
while True:
# 检查任务是否已被取消
if self.tasks is None:
break
try:
now = datetime.now()
target_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
# 如果今天的目标时间已过,则设置为明天
if target_time <= now:
target_time += timedelta(days=1)
# 计算等待时间
wait_time = (target_time - now).total_seconds()
# 等待到目标时间,每秒检查一次任务是否已取消
wait_done = True
for _ in range(int(wait_time // 1)):
if self.tasks is None:
wait_done = False
break
time.sleep(1)
# 检查是否需要执行
if wait_done and self.tasks is not None:
# 更新当前时间
now = datetime.now()
# 根据重复类型检查是否应该执行
should_execute = False
if repeat_type == "每日":
should_execute = True
elif repeat_type == "每周":
weekday = now.weekday()# 0=周一, 6=周日
weekdays_map = {"周一": 0, "周二": 1, "周三": 2, "周四": 3, "周五": 4, "周六": 5, "周日": 6}
selected_days = for day, var in self.week_days.items() if var.get()]
should_execute = weekday in selected_days
elif repeat_type == "每月":
# 处理月份天数差异
day_of_month = self.day_of_month.get()
last_day = (now.replace(day=28) + timedelta(days=4)).replace(day=1) - timedelta(days=1)
if day_of_month > last_day.day:
should_execute = now.day == last_day.day
else:
should_execute = now.day == day_of_month
if should_execute:
self.execute_operation(operation)
except Exception as e:
# 记录错误但不中断任务
error_msg = f"任务执行错误: {str(e)}操作: {operation}"
print(error_msg)
# 可以选择记录到日志文件
try:
with open("task_error.log", "a") as f:
f.write(f"{datetime.now()}: {error_msg}\n")
except:
pass
# 短暂暂停后继续
time.sleep(5)
def execute_operation(self, operation=None):
if operation is None:
operation = self.operation_mode.get()
try:
if operation == "重启":
os.system("shutdown /r /t 0")
elif operation == "关机":
os.system("shutdown /s /t 0")
elif operation == "休眠":
# 注意:Windows休眠命令可能需要管理员权限
os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
except Exception as e:
messagebox.showerror("操作失败", f"无法执行{operation}操作: {str(e)}")
# 记录错误到日志
try:
with open("operation_error.log", "a") as f:
f.write(f"{datetime.now()}: 无法执行{operation}操作: {str(e)}\n")
except:
pass
def on_closing(root, app):
# 取消所有定时任务
app.cancel_timed_task()
# 释放文件锁
try:
msvcrt.locking(app.lock.fileno(), msvcrt.LK_UNLCK, 1)
app.lock.close()
os.remove(app.lock_file)
except:
pass
root.destroy()
if __name__ == "__main__":
root = tk.Tk()
app = TimedTaskTool(root)
root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root, app))
root.mainloop() 这是定时重启操作系统吗?有没有定时重启某个应用程序 是的,是定时重启电脑的,可能我的叙述不太清楚,我改一下
目前没有重启某应用这个功能。 多谢支持 用系统cmd命令也不错 建议你在下面增加倒计时关机和倒计时休眠,这也有用 感觉真是不错啊啊啊啊 这个不错,挺好。。定期定时。
页:
[1]
2