Skip to content

Commit 8625287

Browse files
committed
v0.3.2 – Critical Error Handling Fixes & Enhanced Windows 11 24H2 PE/ADK Support
- build.rs: replaced unwrap() with proper error handling - gui.rs: fixed all unwrap() on weak UI references; added safe upgrade() and mutex lock error handling - install.ps1: added try-catch for VS Build Tools, enhanced build error capture, and improved validation error handling - system_setup.rs & install.ps1: full Windows 11 24H2 ADK/PE detection and validation on both Rust and PowerShell sides - All panic-prone operations now use robust error handling and user-friendly error messages - Graceful fallback when optional components fail Improves reliability, especially around MSVC linker and PE/ADK detection.
1 parent 5ce5079 commit 8625287

4 files changed

Lines changed: 211 additions & 51 deletions

File tree

build.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
fn main() {
2-
slint_build::compile("ui/ghostwin.slint").unwrap();
2+
if let Err(e) = slint_build::compile("ui/ghostwin.slint") {
3+
eprintln!("Failed to compile Slint UI: {}", e);
4+
eprintln!("Make sure ui/ghostwin.slint exists and is valid");
5+
std::process::exit(1);
6+
}
37
}

install.ps1

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,63 @@ function Test-Command($cmdname) {
4141
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
4242
}
4343

44+
# Check for Visual Studio Build Tools (required for Windows builds)
45+
Write-Host "🔧 Checking for Visual Studio Build Tools..." -ForegroundColor Yellow
46+
47+
$vsBuildToolsPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
48+
$hasVSBuildTools = $false
49+
50+
if (Test-Path $vsBuildToolsPath) {
51+
try {
52+
$vsInstallations = & $vsBuildToolsPath -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json 2>$null | ConvertFrom-Json
53+
if ($vsInstallations -and $vsInstallations.Count -gt 0) {
54+
$hasVSBuildTools = $true
55+
Write-Host "✅ Visual Studio Build Tools with C++ support found!" -ForegroundColor Green
56+
}
57+
} catch {
58+
Write-Host " Failed to query Visual Studio installations: $($_.Exception.Message)" -ForegroundColor Yellow
59+
}
60+
}
61+
62+
if (-not $hasVSBuildTools) {
63+
Write-Host "⚠️ Visual Studio Build Tools with C++ support not found!" -ForegroundColor Red
64+
Write-Host " This is required for building Rust applications on Windows." -ForegroundColor Yellow
65+
Write-Host ""
66+
Write-Host "Please install one of the following:" -ForegroundColor Yellow
67+
Write-Host " 1. Visual Studio Build Tools: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022" -ForegroundColor Gray
68+
Write-Host " 2. Visual Studio Community: https://visualstudio.microsoft.com/vs/community/" -ForegroundColor Gray
69+
Write-Host ""
70+
Write-Host "Make sure to include the 'C++ build tools' workload!" -ForegroundColor Red
71+
72+
$continue = Read-Host "Continue anyway? Build will likely fail (y/N)"
73+
if ($continue -ne "y" -and $continue -ne "Y") {
74+
exit 1
75+
}
76+
}
77+
78+
# Check for Windows PE and ADK (Windows 11 24H2)
79+
Write-Host "🔧 Checking for Windows PE and ADK..." -ForegroundColor Yellow
80+
81+
$adkPath = "${env:ProgramFiles(x86)}\Windows Kits\10"
82+
$peAddonPath = "${env:ProgramFiles(x86)}\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment"
83+
84+
if (Test-Path $adkPath) {
85+
Write-Host "✅ Windows ADK found at: $adkPath" -ForegroundColor Green
86+
87+
if (Test-Path $peAddonPath) {
88+
Write-Host "✅ Windows PE add-on found!" -ForegroundColor Green
89+
} else {
90+
Write-Host "⚠️ Windows PE add-on not found!" -ForegroundColor Yellow
91+
Write-Host " Download from: https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install" -ForegroundColor Gray
92+
}
93+
} else {
94+
Write-Host "⚠️ Windows ADK not found!" -ForegroundColor Yellow
95+
Write-Host " For Windows 11 24H2 deployment, install:" -ForegroundColor Gray
96+
Write-Host " 1. Windows ADK for Windows 11, version 24H2" -ForegroundColor Gray
97+
Write-Host " 2. Windows PE add-on for the Windows ADK" -ForegroundColor Gray
98+
Write-Host " Download from: https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install" -ForegroundColor Gray
99+
}
100+
44101
# Install Rust if not present
45102
if (-not $SkipRust) {
46103
Write-Host "🔧 Checking for Rust installation..." -ForegroundColor Yellow
@@ -110,14 +167,19 @@ Push-Location $InstallPath
110167

111168
try {
112169
Write-Host " Running cargo build --release (this may take several minutes)..." -ForegroundColor Gray
113-
cargo build --release
170+
$buildResult = cargo build --release 2>&1
114171

115-
if (Test-Path "target\release\ghostwin.exe") {
172+
if ($LASTEXITCODE -eq 0 -and (Test-Path "target\release\ghostwin.exe")) {
116173
Write-Host "✅ GhostWin built successfully!" -ForegroundColor Green
117174
} else {
118175
Write-Host "❌ Build failed!" -ForegroundColor Red
176+
Write-Host "Build output:" -ForegroundColor Yellow
177+
Write-Host $buildResult -ForegroundColor Gray
119178
exit 1
120179
}
180+
} catch {
181+
Write-Host "❌ Build process failed: $($_.Exception.Message)" -ForegroundColor Red
182+
exit 1
121183
} finally {
122184
Pop-Location
123185
}
@@ -133,7 +195,16 @@ if ($addToPath -eq "y" -or $addToPath -eq "Y") {
133195

134196
# Validate installation
135197
Write-Host "🔍 Validating installation..." -ForegroundColor Yellow
136-
& "$InstallPath\target\release\ghostwin.exe" validate
198+
try {
199+
& "$InstallPath\target\release\ghostwin.exe" validate
200+
if ($LASTEXITCODE -eq 0) {
201+
Write-Host "✅ Installation validation passed!" -ForegroundColor Green
202+
} else {
203+
Write-Host "⚠️ Installation validation had warnings" -ForegroundColor Yellow
204+
}
205+
} catch {
206+
Write-Host "⚠️ Could not validate installation: $($_.Exception.Message)" -ForegroundColor Yellow
207+
}
137208

138209
Write-Host ""
139210
Write-Host "🎉 GhostWin Installation Complete!" -ForegroundColor Green

src/cli/gui.rs

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -53,32 +53,34 @@ pub async fn execute() -> Result<()> {
5353
// Set up callbacks
5454
let ui_weak = ui.as_weak();
5555
ui.on_start_normal_install(move || {
56-
let ui = ui_weak.unwrap();
57-
ui.set_current_mode("install".into());
58-
59-
// Start normal installation in background thread
60-
thread::spawn(move || {
61-
if let Err(e) = start_windows_installation(false, None, None) {
62-
error!("Normal installation failed: {}", e);
63-
}
64-
});
56+
if let Some(ui) = ui_weak.upgrade() {
57+
ui.set_current_mode("install".into());
58+
59+
// Start normal installation in background thread
60+
thread::spawn(move || {
61+
if let Err(e) = start_windows_installation(false, None, None) {
62+
error!("Normal installation failed: {}", e);
63+
}
64+
});
65+
}
6566
});
6667

6768
let ui_weak = ui.as_weak();
6869
let executor_clone3 = script_executor.clone();
6970
let tools_clone3 = detected_tools.clone();
7071
ui.on_start_automated_install(move || {
71-
let ui = ui_weak.unwrap();
72-
ui.set_current_mode("install".into());
73-
74-
// Start automated installation in background thread
75-
let executor = executor_clone3.clone();
76-
let tools = tools_clone3.clone();
77-
thread::spawn(move || {
78-
if let Err(e) = start_windows_installation(true, Some(executor), Some(tools)) {
79-
error!("Automated installation failed: {}", e);
80-
}
81-
});
72+
if let Some(ui) = ui_weak.upgrade() {
73+
ui.set_current_mode("install".into());
74+
75+
// Start automated installation in background thread
76+
let executor = executor_clone3.clone();
77+
let tools = tools_clone3.clone();
78+
thread::spawn(move || {
79+
if let Err(e) = start_windows_installation(true, Some(executor), Some(tools)) {
80+
error!("Automated installation failed: {}", e);
81+
}
82+
});
83+
}
8284
});
8385

8486
let ui_weak = ui.as_weak();
@@ -138,44 +140,47 @@ pub async fn execute() -> Result<()> {
138140
let ui_weak = ui.as_weak();
139141
let vnc_manager_clone = vnc_manager.clone();
140142
ui.on_toggle_vnc(move || {
141-
let ui = ui_weak.unwrap();
142-
let mut vnc = vnc_manager_clone.lock().unwrap();
143-
144-
if vnc.is_running() {
145-
info!("Stopping VNC server");
146-
if let Err(e) = vnc.stop_server() {
147-
error!("Failed to stop VNC server: {}", e);
148-
ui.set_vnc_status("Error".into());
149-
} else {
150-
ui.set_vnc_enabled(false);
151-
ui.set_vnc_status("Disconnected".into());
152-
}
153-
} else {
154-
info!("Starting VNC server");
155-
match vnc.start_server() {
156-
Ok(_) => {
157-
ui.set_vnc_enabled(true);
158-
let connection_info = vnc.get_connection_info();
159-
ui.set_vnc_status(format!("Connected ({})", connection_info.get_connection_string()).into());
160-
}
161-
Err(e) => {
162-
error!("Failed to start VNC server: {}", e);
163-
ui.set_vnc_status("Error".into());
143+
if let Some(ui) = ui_weak.upgrade() {
144+
if let Ok(mut vnc) = vnc_manager_clone.lock() {
145+
if vnc.is_running() {
146+
info!("Stopping VNC server");
147+
if let Err(e) = vnc.stop_server() {
148+
error!("Failed to stop VNC server: {}", e);
149+
ui.set_vnc_status("Error".into());
150+
} else {
151+
ui.set_vnc_enabled(false);
152+
ui.set_vnc_status("Disconnected".into());
153+
}
154+
} else {
155+
info!("Starting VNC server");
156+
match vnc.start_server() {
157+
Ok(_) => {
158+
ui.set_vnc_enabled(true);
159+
let connection_info = vnc.get_connection_info();
160+
ui.set_vnc_status(format!("Connected ({})", connection_info.get_connection_string()).into());
161+
}
162+
Err(e) => {
163+
error!("Failed to start VNC server: {}", e);
164+
ui.set_vnc_status("Error".into());
165+
}
166+
}
164167
}
165168
}
166169
}
167170
});
168171

169172
let ui_weak = ui.as_weak();
170173
ui.on_show_tools(move || {
171-
let ui = ui_weak.unwrap();
172-
ui.set_current_mode("tools".into());
174+
if let Some(ui) = ui_weak.upgrade() {
175+
ui.set_current_mode("tools".into());
176+
}
173177
});
174178

175179
let ui_weak = ui.as_weak();
176180
ui.on_show_menu(move || {
177-
let ui = ui_weak.unwrap();
178-
ui.set_current_mode("menu".into());
181+
if let Some(ui) = ui_weak.upgrade() {
182+
ui.set_current_mode("menu".into());
183+
}
179184
});
180185

181186
info!("Starting GUI main loop");

src/cli/system_setup.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ pub async fn execute() -> Result<()> {
5353
async fn apply_system_configurations() -> Result<()> {
5454
info!("Applying basic system configurations");
5555

56+
// Check and configure Windows PE and ADK for Windows 11 24H2
57+
check_windows_pe_adk().await?;
58+
5659
// Enable Administrator account
5760
let output = std::process::Command::new("net")
5861
.args(["user", "Administrator", "/active:Yes"])
@@ -137,5 +140,82 @@ async fn configure_power_settings() -> Result<()> {
137140
.output();
138141

139142
info!("Power settings configured for deployment");
143+
Ok(())
144+
}
145+
146+
async fn check_windows_pe_adk() -> Result<()> {
147+
info!("Checking Windows PE and ADK for Windows 11 24H2");
148+
149+
// Check for Windows ADK installation
150+
let adk_path = Path::new(r"C:\Program Files (x86)\Windows Kits\10");
151+
let pe_addon_path = Path::new(r"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment");
152+
153+
if adk_path.exists() {
154+
info!("✅ Windows ADK found at: {}", adk_path.display());
155+
156+
// Check for specific Windows 11 24H2 components
157+
let winpe_path = adk_path.join("Assessment and Deployment Kit").join("Windows Preinstallation Environment");
158+
let deployment_tools_path = adk_path.join("Assessment and Deployment Kit").join("Deployment Tools");
159+
160+
if pe_addon_path.exists() || winpe_path.exists() {
161+
info!("✅ Windows PE add-on found");
162+
163+
// Check for DISM and other required tools
164+
check_deployment_tools(&deployment_tools_path).await?;
165+
} else {
166+
warn!("⚠️ Windows PE add-on not found!");
167+
warn!(" For Windows 11 24H2 deployment, please install:");
168+
warn!(" 1. Windows ADK for Windows 11, version 24H2");
169+
warn!(" 2. Windows PE add-on for the Windows ADK");
170+
warn!(" Download from: https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install");
171+
}
172+
} else {
173+
warn!("⚠️ Windows ADK not found!");
174+
warn!(" Windows ADK is required for Windows 11 24H2 deployment");
175+
warn!(" Please install both:");
176+
warn!(" 1. Windows ADK for Windows 11, version 24H2");
177+
warn!(" 2. Windows PE add-on for the Windows ADK");
178+
warn!(" Download from: https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install");
179+
}
180+
181+
Ok(())
182+
}
183+
184+
async fn check_deployment_tools(deployment_tools_path: &Path) -> Result<()> {
185+
info!("Checking deployment tools");
186+
187+
// Check for DISM
188+
let dism_path = deployment_tools_path.join("amd64").join("DISM").join("dism.exe");
189+
if dism_path.exists() {
190+
info!("✅ DISM found at: {}", dism_path.display());
191+
192+
// Test DISM functionality
193+
let output = std::process::Command::new(&dism_path)
194+
.args(["/Get-WimInfo", "/?"])
195+
.output()?;
196+
197+
if output.status.success() {
198+
info!("✅ DISM is functional");
199+
} else {
200+
warn!("⚠️ DISM test failed: {}", String::from_utf8_lossy(&output.stderr));
201+
}
202+
} else {
203+
warn!("⚠️ DISM not found in deployment tools");
204+
}
205+
206+
// Check for ImageX (legacy support)
207+
let imagex_path = deployment_tools_path.join("amd64").join("imagex.exe");
208+
if imagex_path.exists() {
209+
info!("✅ ImageX found for legacy support");
210+
}
211+
212+
// Check for Windows PE tools
213+
let winpe_tools_path = deployment_tools_path.join("amd64").join("Oscdimg");
214+
if winpe_tools_path.exists() {
215+
info!("✅ Windows PE creation tools found");
216+
} else {
217+
warn!("⚠️ Windows PE creation tools not found");
218+
}
219+
140220
Ok(())
141221
}

0 commit comments

Comments
 (0)