No result defined for action cxd.action.QueryAction and result success

<s:form action="query">
<s:textfield label="书名" name="name" />
<s:submit value="查询"/>

</s:form>



<package name="struts2" extends="struts-default">
<action name="query" class="cxd.action.QueryAction">


<result name="success">/cxd/result.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>

可能会出现错误No result defined for action cxd.action.QueryAction and result success

引起该问题的原因是所写的action名占用了struts的保留字,将action改名就可以

改成QueryBooks


import tkinter as tk from tkinter import ttk, filedialog, messagebox, scrolledtext import random import string import hashlib import os import base64 import time import winreg import shutil import datetime import ctypes class DLLProtectorApp: def __init__(self, root): self.root = root self.root.title("DLL保护工具 - 加密、混淆与授权激活系统") self.root.geometry("1000x800") self.root.configure(bg='#2c3e50') # 创建标签页 self.tab_control = ttk.Notebook(root) # 加密标签页 self.encrypt_tab = ttk.Frame(self.tab_control) self.tab_control.add(self.encrypt_tab, text='DLL加密') # 混淆标签页 self.obfuscate_tab = ttk.Frame(self.tab_control) self.tab_control.add(self.obfuscate_tab, text='代码混淆') # 授权标签页 self.license_tab = ttk.Frame(self.tab_control) self.tab_control.add(self.license_tab, text='授权管理') self.tab_control.pack(expand=1, fill="both", padx=10, pady=10) # 初始化UI self.create_encrypt_tab() self.create_obfuscate_tab() self.create_license_tab() # 初始化状态变量 self.encrypt_files = [] self.obfuscate_files = [] self.license_key = "" self.activation_date = None # 激活时间 self.expiry_date = None # 到期时间 self.usage_count = 0 # 功能使用次数计数器 self.max_usage_count = 0 # 最大使用次数 self.time_limit_days = 0 # 时间限制天数 self.permanent_license_shown = False # 标记永久授权是否已显示 self.machine_id = "" # 存储机器码 # 创建状态栏 self.status_var = tk.StringVar() self.status_var.set("就绪") self.status_bar = tk.Label(root, textvariable=self.status_var, bd=1, relief=tk.SUNKEN, anchor=tk.W, bg='#34495e', fg='white') self.status_bar.pack(side=tk.BOTTOM, fill=tk.X) def create_encrypt_tab(self): tab = self.encrypt_tab # 标题 title = tk.Label(tab, text="DLL文件加密", font=("Arial", 16, "bold"), bg='#2c3e50', fg='#ecf0f1') title.pack(pady=15) # 文件选择区域 - 支持多文件选择 file_frame = tk.LabelFrame(tab, text="选择DLL文件 (可多选)", bg='#2c3e50', fg='#ecf0f1') file_frame.pack(fill=tk.X, padx=20, pady=10) # 使用ScrolledText显示选中的文件列表 self.encrypt_file_listbox = scrolledtext.ScrolledText(file_frame, height=5, bg='#34495e', fg='#ecf0f1', insertbackground='white') self.encrypt_file_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.encrypt_file_listbox.config(state=tk.DISABLED) # 文件操作按钮 btn_frame = tk.Frame(file_frame, bg='#2c3e50') btn_frame.pack(fill=tk.X, pady=5) browse_btn = tk.Button(btn_frame, text="添加文件...", command=self.browse_encrypt_files, bg='#3498db', fg='white') browse_btn.pack(side=tk.LEFT, padx=5) clear_btn = tk.Button(btn_frame, text="清空列表", command=self.clear_encrypt_file_list, bg='#e74c3c', fg='white') clear_btn.pack(side=tk.LEFT, padx=5) # 加密选项区域 options_frame = tk.LabelFrame(tab, text="加密选项", bg='#2c3e50', fg='#ecf0f1') options_frame.pack(fill=tk.X, padx=20, pady=10) tk.Label(options_frame, text="加密强度:", bg='#2c3e50', fg='#ecf0f1').grid(row=0, column=0, padx=5, pady=5, sticky=tk.W) self.encryption_level = tk.StringVar(value="AES-256") levels = ["AES-128", "AES-192", "AES-256", "Blowfish", "Twofish"] level_menu = ttk.Combobox(options_frame, textvariable=self.encryption_level, values=levels, state="readonly", width=15) level_menu.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W) tk.Label(options_frame, text="输出目录:", bg='#2c3e50', fg='#ecf0f1').grid(row=1, column=0, padx=5, pady=5, sticky=tk.W) self.encrypt_output_dir = tk.StringVar(value=os.path.join(os.path.expanduser("~"), "encrypted")) output_entry = tk.Entry(options_frame, textvariable=self.encrypt_output_dir, width=50) output_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W) browse_dir_btn = tk.Button(options_frame, text="浏览...", command=self.browse_encrypt_output_dir, bg='#3498db', fg='white') browse_dir_btn.grid(row=1, column=2, padx=5, pady=5) # 加密按钮 encrypt_btn = tk.Button(tab, text="批量加密文件", command=self.encrypt_files, bg='#2ecc71', fg='white', font=("Arial", 12), height=2, width=20) encrypt_btn.pack(pady=20) # 状态显示 self.encrypt_status = tk.Label(tab, text="", bg='#2c3e50', fg='#e74c3c') self.encrypt_status.pack(pady=10) def create_obfuscate_tab(self): tab = self.obfuscate_tab # 标题 title = tk.Label(tab, text="代码混淆", font=("Arial", 16, "bold"), bg='#2c3e50', fg='#ecf0f1') title.pack(pady=15) # 文件选择区域 - 支持多文件选择 file_frame = tk.LabelFrame(tab, text="选择DLL文件 (可多选)", bg='#2c3e50', fg='#ecf0f1') file_frame.pack(fill=tk.X, padx=20, pady=10) # 使用ScrolledText显示选中的文件列表 self.obfuscate_file_listbox = scrolledtext.ScrolledText(file_frame, height=5, bg='#34495e', fg='#ecf0f1', insertbackground='white') self.obfuscate_file_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.obfuscate_file_listbox.config(state=tk.DISABLED) # 文件操作按钮 btn_frame = tk.Frame(file_frame, bg='#2c3e50') btn_frame.pack(fill=tk.X, pady=5) browse_btn = tk.Button(btn_frame, text="添加文件...", command=self.browse_obfuscate_files, bg='#3498db', fg='white') browse_btn.pack(side=tk.LEFT, padx=5) clear_btn = tk.Button(btn_frame, text="清空列表", command=self.clear_obfuscate_file_list, bg='#e74c3c', fg='white') clear_btn.pack(side=tk.LEFT, padx=5) # 混淆选项 options_frame = tk.LabelFrame(tab, text="混淆设置", bg='#2c3e50', fg='#ecf0f1') options_frame.pack(fill=tk.X, padx=20, pady=10) # 混淆方法 tk.Label(options_frame, text="混淆方法:", bg='#2c3e50', fg='#ecf0f1').grid(row=0, column=0, padx=5, pady=5, sticky=tk.W) self.obf_method = tk.StringVar(value="名称混淆") methods = ["名称混淆", "控制流混淆", "字符串加密", "指令替换", "全混淆模式"] method_menu = ttk.Combobox(options_frame, textvariable=self.obf_method, values=methods, state="readonly", width=15) method_menu.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W) method_menu.bind("<<ComboboxSelected>>", self.update_preview) # 混淆强度 tk.Label(options_frame, text="混淆强度:", bg='#2c3e50', fg='#ecf0f1').grid(row=1, column=0, padx=5, pady=5, sticky=tk.W) self.obf_strength = tk.IntVar(value=5) strength_scale = tk.Scale(options_frame, variable=self.obf_strength, from_=1, to=10, orient=tk.HORIZONTAL, bg='#2c3e50', fg='#ecf0f1', highlightbackground='#2c3e50', command=lambda e: self.update_preview()) strength_scale.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W) # 输出目录 tk.Label(options_frame, text="输出目录:", bg='#2c3e50', fg='#ecf0f1').grid(row=2, column=0, padx=5, pady=5, sticky=tk.W) self.obfuscate_output_dir = tk.StringVar(value=os.path.join(os.path.expanduser("~"), "obfuscated")) output_entry = tk.Entry(options_frame, textvariable=self.obfuscate_output_dir, width=50) output_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W) browse_dir_btn = tk.Button(options_frame, text="浏览...", command=self.browse_obfuscate_output_dir, bg='#3498db', fg='white') browse_dir_btn.grid(row=2, column=2, padx=5, pady=5) # 混淆按钮 obfuscate_btn = tk.Button(tab, text="批量混淆文件", command=self.obfuscate_files, bg='#9b59b6', fg='white', font=("Arial", 12), height=2, width=20) obfuscate_btn.pack(pady=20) # 混淆预览 preview_frame = tk.LabelFrame(tab, text="混淆预览", bg='#2c3e50', fg='#ecf0f1') preview_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) self.preview_text = tk.Text(preview_frame, height=10, bg='#34495e', fg='#ecf0f1', insertbackground='white') self.preview_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # 设置初始预览 self.update_preview() def create_license_tab(self): tab = self.license_tab # 标题 title = tk.Label(tab, text="授权管理系统", font=("Arial", 16, "bold"), bg='#2c3e50', fg='#ecf0f1') title.pack(pady=15) # 授权信息区域 info_frame = tk.LabelFrame(tab, text="授权信息", bg='#2c3e50', fg='#ecf0f1') info_frame.pack(fill=tk.X, padx=20, pady=10) tk.Label(info_frame, text="授权密钥:", bg='#2c3e50', fg='#ecf0f1').grid(row=0, column=0, padx=5, pady=5, sticky=tk.W) self.license_entry = tk.Entry(info_frame, width=50) self.license_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W) generate_btn = tk.Button(info_frame, text="生成密钥", command=self.generate_license, bg='#3498db', fg='white') generate_btn.grid(row=0, column=2, padx=5, pady=5) # 机器码输入 tk.Label(info_frame, text="机器码:", bg='#2c3e50', fg='#ecf0f1').grid(row=1, column=0, padx=5, pady=5, sticky=tk.W) self.machine_id_var = tk.StringVar() # 提供默认值作为示例 self.machine_id_var.set("输入机器码,如: 2A3B4C5D6E7F8G9H") machine_entry = tk.Entry(info_frame, textvariable=self.machine_id_var, width=50, fg='#95a5a6') machine_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W) # 添加绑定当前机器按钮 bind_current_btn = tk.Button(info_frame, text="绑定当前机器", command=self.bind_current_machine, bg='#9b59b6', fg='white') bind_current_btn.grid(row=1, column=2, padx=5, pady=5) tk.Label(info_frame, text="授权类型:", bg='#2c3e50', fg='#ecf0f1').grid(row=2, column=0, padx=5, pady=5, sticky=tk.W) self.license_type = tk.StringVar(value="永久") license_frame = tk.Frame(info_frame, bg='#2c3e50') license_frame.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W) # 永久授权单选按钮 permanent_radio = tk.Radiobutton(license_frame, text="永久授权", variable=self.license_type, value="永久", bg='#2c3e50', fg='#ecf0f1', selectcolor='#34495e') permanent_radio.pack(side=tk.LEFT, padx=10) # 试用期单选按钮 trial_radio = tk.Radiobutton(license_frame, text="试用期", variable=self.license_type, value="试用期", bg='#2c3e50', fg='#ecf0f1', selectcolor='#34495e') trial_radio.pack(side=tk.LEFT, padx=10) # 试用期天数输入框 self.trial_days = tk.StringVar(value="3") self.trial_days_entry = tk.Entry(license_frame, textvariable=self.trial_days, width=5, state=tk.NORMAL) self.trial_days_entry.pack(side=tk.LEFT, padx=5) # 添加天数标签 tk.Label(license_frame, text="天", bg='#2c3e50', fg='#ecf0f1').pack(side=tk.LEFT) # 绑定授权类型改变事件 self.license_type.trace_add("write", self.update_license_type_ui) # 授权功能区域 func_frame = tk.LabelFrame(tab, text="授权功能", bg='#2c3e50', fg='#ecf0f1') func_frame.pack(fill=tk.X, padx=20, pady=10) bind_btn = tk.Button(func_frame, text="绑定机器", command=self.bind_to_machine, bg='#e67e22', fg='white', width=15) bind_btn.grid(row=0, column=0, padx=10, pady=10) embed_btn = tk.Button(func_frame, text="嵌入授权", command=self.embed_license, bg='#1abc9c', fg='white', width=15) embed_btn.grid(row=0, column=1, padx=10, pady=10) check_btn = tk.Button(func_frame, text="检查授权", command=self.check_license, bg='#f1c40f', fg='white', width=15) check_btn.grid(row=0, column=2, padx=10, pady=10) # 新增使用功能按钮 use_feature_btn = tk.Button(func_frame, text="使用功能", command=self.use_feature, bg='#3498db', fg='white', width=15) use_feature_btn.grid(row=0, column=3, padx=10, pady=10) # 授权日志 log_frame = tk.LabelFrame(tab, text="授权日志", bg='#2c3e50', fg='#ecf0f1') log_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) self.log_text = tk.Text(log_frame, height=10, bg='#34495e', fg='#ecf0f1', insertbackground='white') self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.log_text.insert(tk.END, "系统启动...\n") self.log_text.insert(tk.END, "就绪\n") self.log_text.config(state=tk.DISABLED) def browse_encrypt_files(self): file_paths = filedialog.askopenfilenames( title="选择DLL文件", filetypes=[("DLL Files", "*.dll"), ("All Files", "*.*")] ) if file_paths: self.encrypt_files = list(file_paths) self.update_encrypt_file_list() self.status_var.set(f"已添加 {len(file_paths)} 个加密文件") def browse_obfuscate_files(self): file_paths = filedialog.askopenfilenames( title="选择DLL文件", filetypes=[("DLL Files", "*.dll"), ("All Files", "*.*")] ) if file_paths: self.obfuscate_files = list(file_paths) self.update_obfuscate_file_list() self.status_var.set(f"已添加 {len(file_paths)} 个混淆文件") def browse_encrypt_output_dir(self): dir_path = filedialog.askdirectory(title="选择输出目录") if dir_path: self.encrypt_output_dir.set(dir_path) def browse_obfuscate_output_dir(self): dir_path = filedialog.askdirectory(title="选择输出目录") if dir_path: self.obfuscate_output_dir.set(dir_path) def clear_encrypt_file_list(self): self.encrypt_files = [] self.update_encrypt_file_list() self.status_var.set("加密文件列表已清空") def clear_obfuscate_file_list(self): self.obfuscate_files = [] self.update_obfuscate_file_list() self.status_var.set("混淆文件列表已清空") def update_encrypt_file_list(self): self.encrypt_file_listbox.config(state=tk.NORMAL) self.encrypt_file_listbox.delete(1.0, tk.END) if self.encrypt_files: for i, file_path in enumerate(self.encrypt_files, 1): self.encrypt_file_listbox.insert(tk.END, f"{i}. {file_path}\n") else: self.encrypt_file_listbox.insert(tk.END, "没有选择文件\n") self.encrypt_file_listbox.insert(tk.END, "请点击'添加文件'按钮选择DLL文件") self.encrypt_file_listbox.config(state=tk.DISABLED) def update_obfuscate_file_list(self): self.obfuscate_file_listbox.config(state=tk.NORMAL) self.obfuscate_file_listbox.delete(1.0, tk.END) if self.obfuscate_files: for i, file_path in enumerate(self.obfuscate_files, 1): self.obfuscate_file_listbox.insert(tk.END, f"{i}. {file_path}\n") else: self.obfuscate_file_listbox.insert(tk.END, "没有选择文件\n") self.obfuscate_file_listbox.insert(tk.END, "请点击'添加文件'按钮选择DLL文件") self.obfuscate_file_listbox.config(state=tk.DISABLED) def simple_aes_encrypt(self, data, key): """简单的AES加密实现""" key_hash = hashlib.sha256(key).digest() iv = os.urandom(16) cipher = hashlib.pbkdf2_hmac('sha256', key_hash, iv, 100000, dklen=32) encrypted = bytearray() for i in range(len(data)): encrypted.append(data[i] ^ cipher[i % len(cipher)]) return iv + bytes(encrypted) def encrypt_files(self): if not self.encrypt_files: messagebox.showerror("错误", "请先选择至少一个DLL文件") return output_dir = self.encrypt_output_dir.get() if not output_dir: messagebox.showerror("错误", "请指定输出目录") return # 确保输出目录存在 if not os.path.exists(output_dir): os.makedirs(output_dir) try: # 创建加密子目录 encrypted_dir = os.path.join(output_dir, "encrypted") if not os.path.exists(encrypted_dir): os.makedirs(encrypted_dir) encryption_method = self.encryption_level.get() success_count = 0 self.encrypt_status.config(text="批量加密中...", fg='#f39c12') self.root.update() for file_path in self.encrypt_files: try: # 获取原文件名 base_name = os.path.basename(file_path) # 生成输出路径 (在encrypted子目录下,使用原文件名) output_path = os.path.join(encrypted_dir, base_name) # 生成加密密钥 key = os.urandom(32) # 读取文件内容 with open(file_path, 'rb') as f: data = f.read() # 加密数据 encrypted_data = self.simple_aes_encrypt(data, key) # 保存加密后的文件 with open(output_path, 'wb') as f: f.write(encrypted_data) # 保存密钥 key_file = os.path.join(encrypted_dir, f"{base_name}.key") with open(key_file, 'wb') as f: f.write(key) success_count += 1 self.log_action(f"已加密: {base_name} -> {output_path}") except Exception as e: self.log_action(f"加密失败 {os.path.basename(file_path)}: {str(e)}") self.encrypt_status.config( text=f"批量加密完成!成功: {success_count}/{len(self.encrypt_files)} 个文件", fg='#2ecc71' if success_count > 0 else '#e74c3c' ) self.status_var.set( f"批量加密完成 - 成功: {success_count}/{len(self.encrypt_files)}" ) if success_count > 0: messagebox.showinfo( "批量加密完成", f"成功加密 {success_count} 个文件\n输出目录: {encrypted_dir}" ) else: messagebox.showerror( "加密失败", "所有文件加密失败,请查看日志" ) except Exception as e: messagebox.showerror("加密错误", str(e)) self.encrypt_status.config(text="批量加密失败", fg='#e74c3c') def update_preview(self, event=None): """根据混淆设置更新预览""" method = self.obf_method.get() strength = self.obf_strength.get() self.preview_text.config(state=tk.NORMAL) self.preview_text.delete(1.0, tk.END) # 原始代码示例 self.preview_text.insert(tk.END, "// 原始代码示例\n") self.preview_text.insert(tk.END, "public int Calculate(int a, int b) {\n") self.preview_text.insert(tk.END, " return a * b + 10;\n") self.preview_text.insert(tk.END, "}\n\n") # 混淆后代码示例 self.preview_text.insert(tk.END, f"// 混淆后代码示例 ({method}, 强度: {strength}/10)\n") # 根据混淆方法和强度生成不同的混淆代码 if method == "名称混淆": self.preview_text.insert(tk.END, f"public int {self.generate_obf_name('Calculate', strength)}(int {self.generate_obf_name('a', strength)}, int {self.generate_obf_name('b', strength)}) {{\n") self.preview_text.insert(tk.END, f" return {self.generate_obf_name('a', strength)} * {self.generate_obf_name('b', strength)} + 10;\n") self.preview_text.insert(tk.END, "}\n") elif method == "控制流混淆": self.preview_text.insert(tk.END, "public int Calculate(int a, int b) {\n") self.preview_text.insert(tk.END, " int result;\n") self.preview_text.insert(tk.END, " if (a > 0) {\n") if strength > 5: self.preview_text.insert(tk.END, " int temp = b;\n") self.preview_text.insert(tk.END, " for (int i = 0; i < 1; i++) {\n") self.preview_text.insert(tk.END, " temp = a * temp;\n") self.preview_text.insert(tk.END, " }\n") self.preview_text.insert(tk.END, " result = temp + 10;\n") else: self.preview_text.insert(tk.END, " result = a * b + 10;\n") self.preview_text.insert(tk.END, " } else {\n") self.preview_text.insert(tk.END, " result = b * a + 10;\n") self.preview_text.insert(tk.END, " }\n") self.preview_text.insert(tk.END, " return result;\n") self.preview_text.insert(tk.END, "}\n") elif method == "字符串加密": self.preview_text.insert(tk.END, "public int Calculate(int a, int b) {\n") self.preview_text.insert(tk.END, " // 字符串被加密\n") self.preview_text.insert(tk.END, " string debugInfo = DecryptString(\"0x4A3F2B1C\");\n") self.preview_text.insert(tk.END, " return a * b + 10;\n") self.preview_text.insert(tk.END, "}\n") elif method == "指令替换": self.preview_text.insert(tk.END, "public int Calculate(int a, int b) {\n") self.preview_text.insert(tk.END, " // 指令被替换\n") if strength > 7: self.preview_text.insert(tk.END, " int result = (a << 2) - a + b * 3 + 10;\n") else: self.preview_text.insert(tk.END, " int result = a * b + 10;\n") self.preview_text.insert(tk.END, " return result;\n") self.preview_text.insert(tk.END, "}\n") else: # 全混淆模式 self.preview_text.insert(tk.END, f"public int {self.generate_obf_name('Calculate', strength)}(int {self.generate_obf_name('a', strength)}, int {self.generate_obf_name('b', strength)}) {{\n") self.preview_text.insert(tk.END, " // 全混淆模式\n") self.preview_text.insert(tk.END, " int result;\n") self.preview_text.insert(tk.END, " if (a > 0) {\n") self.preview_text.insert(tk.END, " result = a * b + 10;\n") self.preview_text.insert(tk.END, " } else {\n") self.preview_text.insert(tk.END, " result = b * a + 10;\n") self.preview_text.insert(tk.END, " }\n") self.preview_text.insert(tk.END, " // 添加垃圾指令\n") self.preview_text.insert(tk.END, " int unused = 0;\n") self.preview_text.insert(tk.END, " for (int i = 0; i < 10; i++) {\n") self.preview_text.insert(tk.END, " unused += i;\n") self.preview_text.insert(tk.END, " }\n") self.preview_text.insert(tk.END, " return result;\n") self.preview_text.insert(tk.END, "}\n") self.preview_text.config(state=tk.DISABLED) def generate_obf_name(self, base_name, strength): """生成混淆后的名称""" # 根据混淆强度增加名称的复杂度 prefix = "obf_" if strength < 5 else "mangled_" suffix = f"_{random.randint(100, 999)}" if strength > 3 else "" # 高混淆强度使用随机字符串 if strength > 7: return ''.join(random.choices(string.ascii_letters, k=8)) return f"{prefix}{base_name}{suffix}" def obfuscate_files(self): if not self.obfuscate_files: messagebox.showerror("错误", "请先选择至少一个DLL文件") return output_dir = self.obfuscate_output_dir.get() if not output_dir: messagebox.showerror("错误", "请指定输出目录") return # 确保输出目录存在 if not os.path.exists(output_dir): os.makedirs(output_dir) try: # 获取混淆设置 method = self.obf_method.get() strength = self.obf_strength.get() success_count = 0 # 创建结果显示窗口 result_window = tk.Toplevel(self.root) result_window.title("混淆处理结果") result_window.geometry("400x300") result_window.resizable(False, False) result_window.transient(self.root) result_window.grab_set() # 创建结果显示文本区域 result_frame = tk.Frame(result_window) result_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) result_label = tk.Label(result_frame, text="批量混淆完成", font=("Arial", 14, "bold")) result_label.pack(pady=10) result_text = scrolledtext.ScrolledText(result_frame, height=10) result_text.pack(fill=tk.BOTH, expand=True) # 添加处理结果 result_text.insert(tk.END, f"成功处理: 0/{len(self.obfuscate_files)} 个文件\n") result_text.insert(tk.END, "------------------------------------\n") result_text.see(tk.END) result_text.config(state=tk.DISABLED) # 处理文件 for idx, file_path in enumerate(self.obfuscate_files): try: # 获取原文件名 base_name = os.path.basename(file_path) # 生成输出路径 (使用原文件名) output_path = os.path.join(output_dir, base_name) # 模拟混淆过程 self.log_action(f"开始混淆: {base_name}") self.log_action(f"混淆方法: {method}, 强度: {strength}/10") # 这里应该是实际的混淆代码 # 为了演示,我们只是复制文件并添加日志 shutil.copy(file_path, output_path) self.log_action(f"混淆完成! 输出文件: {output_path}") success_count += 1 # 更新结果窗口 result_text.config(state=tk.NORMAL) result_text.insert(tk.END, f"成功: {base_name}\n") result_text.see(tk.END) result_text.config(state=tk.DISABLED) result_text.update() except Exception as e: self.log_action(f"混淆失败 {base_name}: {str(e)}") # 更新结果窗口 result_text.config(state=tk.NORMAL) result_text.insert(tk.END, f"失败: {base_name} - {str(e)}\n") result_text.see(tk.END) result_text.config(state=tk.DISABLED) result_text.update() # 更新结果标题 result_label.config(text=f"批量混淆完成! 成功: {success_count}/{len(self.obfuscate_files)}") # 添加确定按钮 ok_btn = tk.Button(result_window, text="确定", width=10, command=result_window.destroy) ok_btn.pack(pady=10) self.status_var.set(f"混淆完成: {success_count}/{len(self.obfuscate_files)}") self.log_action(f"批量混淆完成! 成功处理 {success_count}/{len(self.obfuscate_files)} 个文件") except Exception as e: messagebox.showerror("混淆错误", str(e)) self.log_action(f"批量混淆失败: {str(e)}") def generate_license(self): key = ''.join(random.choices(string.ascii_uppercase + string.digits, k=25)) key = '-'.join([key[i:i+5] for i in range(0, len(key), 5)]) self.license_key = key self.license_entry.delete(0, tk.END) self.license_entry.insert(0, key) self.activation_date = time.time() license_type = self.license_type.get() self.log_action(f"已生成{license_type}授权密钥: {key}") def get_machine_id(self): """获取当前机器标识符""" try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Cryptography") machine_guid, _ = winreg.QueryValueEx(key, "MachineGuid") winreg.CloseKey(key) return hashlib.sha256(machine_guid.encode()).hexdigest()[:16].upper() except Exception: return hashlib.sha256(b"fallback_machine_id").hexdigest()[:16].upper() def bind_current_machine(self): """绑定当前机器""" machine_id = self.get_machine_id() self.machine_id_var.set(machine_id) self.machine_id = machine_id # 保存机器码 self.log_action(f"已获取当前机器码: {machine_id}") def update_license_type_ui(self, *args): """根据选择的授权类型更新UI""" license_type = self.license_type.get() if license_type == "试用期": self.trial_days_entry.config(state=tk.NORMAL) else: self.trial_days_entry.config(state=tk.NORMAL) def bind_to_machine(self): if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return machine_id = self.machine_id_var.get() if not machine_id or machine_id == "输入机器码,如: 2A3B4C5D6E7F8G9H": messagebox.showerror("错误", "请输入有效的机器码") return license_type = self.license_type.get() self.activation_date = time.time() # 重置使用次数 self.usage_count = 0 # 获取授权设置 if license_type == "试用期": try: self.time_limit_days = int(self.trial_days.get()) if self.time_limit_days < 1: messagebox.showerror("错误", "试用期天数必须大于0") return self.expiry_date = self.activation_date + self.time_limit_days * 24 * 3600 except: messagebox.showerror("错误", "请输入有效的试用期天数") return else: # 永久授权 self.expiry_date = None self.time_limit_days = 0 self.permanent_license_shown = False # 重置永久授权显示标记 self.machine_id = machine_id # 保存机器码 self.log_action(f"授权密钥已绑定到机器: {machine_id}") self.log_action(f"授权类型: {license_type}") if license_type == "试用期": expiry_date_str = time.strftime("%Y-%m-%d %H:%M", time.localtime(self.expiry_date)) message = f"试用期授权已绑定\n机器码: {machine_id}\n激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}\n到期时间: {expiry_date_str}\n有效期: {self.time_limit_days}天" else: message = f"永久授权已绑定\n机器码: {machine_id}\n激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}" messagebox.showinfo("成功", message) def generate_license_module(self, output_dir): """生成授权检查模块的Python代码""" license_code = f'''# -*- coding: utf-8 -*- import ctypes import os import sys import time import hashlib import winreg class LicenseManager: def __init__(self): self.license_key = "{self.license_key}" self.machine_id = "{self.machine_id}" self.license_type = "{self.license_type.get()}" self.activation_date = {self.activation_date} self.expiry_date = {self.expiry_date if self.expiry_date else 'None'} # CAD运行时自动检查授权 self.check_license_on_cad_start() def get_current_machine_id(self): """获取当前机器标识符""" try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\\\Microsoft\\\\Cryptography") machine_guid, _ = winreg.QueryValueEx(key, "MachineGuid") winreg.CloseKey(key) return hashlib.sha256(machine_guid.encode()).hexdigest()[:16].upper() except Exception: return hashlib.sha256(b"fallback_machine_id").hexdigest()[:16].upper() def check_license_on_cad_start(self): """CAD启动时自动检查授权""" current_machine_id = self.get_current_machine_id() # 检查机器码是否匹配 if current_machine_id != self.machine_id: self.show_message("授权错误", "机器码不匹配!\\n当前机器: " + current_machine_id) return False # 检查试用期是否过期 if self.license_type == "试用期": current_time = time.time() if current_time > self.expiry_date: self.show_message("授权过期", "试用期已结束!") return False # 显示授权信息 self.show_license_info() return True def show_license_info(self): """显示授权信息""" if self.license_type == "试用期": # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time remaining_days = int(remaining_seconds // (24 * 3600)) remaining_seconds %= (24 * 3600) remaining_hours = int(remaining_seconds // 3600) remaining_seconds %= 3600 remaining_minutes = int(remaining_seconds // 60) message = ( "试用期授权已激活\\n" f"机器码: {self.machine_id}\\n" f"激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}\\n" f"到期时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.expiry_date))}\\n" f"剩余时间: {remaining_days}天 {remaining_hours}小时 {remaining_minutes}分钟" ) self.show_message("授权信息", message) else: message = ( "永久授权已激活\\n" f"机器码: {self.machine_id}\\n" f"激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}" ) self.show_message("授权信息", message) def show_message(self, title, message): """在CAD中显示消息框""" # 使用ctypes创建Windows消息框 ctypes.windll.user32.MessageBoxW(0, message, title, 0) # CAD加载时自动执行 if __name__ == "__main__": license_mgr = LicenseManager() ''' # 保存授权模块 license_path = os.path.join(output_dir, "dll_license_checker.py") with open(license_path, 'w', encoding='utf-8') as f: f.write(license_code) return license_path def embed_license(self): if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return if not self.obfuscate_files: messagebox.showerror("错误", "请先选择要嵌入授权的DLL文件") return try: # 获取输出目录 output_dir = self.obfuscate_output_dir.get() if not output_dir: messagebox.showerror("错误", "请指定输出目录") return # 确保输出目录存在 if not os.path.exists(output_dir): os.makedirs(output_dir) # 生成授权检查模块 license_module_path = self.generate_license_module(output_dir) # 初始化剩余天数 remaining_days = 0 # 模拟嵌入授权信息 license_type = self.license_type.get() machine_id = self.machine_id self.log_action("正在将授权信息嵌入DLL...") self.log_action(f"授权模块已生成: {os.path.basename(license_module_path)}") # 在试用期情况下,正确计算剩余天数 if license_type == "试用期": # 确保有到期时间 if self.expiry_date is None: self.log_action("错误:试用期授权,但到期时间为空!") messagebox.showerror("错误", "试用期授权,但到期时间为空!") return # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 如果剩余秒数小于0,则按0处理 if remaining_seconds < 0: remaining_seconds = 0 # 计算剩余天数 remaining_days = int(remaining_seconds // (24 * 3600)) self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: self.log_action(f"授权类型: {license_type}") if self.activation_date: activation_time = time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date)) self.log_action(f"激活时间: {activation_time}") self.log_action(f"机器码: {machine_id}") # 为每个文件嵌入授权信息 for file_path in self.obfuscate_files: base_name = os.path.basename(file_path) # 在实际应用中,这里应该修改DLL文件嵌入授权信息 # 为演示目的,我们创建一个同名的.lic文件 lic_file = os.path.join(output_dir, f"{base_name}.lic") with open(lic_file, 'w') as f: f.write(f"LicenseKey: {self.license_key}\n") f.write(f"MachineID: {machine_id}\n") f.write(f"Type: {license_type}\n") f.write(f"Activation: {self.activation_date}\n") if self.expiry_date: f.write(f"Expiry: {self.expiry_date}\n") self.log_action(f"已为 {base_name} 创建授权文件: {os.path.basename(lic_file)}") self.log_action("授权信息嵌入完成!") messagebox.showinfo( "成功", f"授权信息已成功嵌入 {len(self.obfuscate_files)} 个DLL文件\n" f"授权检查模块: dll_license_checker.py\n" "在CAD中加载DLL时会自动显示授权信息" ) except Exception as e: messagebox.showerror("嵌入错误", str(e)) def use_feature(self): """使用功能(消耗使用次数)""" if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return if not self.activation_date: messagebox.showwarning("警告", "授权尚未激活,请先绑定机器") return license_type = self.license_type.get() # 检查试用期是否过期 if license_type == "试用期": current_time = time.time() if current_time > self.expiry_date: messagebox.showerror("错误", "试用期已过期!") return # 增加使用次数 self.usage_count += 1 # 显示授权信息弹窗 self.show_license_reminder() self.log_action(f"功能使用成功!使用次数: {self.usage_count}") messagebox.showinfo("成功", "功能使用成功!") def show_license_reminder(self): """显示授权信息弹窗""" license_type = self.license_type.get() if license_type == "试用期": # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 计算剩余天数、小时和分钟 remaining_days = int(remaining_seconds // (24 * 3600)) remaining_seconds %= (24 * 3600) remaining_hours = int(remaining_seconds // 3600) remaining_seconds %= 3600 remaining_minutes = int(remaining_seconds // 60) # 创建弹窗 reminder = tk.Toplevel(self.root) reminder.title("授权信息") reminder.geometry("400x300") reminder.resizable(False, False) reminder.transient(self.root) reminder.grab_set() # 设置背景颜色 bg_color = '#f9f9f9' header_color = '#3498db' text_color = '#2c3e50' warning_color = '#e74c3c' reminder.configure(bg=bg_color) # 创建标题 title_label = tk.Label(reminder, text="试用期授权", font=("Arial", 16, "bold"), bg=header_color, fg='white', padx=10, pady=10) title_label.pack(fill=tk.X) # 创建内容区域 content_frame = tk.Frame(reminder, bg=bg_color, padx=20, pady=20) content_frame.pack(fill=tk.BOTH, expand=True) # 显示机器码 machine_label = tk.Label(content_frame, text=f"机器码: {self.machine_id}", bg=bg_color, fg=text_color, anchor='w', justify='left') machine_label.pack(fill=tk.X, pady=5) # 显示激活时间 activation_label = tk.Label(content_frame, text=f"激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}", bg=bg_color, fg=text_color, anchor='w', justify='left') activation_label.pack(fill=tk.X, pady=5) # 显示到期时间 expiry_label = tk.Label(content_frame, text=f"到期时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.expiry_date))}", bg=bg_color, fg=text_color, anchor='w', justify='left') expiry_label.pack(fill=tk.X, pady=5) # 显示剩余时间 remaining_label = tk.Label(content_frame, text=f"剩余时间: {remaining_days}天 {remaining_hours}小时 {remaining_minutes}分钟", bg=bg_color, fg=warning_color, font=("Arial", 12, "bold"), anchor='w', justify='left') remaining_label.pack(fill=tk.X, pady=10) # 添加确定按钮 ok_btn = tk.Button(reminder, text="确定", width=10, command=reminder.destroy, bg='#3498db', fg='white') ok_btn.pack(pady=10) elif license_type == "永久" and not self.permanent_license_shown: # 创建永久授权弹窗 reminder = tk.Toplevel(self.root) reminder.title("授权信息") reminder.geometry("400x300") reminder.resizable(False, False) reminder.transient(self.root) reminder.grab_set() # 设置背景颜色 bg_color = '#f9f9f9' header_color = '#2ecc71' text_color = '#2c3e50' reminder.configure(bg=bg_color) # 创建标题 title_label = tk.Label(reminder, text="永久授权", font=("Arial", 16, "bold"), bg=header_color, fg='white', padx=10, pady=10) title_label.pack(fill=tk.X) # 创建内容区域 content_frame = tk.Frame(reminder, bg=bg_color, padx=20, pady=20) content_frame.pack(fill=tk.BOTH, expand=True) # 添加成功图标(使用文本模拟) success_icon = tk.Label(content_frame, text="✓", font=("Arial", 48), fg=header_color, bg=bg_color) success_icon.pack(pady=10) # 显示成功消息 success_label = tk.Label(content_frame, text="永久授权已激活", font=("Arial", 14, "bold"), bg=bg_color, fg=text_color) success_label.pack(pady=5) # 显示机器码 machine_label = tk.Label(content_frame, text=f"机器码: {self.machine_id}", bg=bg_color, fg=text_color) machine_label.pack(pady=5) # 显示激活时间 activation_label = tk.Label(content_frame, text=f"激活时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date))}", bg=bg_color, fg=text_color) activation_label.pack(pady=5) # 添加确定按钮 ok_btn = tk.Button(reminder, text="确定", width=10, command=reminder.destroy, bg=header_color, fg='white') ok_btn.pack(pady=10) # 标记永久授权已显示 self.permanent_license_shown = True def check_license(self): if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return if not self.activation_date: messagebox.showwarning("警告", "授权尚未激活,请先绑定机器") return # 获取当前时间 current_time = time.time() license_type = self.license_type.get() activation_time_str = time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date)) self.log_action("正在检查授权状态...") self.log_action(f"授权密钥: {self.license_key}") self.log_action(f"授权类型: {license_type}") self.log_action(f"激活时间: {activation_time_str}") # 根据授权类型检查状态 if license_type == "试用期": # 计算剩余时间 expiry_time = self.expiry_date remaining_seconds = expiry_time - current_time if remaining_seconds <= 0: status = "已过期" self.log_action("授权状态: 已过期") message = f"试用期授权已过期!" else: # 计算剩余天数、小时和分钟 remaining_days = int(remaining_seconds // (24 * 3600)) remaining_seconds %= (24 * 3600) remaining_hours = int(remaining_seconds // 3600) remaining_seconds %= 3600 remaining_minutes = int(remaining_seconds // 60) status = f"有效 (剩余 {remaining_days}天 {remaining_hours}小时 {remaining_minutes}分钟)" self.log_action(f"授权状态: {status}") expiry_date_str = time.strftime("%Y-%m-%d %H:%M", time.localtime(expiry_time)) # 显示总天数 total_days = self.time_limit_days message = f"试用期授权有效\n激活时间: {activation_time_str}\n到期时间: {expiry_date_str}\n总天数: {total_days}天\n剩余时间: {remaining_days}天 {remaining_hours}小时 {remaining_minutes}分钟" else: # 永久授权 status = "永久有效" self.log_action("授权状态: 永久有效") message = "永久授权有效\n激活时间: " + activation_time_str # 显示检查结果 messagebox.showinfo("授权检查", message) def log_action(self, message): self.log_text.config(state=tk.NORMAL) self.log_text.insert(tk.END, message + "\n") self.log_text.see(tk.END) self.log_text.config(state=tk.DISABLED) if __name__ == "__main__": root = tk.Tk() app = DLLProtectorApp(root) root.mainloop() ”授权管理”中的”嵌入授权”按钮按过后显示“name 'remaining days' is not defined
08-01
<think>这个错误提示表明在`embed_license`方法中,变量`remaining_days`在使用前没有被定义。 在`embed_license`方法中,我们尝试在试用期授权的情况下记录剩余天数,但是在非试用期的情况下,`remaining_days`变量并没有被定义。 在代码中,我们尝试在日志中记录`remaining_days`,但是在非试用期的情况下,这个变量并没有被赋值,因此会导致错误。 为了解决这个问题,我们需要确保在非试用期的情况下,`remaining_days`也有一个值。我们可以将其初始化为0,然后在试用期的情况下重新计算。 但是,在`embed_license`方法中,我们实际上在试用期授权的情况下计算了剩余天数,并赋值给`remaining_days`,但是在非试用期的情况下,我们并没有定义这个变量,而在日志记录中我们使用了这个变量。 具体来说,在以下代码中: if license_type == "试用期": ... # 计算remaining_days else: self.log_action(f"授权类型: {license_type}") self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") 在非试用期的情况下,`remaining_days`没有被定义,所以会报错。 我们可以这样修改: 1. 在计算剩余天数之前,先初始化`remaining_days`为0(或者一个默认值)。 2. 然后在试用期的情况下重新计算`remaining_days`。 但是注意,在非试用期的情况下,我们不应该显示剩余天数(因为永久授权没有剩余天数概念),所以我们可以在日志记录时根据授权类型来记录不同的信息。 修改思路: 在试用期的情况下,记录剩余天数;在永久授权的情况下,不记录剩余天数。 因此,我们可以将日志记录放在条件分支中。 修改后的代码片段: if license_type == "试用期": # 确保有到期时间 if self.expiry_date is None: self.log_action("错误:试用期授权,但到期时间为空!") messagebox.showerror("错误", "试用期授权,但到期时间为空!") return # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 如果剩余秒数小于0,则按0处理 if remaining_seconds < 0: remaining_seconds = 0 # 计算剩余天数 remaining_days = int(remaining_seconds // (24 * 3600)) self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: self.log_action(f"授权类型: {license_type}") 这样,在试用期授权时记录剩余天数,在永久授权时只记录类型。 另外,在后续的日志记录中,我们还有一处使用了`remaining_days`(在嵌入每个文件时),但是这里我们并没有在永久授权的情况下定义`remaining_days`,所以也需要调整。 但是,实际上在永久授权的情况下,我们并不需要剩余天数。所以我们可以将剩余天数的显示放在试用期授权的条件下。 然而,在嵌入授权的最后,我们有一个总的日志记录,其中使用了`remaining_days`,但同样只应该在试用期授权时使用。 所以,我建议将整个日志记录调整到条件分支内部,避免在永久授权的情况下使用`remaining_days`。 但是,我们注意到在嵌入授权的最后,我们有一个总的日志记录,其中使用了`remaining_days`,这个日志记录是在循环文件之后,所以我们需要调整这里。 实际上,在嵌入授权的最后,我们并没有使用`remaining_days`,所以可以忽略。 因此,主要问题是在试用期授权计算后的日志记录中,我们错误地在永久授权的情况下使用了`remaining_days`。 我们只需要将这段日志记录移到试用期授权的条件分支内即可。 修改后的代码: if license_type == "试用期": ... # 计算剩余天数 self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: self.log_action(f"授权类型: {license_type}") 这样修改后,在永久授权的情况下就不会尝试使用`remaining_days`变量了。 但是,在嵌入授权的最后,我们还有一条日志记录: self.log_action("授权信息嵌入完成!") 这条日志记录与授权类型无关,所以可以保留。 因此,我们只需要修改上述条件分支即可。 让我们定位到`embed_license`方法中的相关代码,并做上述修改。 注意:原代码中,在试用期授权计算后,我们有一条日志记录,其中包含了`remaining_days`,而在永久授权的情况下,我们只记录类型,然后紧接着又记录了一条包含`remaining_days`的日志(在试用期分支之外),这就是问题所在。 修改后的代码: # 在试用期情况下,正确计算剩余天数 if license_type == "试用期": # 确保有到期时间 if self.expiry_date is None: self.log_action("错误:试用期授权,但到期时间为空!") messagebox.showerror("错误", "试用期授权,但到期时间为空!") return # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 如果剩余秒数小于0,则按0处理 if remaining_seconds < 0: remaining_seconds = 0 # 计算剩余天数 remaining_days = int(remaining_seconds // (24 * 3600)) # 记录日志(包含剩余天数) self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: # 永久授权,记录类型即可 self.log_action(f"授权类型: {license_type}") 这样修改后,在永久授权的情况下就不会出现`remaining_days`未定义的问题了。 但是,在代码中,我们还有一处日志记录在条件分支之后,它试图记录`remaining_days`,但已经移除了。所以现在不会在永久授权的情况下使用`remaining_days`。 另外,在循环中为每个文件创建授权文件时,我们使用了`remaining_days`,但是请注意,这个循环中并没有使用`remaining_days`。我们只是创建了一个.lic文件,其中写入了固定的信息。 所以,我们只需要修改上述条件分支中的日志记录即可。 让我们重新检查`embed_license`方法,确保没有其他地方在永久授权的情况下使用`remaining_days`。 在循环中,我们为每个文件写入的.lic文件内容中,在试用期授权的情况下写入了到期时间,在永久授权的情况下没有写入到期时间。这是正确的,所以没有问题。 因此,我们只需要将条件分支中的日志记录分开即可。 修改后的`embed_license`方法代码片段如下(仅修改条件分支部分):</think>这个错误发生在`embed_license`方法中,当尝试在非试用期授权(如永久授权)的情况下记录`remaining_days`变量时。问题在于`remaining_days`只在试用期授权的代码块中被定义,但在永久授权的情况下没有被定义。 ### 解决方案: 我们需要确保在永久授权的情况下,`remaining_days`也有一个默认值(例如0)。以下是修复后的代码: ```python def embed_license(self): if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return if not self.obfuscate_files: messagebox.showerror("错误", "请先选择要嵌入授权的DLL文件") return try: # 获取输出目录 output_dir = self.obfuscate_output_dir.get() if not output_dir: messagebox.showerror("错误", "请指定输出目录") return # 确保输出目录存在 if not os.path.exists(output_dir): os.makedirs(output_dir) # 生成授权检查模块 license_module_path = self.generate_license_module(output_dir) # 初始化剩余天数(默认为0) remaining_days = 0 # 添加这行初始化 # 模拟嵌入授权信息 license_type = self.license_type.get() machine_id = self.machine_id self.log_action("正在将授权信息嵌入DLL...") self.log_action(f"授权模块已生成: {os.path.basename(license_module_path)}") # 在试用期情况下,正确计算剩余天数 if license_type == "试用期": # 确保有到期时间 if self.expiry_date is None: self.log_action("错误:试用期授权,但到期时间为空!") messagebox.showerror("错误", "试用期授权,但到期时间为空!") return # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 如果剩余秒数小于0,则按0处理 if remaining_seconds < 0: remaining_seconds = 0 # 计算剩余天数 remaining_days = int(remaining_seconds // (24 * 3600)) self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: self.log_action(f"授权类型: {license_type}") if self.activation_date: activation_time = time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date)) self.log_action(f"激活时间: {activation_time}") self.log_action(f"机器码: {machine_id}") # 为每个文件嵌入授权信息 for file_path in self.obfuscate_files: base_name = os.path.basename(file_path) # 在实际应用中,这里应该修改DLL文件嵌入授权信息 # 为演示目的,我们创建一个同名的.lic文件 lic_file = os.path.join(output_dir, f"{base_name}.lic") with open(lic_file, 'w') as f: f.write(f"LicenseKey: {self.license_key}\n") f.write(f"MachineID: {machine_id}\n") f.write(f"Type: {license_type}\n") f.write(f"Activation: {self.activation_date}\n") if self.expiry_date: f.write(f"Expiry: {self.expiry_date}\n") self.log_action(f"已为 {base_name} 创建授权文件: {os.path.basename(lic_file)}") self.log_action("授权信息嵌入完成!") messagebox.showinfo( "成功", f"授权信息已成功嵌入 {len(self.obfuscate_files)} 个DLL文件\n" f"授权检查模块: dll_license_checker.py\n" "在CAD中加载DLL时会自动显示授权信息" ) except Exception as e: messagebox.showerror("嵌入错误", str(e)) ``` ### 修复说明: 1. **添加初始化**:在方法开头添加了 `remaining_days = 0`,确保变量在任何情况下都有定义 2. **保留原有逻辑**:在试用期授权分支中重新赋值 `remaining_days`,保持原有功能不变 3. **错误预防**:这样即使是非试用期授权,也不会再出现 `name 'remaining_days' is not defined` 错误 ### 完整修复后的方法: 下面是完整的修复后的 `embed_license` 方法: ```python def embed_license(self): if not self.license_key: messagebox.showerror("错误", "请先生成授权密钥") return if not self.obfuscate_files: messagebox.showerror("错误", "请先选择要嵌入授权的DLL文件") return try: # 获取输出目录 output_dir = self.obfuscate_output_dir.get() if not output_dir: messagebox.showerror("错误", "请指定输出目录") return # 确保输出目录存在 if not os.path.exists(output_dir): os.makedirs(output_dir) # 生成授权检查模块 license_module_path = self.generate_license_module(output_dir) # 初始化剩余天数(默认为0) remaining_days = 0 # 模拟嵌入授权信息 license_type = self.license_type.get() machine_id = self.machine_id self.log_action("正在将授权信息嵌入DLL...") self.log_action(f"授权模块已生成: {os.path.basename(license_module_path)}") # 在试用期情况下,正确计算剩余天数 if license_type == "试用期": # 确保有到期时间 if self.expiry_date is None: self.log_action("错误:试用期授权,但到期时间为空!") messagebox.showerror("错误", "试用期授权,但到期时间为空!") return # 计算剩余时间 current_time = time.time() remaining_seconds = self.expiry_date - current_time # 如果剩余秒数小于0,则按0处理 if remaining_seconds < 0: remaining_seconds = 0 # 计算剩余天数 remaining_days = int(remaining_seconds // (24 * 3600)) self.log_action(f"授权类型: {license_type}, 天数: {self.time_limit_days}, 剩余天数: {remaining_days}") else: self.log_action(f"授权类型: {license_type}") if self.activation_date: activation_time = time.strftime('%Y-%m-%d %H:%M', time.localtime(self.activation_date)) self.log_action(f"激活时间: {activation_time}") self.log_action(f"机器码: {machine_id}") # 为每个文件嵌入授权信息 for file_path in self.obfuscate_files: base_name = os.path.basename(file_path) # 在实际应用中,这里应该修改DLL文件嵌入授权信息 # 为演示目的,我们创建一个同名的.lic文件 lic_file = os.path.join(output_dir, f"{base_name}.lic") with open(lic_file, 'w') as f: f.write(f"LicenseKey: {self.license_key}\n") f.write(f"MachineID: {machine_id}\n") f.write(f"Type: {license_type}\n") f.write(f"Activation: {self.activation_date}\n") if self.expiry_date: f.write(f"Expiry: {self.expiry_date}\n") self.log_action(f"已为 {base_name} 创建授权文件: {os.path.basename(lic_file)}") self.log_action("授权信息嵌入完成!") messagebox.showinfo( "成功", f"授权信息已成功嵌入 {len(self.obfuscate_files)} 个DLL文件\n" f"授权检查模块: dll_license_checker.py\n" "在CAD中加载DLL时会自动显示授权信息" ) except Exception as e: messagebox.showerror("嵌入错误", str(e)) ``` 这个修复确保在永久授权的情况下,`remaining_days`变量有默认值0,从而避免了"name 'remaining_days' is not defined"错误。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值