-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstaller.py
More file actions
232 lines (191 loc) · 9.1 KB
/
Copy pathinstaller.py
File metadata and controls
232 lines (191 loc) · 9.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import ctypes
import winreg
import os
import sys
import shutil
import tkinter as tk
from tkinter import messagebox
# Enable DPI awareness for high-resolution displays
try:
ctypes.windll.shcore.SetProcessDpiAwarenessContext(-2)
except (AttributeError, OSError):
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1)
except (AttributeError, OSError):
try:
ctypes.windll.user32.SetProcessDPIAware()
except (AttributeError, OSError):
pass
# Application constants
WINDOW_WIDTH = 700
WINDOW_HEIGHT = 760
class Installer:
"""Windows installer for Hash Verifier application.
Copies HashVerifier.exe to Program Files and registers a Windows Explorer
context menu entry for all files. Requires administrator privileges.
"""
def __init__(self):
"""Initialize installer and elevate to administrator if needed."""
if not self.is_admin():
self.run_as_admin()
sys.exit(0)
self.window = tk.Tk()
self.window.title("Hash Verifier Installer (github/mirbyte)")
self.window.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}")
self.window.resizable(True, True)
self.install_dir = r"C:\Program Files\HashVerifier"
self.current_dir = self.get_current_dir()
self.hash_verifier_source = os.path.join(self.current_dir, "HashVerifier.exe")
self.setup_gui()
def get_current_dir(self):
"""Get the directory containing the installer executable.
Returns:
Absolute path to installer directory
"""
if getattr(sys, 'frozen', False):
# Running as compiled executable
return os.path.dirname(sys.executable)
# Running as Python script
return os.path.dirname(os.path.abspath(__file__))
def is_admin(self):
"""Check if process has administrator privileges.
Returns:
True if running as administrator, False otherwise
"""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except AttributeError:
return False
def run_as_admin(self):
"""Relaunch the installer with administrator privileges via UAC prompt.
Raises:
SystemExit: Always exits after triggering elevation
"""
try:
if getattr(sys, 'frozen', False):
# Relaunch compiled executable
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, "", None, 1
)
else:
# Relaunch Python script
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, f'"{__file__}"', None, 1
)
except Exception:
messagebox.showerror("Error", "Administrator privileges are required for installation.")
sys.exit(1)
def setup_gui(self):
"""Construct the installer GUI with installation details and controls."""
main_frame = tk.Frame(self.window, padx=20, pady=20)
main_frame.pack(fill=tk.BOTH, expand=True)
# Introduction text
info = tk.Label(main_frame,
text="This will install Hash Verifier to your system and add\n"
"'Verify Hash' to the right-click context menu for all files.\n\n"
"Administrator privileges are required.",
font=("Segoe UI", 9),
justify=tk.LEFT)
info.pack(anchor=tk.W, pady=(0, 20))
# Installation details panel
details_frame = tk.LabelFrame(main_frame, text="Installation Details",
padx=15, pady=15, font=("Segoe UI", 9, "bold"))
details_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 20))
# Check if HashVerifier.exe exists in current directory
if os.path.exists(self.hash_verifier_source):
status_label = tk.Label(details_frame, text="✓ HashVerifier.exe found",
font=("Segoe UI", 9), fg="#00aa00")
else:
status_label = tk.Label(details_frame, text="✗ HashVerifier.exe not found",
font=("Segoe UI", 9, "bold"), fg="#cc0000")
status_label.pack(anchor=tk.W, pady=(0, 10))
# Installation path
tk.Label(details_frame, text="Install location:",
font=("Segoe UI", 9, "bold")).pack(anchor=tk.W, pady=(5, 2))
install_display = tk.Text(details_frame, height=2, wrap=tk.WORD,
font=("Segoe UI", 8), bg="#f0f0f0", relief=tk.FLAT)
install_display.insert("1.0", self.install_dir)
install_display.config(state=tk.DISABLED)
install_display.pack(fill=tk.X, pady=(0, 10))
# Files to be installed
tk.Label(details_frame, text="Files to install:",
font=("Segoe UI", 9, "bold")).pack(anchor=tk.W, pady=(5, 2))
tk.Label(details_frame, text="• HashVerifier.exe (~15 MB)",
font=("Segoe UI", 9)).pack(anchor=tk.W, padx=(10, 0))
# Registry modification details
tk.Label(details_frame, text="Registry location:",
font=("Segoe UI", 9, "bold")).pack(anchor=tk.W, pady=(10, 2))
reg_text = r"HKEY_CURRENT_USER\Software\Classes\*\shell\HashVerifier"
reg_display = tk.Text(details_frame, height=2, wrap=tk.WORD,
font=("Segoe UI", 8), bg="#f0f0f0", relief=tk.FLAT)
reg_display.insert("1.0", reg_text)
reg_display.config(state=tk.DISABLED)
reg_display.pack(fill=tk.X, pady=(0, 5))
# Context menu entry preview
tk.Label(details_frame, text="Context menu entry:",
font=("Segoe UI", 9, "bold")).pack(anchor=tk.W, pady=(10, 2))
tk.Label(details_frame, text="'Verify Hash' (right-click any file)",
font=("Segoe UI", 9), fg="#0066cc").pack(anchor=tk.W)
# Action buttons
button_frame = tk.Frame(main_frame)
button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=(10, 0))
cancel_btn = tk.Button(button_frame, text="Cancel", width=12,
command=self.window.quit)
cancel_btn.pack(side=tk.RIGHT, padx=(5, 0))
self.install_btn = tk.Button(button_frame, text="Install", width=12,
command=self.install,
bg="#0066cc", fg="white",
font=("Segoe UI", 9, "bold"))
self.install_btn.pack(side=tk.RIGHT)
# Disable install button if HashVerifier.exe is missing
if not os.path.exists(self.hash_verifier_source):
self.install_btn.config(state=tk.DISABLED)
def install(self):
"""Execute the installation process.
Copies HashVerifier.exe to Program Files and creates registry entries
for Windows Explorer context menu integration.
"""
if not os.path.exists(self.hash_verifier_source):
messagebox.showerror("Error",
"HashVerifier.exe not found!\n\n"
"Please make sure install.exe and HashVerifier.exe "
"are in the same folder.")
return
try:
# Create installation directory
os.makedirs(self.install_dir, exist_ok=True)
# Copy executable to Program Files
dest_path = os.path.join(self.install_dir, "HashVerifier.exe")
shutil.copy2(self.hash_verifier_source, dest_path)
# Register context menu entry in Windows Registry
# Using HKEY_CURRENT_USER to avoid requiring full admin rights
key_path = r"Software\Classes\*\shell\HashVerifier"
key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path)
winreg.SetValueEx(key, "", 0, winreg.REG_SZ, "Verify Hash")
winreg.SetValueEx(key, "Icon", 0, winreg.REG_SZ, f'"{dest_path}",0')
winreg.CloseKey(key)
# Set command to execute when context menu item is clicked
command_key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path + r"\command")
winreg.SetValueEx(command_key, "", 0, winreg.REG_SZ, f'"{dest_path}" "%1"')
winreg.CloseKey(command_key)
messagebox.showinfo("Success",
"Hash Verifier has been successfully installed!\n\n"
f"Installed to:\n{self.install_dir}\n\n"
"Right-click any file and select 'Verify Hash' to use it.")
self.window.quit()
except PermissionError:
messagebox.showerror("Permission Denied",
"Failed to write to Program Files.\n\n"
"Please run the installer as Administrator.")
except OSError as e:
messagebox.showerror("Installation Failed",
f"Failed to copy files:\n\n{str(e)}")
except Exception as e:
messagebox.showerror("Installation Failed",
f"Failed to install Hash Verifier:\n\n{str(e)}")
def run(self):
"""Start the application main event loop."""
self.window.mainloop()
if __name__ == "__main__":
app = Installer()
app.run()