Skip to content

Commit 9f87d59

Browse files
committed
up
1 parent 1233f8d commit 9f87d59

6 files changed

Lines changed: 121 additions & 28 deletions

File tree

.idea/.gitignore

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/Windows-OOBE-Inject.iml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/profiles_settings.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inject.py

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import threading
55
import os
66
import sys
7+
import locale
8+
9+
COMMAND_TIMEOUT = 300
710

811

912
class BatRunnerApp:
@@ -16,15 +19,35 @@ def __init__(self, root):
1619
self.lines = []
1720
self.running = False
1821
self.current_row = -1
22+
self.has_failure = False
23+
self.encoding = locale.getpreferredencoding(False) or "utf-8"
1924
if getattr(sys, 'frozen', False):
2025
self.script_dir = os.path.dirname(sys.executable)
2126
else:
2227
self.script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
2328
self.inject_path = os.path.join(self.script_dir, "inject.txt")
2429

2530
self._build_ui()
31+
self.root.protocol("WM_DELETE_WINDOW", self._on_close)
2632
self.root.after(100, self._auto_load_and_run)
2733

34+
def _on_close(self):
35+
self.running = False
36+
self._safe_destroy()
37+
38+
def _safe_after(self, delay, func, *args):
39+
try:
40+
if self.root.winfo_exists():
41+
self.root.after(delay, func, *args)
42+
except tk.TclError:
43+
pass
44+
45+
def _safe_destroy(self):
46+
try:
47+
self.root.destroy()
48+
except tk.TclError:
49+
pass
50+
2851
def _build_ui(self):
2952
container = ttk.Frame(self.root)
3053
container.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
@@ -61,16 +84,26 @@ def _load_inject(self):
6184
self.status_var.set(f"未找到 inject.txt: {self.inject_path}")
6285
return False
6386

64-
with open(self.inject_path, "r", encoding="gbk", errors="replace") as f:
65-
self.lines = f.readlines()
87+
try:
88+
with open(self.inject_path, "r", encoding=self.encoding, errors="replace") as f:
89+
self.lines = f.readlines()
90+
except OSError as e:
91+
self.status_var.set(f"读取失败: {e}")
92+
return False
6693

6794
for item in self.tree.get_children():
6895
self.tree.delete(item)
6996

7097
for i, line in enumerate(self.lines, 1):
7198
stripped = line.strip()
72-
if stripped and not stripped.startswith("@") and not stripped.lower().startswith("rem"):
73-
self.tree.insert("", tk.END, iid=str(i), values=("⏳", stripped))
99+
if not stripped:
100+
continue
101+
if stripped.startswith("@") or stripped.startswith("::"):
102+
continue
103+
first_word = stripped.split(None, 1)[0].lower()
104+
if first_word == "rem":
105+
continue
106+
self.tree.insert("", tk.END, iid=str(i), values=("⏳", stripped))
74107

75108
self.progress["value"] = 0
76109
self.status_var.set(f"已加载 inject.txt,共 {len(self.lines)} 行")
@@ -87,71 +120,91 @@ def _run(self):
87120
self.status_var.set("inject.txt 为空或未加载")
88121
return
89122

123+
items = self.tree.get_children()
124+
if not items:
125+
self.status_var.set("没有可执行的命令")
126+
return
127+
128+
tasks = []
129+
for item_id in items:
130+
values = self.tree.item(item_id, "values")
131+
tasks.append((item_id, values[1]))
132+
self.tree.item(item_id, values=("⏳", *values[1:]))
133+
90134
self.running = True
135+
self.has_failure = False
91136
self.current_row = -1
92137
self._set_output("")
93138

94-
for item in self.tree.get_children():
95-
self.tree.item(item, values=(self.tree.item(item, "values")[0].replace("✅", "⏳").replace("❌", "⏳"), *self.tree.item(item, "values")[1:]))
96-
97-
total = len(self.tree.get_children())
139+
total = len(tasks)
98140
self.progress["maximum"] = total
99141
self.progress["value"] = 0
100142

101-
threading.Thread(target=self._execute, daemon=True).start()
143+
threading.Thread(target=self._execute, args=(tasks,), daemon=True).start()
102144

103-
def _execute(self):
104-
items = self.tree.get_children()
105-
total = len(items)
145+
def _execute(self, tasks):
146+
total = len(tasks)
106147

107-
for idx, item_id in enumerate(items):
148+
for idx, (item_id, command) in enumerate(tasks):
108149
if not self.running:
109150
break
110151

111-
values = self.tree.item(item_id, "values")
112-
command = values[1]
113-
self.root.after(0, self._highlight_row, item_id)
152+
self._safe_after(0, self._highlight_row, item_id, command)
114153

115154
try:
116155
result = subprocess.run(
117156
command,
118157
shell=True,
119158
capture_output=True,
120159
text=True,
121-
encoding="gbk",
160+
encoding=self.encoding,
122161
errors="replace",
123-
timeout=60,
162+
timeout=COMMAND_TIMEOUT,
124163
cwd=self.script_dir,
125164
)
126165
success = result.returncode == 0
127-
output = result.stdout + result.stderr
166+
output = (result.stdout or "") + (result.stderr or "")
128167
except subprocess.TimeoutExpired:
129168
success = False
130-
output = "执行超时(60秒)"
169+
output = f"执行超时({COMMAND_TIMEOUT})"
131170
except Exception as e:
132171
success = False
133172
output = str(e)
134173

174+
if not success:
175+
self.has_failure = True
176+
135177
status_icon = "✅" if success else "❌"
136-
self.root.after(0, self._update_row, item_id, status_icon, output)
137-
self.root.after(0, self._update_progress, idx + 1, total)
178+
self._safe_after(0, self._update_row, item_id, command, status_icon, output)
179+
self._safe_after(0, self._update_progress, idx + 1, total)
138180

139181
self.running = False
140-
self.root.after(0, lambda: self.status_var.set("执行完成,即将退出..."))
141-
self.root.after(1500, self.root.destroy)
182+
self._safe_after(0, self._finalize)
183+
184+
def _finalize(self):
185+
if self.has_failure:
186+
self.status_var.set("执行完成(含失败项),10 秒后退出")
187+
self._safe_after(10000, self._safe_destroy)
188+
else:
189+
self.status_var.set("执行完成,即将退出...")
190+
self._safe_after(1500, self._safe_destroy)
142191

143-
def _highlight_row(self, item_id):
192+
def _highlight_row(self, item_id, command):
193+
if not self.tree.exists(item_id):
194+
return
144195
self.tree.selection_set(item_id)
145196
self.tree.see(item_id)
146197
values = self.tree.item(item_id, "values")
147198
self.tree.item(item_id, values=("▶", *values[1:]))
148-
self.status_var.set(f"正在执行: {values[1]}")
199+
self.status_var.set(f"正在执行: {command}")
149200

150-
def _update_row(self, item_id, status_icon, output):
201+
def _update_row(self, item_id, command, status_icon, output):
202+
if not self.tree.exists(item_id):
203+
return
151204
values = self.tree.item(item_id, "values")
152205
self.tree.item(item_id, values=(status_icon, *values[1:]))
153206
if output.strip():
154-
self._append_output(f"{values[1]}\n{output.strip()}\n{'─' * 40}\n")
207+
self._append_output(f"{command}\n{output.strip()}\n{'─' * 40}\n")
155208

156209
def _update_progress(self, current, total):
157210
self.progress["value"] = current

0 commit comments

Comments
 (0)