如何为Tkinter GUI的Python打包EXE设置30天到期限制?
实现Tkinter程序的30天过期限制
你的核心思路完全没问题——通过记录首次启动日期来计算过期时间,但现有代码还有几处需要调整,同时咱们得优化下防篡改能力,毕竟打包成EXE后,用户很可能会手动修改日期文件绕过期限制。
1. 修正基础逻辑并完善首次运行处理
你的代码里launch_date变量未定义,messagebox.Message的用法也不对,而且没处理首次运行时创建启动日期文件的场景。这是修正后的基础版本:
import os import sys import datetime from tkinter import Tk, messagebox # 把启动日期文件放在用户目录下,避免权限问题,也更隐蔽 LAUNCH_DATE_FILE = os.path.join(os.path.expanduser("~"), ".my_app_launch_date.txt") def program_expired(): if os.path.exists(LAUNCH_DATE_FILE): try: with open(LAUNCH_DATE_FILE, 'r') as fileRead: time_as_str = fileRead.read().strip() start_date = datetime.datetime.strptime(time_as_str, "%Y_%m_%d") expire_date = start_date + datetime.timedelta(days=30) # 改为你要的30天 if datetime.datetime.now() > expire_date: messagebox.showerror("过期提示", "您的工具已过期,请联系开发者获取新版本。") sys.exit() else: main() except Exception as e: # 只要文件被篡改或者格式错误,直接判定过期 messagebox.showerror("验证失败", "程序完整性被破坏,工具已过期。") sys.exit() else: # 首次运行,写入当天日期 today = datetime.datetime.now().strftime("%Y_%m_%d") with open(LAUNCH_DATE_FILE, 'w') as fileWrite: fileWrite.write(today) main() def main(): root = Tk() root.resizable(width=False, height=False) root.geometry("550x300") root.title("我的工具") # 这里添加你的GUI组件逻辑 root.mainloop() if __name__ == "__main__": program_expired()
2. 提升防篡改能力(关键!)
上面的基础版本很容易被用户手动修改文件绕过,咱们可以用以下两种方案优化:
方案A:把日期存到Windows注册表
对于Windows平台,把首次启动日期放在注册表中,比本地文件更隐蔽:
import winreg def get_launch_date_from_registry(): try: # 打开HKEY_CURRENT_USER下的自定义软件项 key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\MyCustomApp", 0, winreg.KEY_READ) start_date_str, _ = winreg.QueryValueEx(key, "FirstLaunchDate") winreg.CloseKey(key) return start_date_str except FileNotFoundError: # 注册表项不存在,说明是首次运行 return None def save_launch_date_to_registry(date_str): try: # 创建注册表项并写入日期 key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, r"Software\MyCustomApp") winreg.SetValueEx(key, "FirstLaunchDate", 0, winreg.REG_SZ, date_str) winreg.CloseKey(key) except Exception as e: messagebox.showerror("错误", "无法保存启动信息,请检查权限。") sys.exit() # 之后把program_expired里的文件读写逻辑替换成上面的注册表操作就行
方案B:加密存储日期
对存储的日期字符串做简单加密,避免用户直接修改:
# 简单异或加密(可以换成更复杂的加密算法,比如AES) def encrypt_date(date_str, key="my_secure_key_123"): encrypted = ''.join([chr(ord(c) ^ ord(key[i%len(key)])) for i, c in enumerate(date_str)]) return encrypted def decrypt_date(encrypted_str, key="my_secure_key_123"): return ''.join([chr(ord(c) ^ ord(key[i%len(key)])) for i, c in enumerate(encrypted_str)]) # 存储时加密: # encrypted_today = encrypt_date(today) # fileWrite.write(encrypted_today) # 读取时解密: # encrypted_str = fileRead.read().strip() # time_as_str = decrypt_date(encrypted_str)
3. 打包EXE的注意事项
如果用PyInstaller打包:
- 用
--onefile参数打包单文件EXE时,咱们把日期文件放在用户目录下(os.path.expanduser("~")),就不会出现临时目录找不到文件的问题。 - 可以加
--windowed参数隐藏控制台窗口(如果你的GUI不需要控制台输出)。
需要说明的是:没有绝对完美的过期限制方案,技术熟练的用户还是可能破解,但上面的方案足以应对大部分普通用户。
内容的提问来源于stack exchange,提问作者ashu
相关产品推荐
相关产品推荐

