1+ import os
2+ import configparser
3+ import subprocess
4+ import logging
5+ from concurrent .futures import ThreadPoolExecutor , as_completed
6+ from tqdm import tqdm
7+ import time
8+ import tkinter as tk
9+ from tkinter import messagebox
10+
11+ # 设置日志记录
12+ logging .basicConfig (
13+ filename = 'signature.log' ,
14+ filemode = 'w' ,
15+ level = logging .INFO ,
16+ format = '%(asctime)s - %(levelname)s - %(message)s'
17+ )
18+
19+ # 读取配置文件
20+ config = configparser .ConfigParser ()
21+ config .read ('config.ini' , encoding = 'utf-8' )
22+ settings = config ['Settings' ]
23+
24+ # 提取配置信息
25+ cert_path = settings ['cert_path' ]
26+ cert_password = settings ['cert_password' ]
27+ timestamp_url = settings .get ('timestamp_url' , '' )
28+ signing_algorithm = settings ['signing_algorithm' ]
29+ hash_algorithm = settings ['hash_algorithm' ]
30+ root_dir = settings ['root_dir' ]
31+ use_timestamp = settings .getboolean ('use_timestamp' , True )
32+ file_extensions = tuple (ext .strip () for ext in settings ['file_extensions' ].split (',' ) if ext .strip ())
33+ thread_count = settings .getint ('thread_count' , fallback = 0 )
34+
35+
36+ # 使用signtool进行签名的函数
37+ def sign_file (file_path ):
38+ # 构建signtool签名命令
39+ command = [
40+ 'signtool' , 'sign' , '/f' , cert_path , '/p' , cert_password ,
41+ '/fd' , hash_algorithm , '/a' , file_path
42+ ]
43+
44+ # 如果需要时间戳,添加相关参数
45+ if use_timestamp and timestamp_url :
46+ command .extend (['/tr' , timestamp_url , '/td' , signing_algorithm ])
47+
48+ try :
49+ logging .info (f"开始对文件进行签名: { file_path } " )
50+ subprocess .check_call (command , stdout = subprocess .DEVNULL , stderr = subprocess .STDOUT )
51+ logging .info (f"已成功签名: { file_path } " )
52+ return True
53+ except subprocess .CalledProcessError as e :
54+ logging .error (f"无法签名 { file_path } : { e } " )
55+ return False
56+ except Exception as e :
57+ logging .exception (f"签名时发生意外错误 { file_path } : { e } " )
58+ return False
59+
60+ # 这个函数会为文件夹中的每个特定扩展名的文件调用签名命令
61+ def sign_files_in_directory (directory , extensions ):
62+ for root , _ , files in os .walk (directory ):
63+ for file in files :
64+ if file .endswith (extensions ):
65+ yield os .path .join (root , file )
66+
67+ # 用于弹窗提醒的函数
68+ def show_completion_message ():
69+ root = tk .Tk ()
70+ root .withdraw () # 隐藏主窗口
71+ messagebox .showinfo ("完成" , "签名已完成" )
72+ root .destroy ()
73+
74+ # 创建文件路径列表
75+ files_to_sign = list (sign_files_in_directory (root_dir , file_extensions ))
76+
77+ # 设置进度条的格式
78+ bar_format = "{l_bar}{bar}{n_fmt}/{total_fmt} [已用时间:{elapsed}, 剩余时间:{remaining}, 签名速度:{rate_fmt}]"
79+
80+ # 初始化进度条
81+ progress_bar = tqdm (total = len (files_to_sign ), desc = "签名中,请稍候" , unit = "file" , bar_format = bar_format )
82+
83+ # 记录开始时间
84+ start_time = time .time ()
85+
86+ # 使用一个线程池执行签名
87+ with ThreadPoolExecutor (max_workers = None if thread_count == 0 else thread_count ) as executor :
88+ # 提交签名任务到线程池
89+ futures_to_file = {executor .submit (sign_file , file_path ): file_path for file_path in files_to_sign }
90+
91+ # 处理完成的任务,并更新进度条
92+ for future in as_completed (futures_to_file ):
93+ _ = futures_to_file [future ]
94+ elapsed = int (time .time () - start_time )
95+ progress_bar .set_postfix_str (f"总共:{ progress_bar .total } " )
96+ progress_bar .update (1 ) # 在此处更新进度条
97+
98+ # 关闭进度条
99+ progress_bar .close ()
100+
101+ # 所有文件签名完成后,显示完成消息
102+ show_completion_message ()
0 commit comments