python打包exe程序,如何加入注册码功能?

87 2025-07-19 10:51

要将 Python 程序打包为带注册码功能的 .exe,推荐使用 PyInstaller 工具,并结合注册码机制实现授权验证。以下是完整实现步骤:

✅ 一、打包为 EXE(使用 PyInstaller)

  1. 安装 PyInstaller:
bash
 
复制
pip install pyinstaller
 
  1. 打包命令(单文件、无控制台):
bash
 
复制
pyinstaller -F -w your_script.py
 
  • -F:单文件打包
  • -w:去掉控制台窗口(GUI程序适用)

✅ 二、注册码机制实现思路

推荐方式:机器码 + 注册码 模式

  • 程序首次运行时生成机器码(如硬盘序列号)
  • 用户将机器码发给管理员
  • 管理员用注册机加密后生成注册码
  • 用户输入注册码验证,验证通过则写入本地授权文件

✅ 三、注册码功能代码示例(基于硬盘序列号)

1. 获取机器码(C盘卷序列号)

Python
 
复制
import win32api

def get_machine_code():
    return str(win32api.GetVolumeInformation("C:\\")[1])
 

2. 注册码生成与验证(使用 DES + Base64)

Python
 
复制
import base64
from pyDes import des, CBC, PAD_PKCS5

DES_KEY = "A1B2C3D4"
DES_IV = "\x11\x22\x33\x44\x55\x66\x77\x88"

def encrypt(text):
    k = des(DES_KEY, CBC, DES_IV, padmode=PAD_PKCS5)
    return base64.b64encode(k.encrypt(text)).decode()

def decrypt(ciphertext):
    k = des(DES_KEY, CBC, DES_IV, padmode=PAD_PKCS5)
    return k.decrypt(base64.b64decode(ciphertext)).decode()
 

3. 注册流程

Python
 
复制
import os

def register():
    if os.path.exists("license.key"):
        with open("license.key") as f:
            encrypted_code = f.read()
        if decrypt(encrypted_code) == get_machine_code():
            return True
    reg_code = input("请输入注册码:")
    try:
        if decrypt(reg_code) == get_machine_code():
            with open("license.key", "w") as f:
                f.write(reg_code)
            print("注册成功!")
            return True
        else:
            print("注册码无效!")
    except Exception:
        print("注册码格式错误!")
    return False
 

✅ 四、管理员注册机(单独脚本)

Python
 
复制
# 管理员使用:输入用户机器码,生成注册码
machine_code = input("输入用户机器码:")
print("注册码为:", encrypt(machine_code))
 

✅ 五、打包注意事项

  • 加密打包(防止反编译):
bash
 
复制
pyinstaller -F -w --key=yourpassword your_script.py
 
  • 使用 UPX 压缩体积:
bash
 
复制
pyinstaller -F -w --upx-dir=upx路径 your_script.py
 

✅ 六、完整流程总结

表格
 
复制
步骤 操作方 内容
1 用户 运行程序,获取机器码
2 用户 将机器码发给管理员
3 管理员 用注册机生成注册码
4 用户 输入注册码激活
5 程序 验证注册码并保存授权文件

如需图形界面注册窗口,可结合 tkinterPyQt 实现,注册逻辑不变。

 

结合 tkinter实现图形界面注册窗口

下面给出一个可直接运行的完整示例,把注册码机制(机器码 → 加密注册码 → 验证)与 Tkinter 图形界面整合在一起。
目录结构只需两个文件即可运行:
 
复制
project/
├─ main.py          # 主程序(带 Tkinter 注册窗口)
└─ regmaker.py      # 管理员注册机(单独脚本,给管理员用)
 

🔧 1. 安装依赖

bash
 
复制
pip install pyinstaller pyDes
 

📁 2. main.py(主程序 + Tkinter 注册界面)

Python
 
复制
# main.py
import os
import tkinter as tk
from tkinter import messagebox
import win32api
import base64
from pyDes import des, CBC, PAD_PKCS5

# DES 密钥和 IV(必须与 regmaker.py 保持一致)
DES_KEY = b"A1B2C3D4"
DES_IV = b"\x11\x22\x33\x44\x55\x66\x77\x88"

# ------------------- 加解密 -------------------
def encrypt(text: str) -> str:
    k = des(DES_KEY, CBC, DES_IV, padmode=PAD_PKCS5)
    return base64.b64encode(k.encrypt(text.encode())).decode()

def decrypt(ciphertext: str) -> str:
    k = des(DES_KEY, CBC, DES_IV, padmode=PAD_PKCS5)
    return k.decrypt(base64.b64decode(ciphertext.encode())).decode()

# ------------------- 机器码 -------------------
def get_machine_code() -> str:
    return str(win32api.GetVolumeInformation("C:\\")[1])

# ------------------- 注册逻辑 -------------------
LICENSE_FILE = "license.key"

def is_licensed() -> bool:
    """检查是否已经注册"""
    if not os.path.exists(LICENSE_FILE):
        return False
    try:
        with open(LICENSE_FILE, "r", encoding="utf-8") as f:
            reg_code = f.read().strip()
        return decrypt(reg_code) == get_machine_code()
    except Exception:
        return False

def save_license(reg_code: str) -> bool:
    """保存注册码,返回是否成功"""
    try:
        if decrypt(reg_code) == get_machine_code():
            with open(LICENSE_FILE, "w", encoding="utf-8") as f:
                f.write(reg_code)
            return True
    except Exception:
        pass
    return False

# ------------------- Tkinter GUI -------------------
class RegWindow(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        self.title("软件注册")
        self.geometry("300x220")
        self.resizable(False, False)
        self.grab_set()  # 模态窗口

        tk.Label(self, text="机器码:").pack(pady=5)
        self.machine_label = tk.Label(self, text=get_machine_code(), bg="#f0f0f0", width=35)
        self.machine_label.pack()

        tk.Label(self, text="请输入注册码:").pack(pady=5)
        self.reg_entry = tk.Entry(self, width=35)
        self.reg_entry.pack()

        tk.Button(self, text="注册", width=15, command=self.on_register).pack(pady=10)

    def on_register(self):
        reg_code = self.reg_entry.get().strip()
        if not reg_code:
            messagebox.showerror("错误", "注册码不能为空!")
            return
        if save_license(reg_code):
            messagebox.showinfo("成功", "注册成功!请重启程序。")
            self.destroy()
        else:
            messagebox.showerror("失败", "注册码无效!")

# ------------------- 主程序入口 -------------------
def main():
    root = tk.Tk()
    root.withdraw()  # 先隐藏主窗口

    if not is_licensed():
        RegWindow(root)
        root.wait_window()  # 等待注册窗口关闭
        if not is_licensed():
            messagebox.showerror("未注册", "软件未注册,即将退出。")
            return

    # 这里开始写真正的主程序逻辑
    root.deiconify()
    root.title("正式版主程序")
    tk.Label(root, text="欢迎使用正式版!", font=("微软雅黑", 16)).pack(pady=50)
    root.geometry("300x200")
    root.mainloop()

if __name__ == "__main__":
    main()
 

📁 3. regmaker.py(管理员注册机)

Python
 
复制
# regmaker.py
import base64
from pyDes import des, CBC, PAD_PKCS5

DES_KEY = b"A1B2C3D4"
DES_IV = b"\x11\x22\x33\x44\x55\x66\x77\x88"

def encrypt(text: str) -> str:
    k = des(DES_KEY, CBC, DES_IV, padmode=PAD_PKCS5)
    return base64.b64encode(k.encrypt(text.encode())).decode()

if __name__ == "__main__":
    machine_code = input("请输入用户机器码:").strip()
    print("注册码:", encrypt(machine_code))
 

🚀 4. 打包成 EXE(单文件、无控制台)

bash
 
复制
pyinstaller -F -w main.py
 
打包后得到 main.exe;把 regmaker.py 单独给管理员即可。

✅ 使用流程

  1. 用户第一次运行 main.exe,弹出注册窗口,显示机器码。
  2. 用户把机器码发给管理员。
  3. 管理员运行 python regmaker.py,输入机器码,得到注册码。
  4. 用户复制注册码到窗口,点击“注册”,验证通过后生成 license.key,下次启动直接跳过注册窗口。

 

全部评论

·