You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:30:34