Hide console window, add Debug Window tray option

- Hide console window by default (windows_subsystem = "windows")
- Add "Show Debug Window" menu item to tray
- AllocConsole when debug window requested
- Console shows logs for troubleshooting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 17:09:15 -07:00
parent d7c272dabc
commit 5bb5116b92
4 changed files with 70 additions and 1 deletions

View File

@@ -72,6 +72,7 @@ windows = { version = "0.58", features = [
"Win32_System_LibraryLoader", "Win32_System_LibraryLoader",
"Win32_System_Threading", "Win32_System_Threading",
"Win32_System_Registry", "Win32_System_Registry",
"Win32_System_Console",
"Win32_Security", "Win32_Security",
"Win32_Storage_FileSystem", "Win32_Storage_FileSystem",
]} ]}

View File

@@ -8,6 +8,9 @@
//! If a support code is provided, the agent will connect using that code //! If a support code is provided, the agent will connect using that code
//! for a one-time support session. //! for a one-time support session.
// Hide console window by default on Windows (release builds)
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod capture; mod capture;
mod chat; mod chat;
mod config; mod config;
@@ -34,6 +37,10 @@ use windows::core::PCWSTR;
use windows::Win32::Security::{GetTokenInformation, TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY}; use windows::Win32::Security::{GetTokenInformation, TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY};
#[cfg(windows)] #[cfg(windows)]
use windows::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken}; use windows::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
#[cfg(windows)]
use windows::Win32::System::Console::{AllocConsole, FreeConsole, GetConsoleWindow};
#[cfg(windows)]
use windows::Win32::UI::WindowsAndMessaging::{ShowWindow, SW_SHOW, SW_HIDE};
/// Extract a 6-digit support code from the executable's filename. /// Extract a 6-digit support code from the executable's filename.
/// Looks for patterns like "GuruConnect-123456.exe" or "123456.exe" /// Looks for patterns like "GuruConnect-123456.exe" or "123456.exe"
@@ -125,6 +132,29 @@ fn show_message_box(_title: &str, _message: &str) {
// No-op on non-Windows platforms // No-op on non-Windows platforms
} }
/// Show the debug console window (Windows only)
#[cfg(windows)]
fn show_debug_console() {
unsafe {
// Check if we already have a console
let hwnd = GetConsoleWindow();
if hwnd.0 == std::ptr::null_mut() {
// No console, allocate one
let _ = AllocConsole();
info!("Debug console window opened");
} else {
// Console exists, make sure it's visible
let _ = ShowWindow(hwnd, SW_SHOW);
info!("Debug console window shown");
}
}
}
#[cfg(not(windows))]
fn show_debug_console() {
// No-op on non-Windows platforms
}
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
// Initialize logging // Initialize logging

View File

@@ -6,11 +6,36 @@
//! - Frame capture and encoding loop //! - Frame capture and encoding loop
//! - Input event handling //! - Input event handling
#[cfg(windows)]
use windows::Win32::System::Console::{AllocConsole, GetConsoleWindow};
#[cfg(windows)]
use windows::Win32::UI::WindowsAndMessaging::{ShowWindow, SW_SHOW};
use crate::capture::{self, Capturer, Display}; use crate::capture::{self, Capturer, Display};
use crate::chat::{ChatController, ChatMessage as ChatMsg}; use crate::chat::{ChatController, ChatMessage as ChatMsg};
use crate::config::Config; use crate::config::Config;
use crate::encoder::{self, Encoder}; use crate::encoder::{self, Encoder};
use crate::input::InputController; use crate::input::InputController;
/// Show the debug console window (Windows only)
#[cfg(windows)]
fn show_debug_console() {
unsafe {
let hwnd = GetConsoleWindow();
if hwnd.0 == std::ptr::null_mut() {
let _ = AllocConsole();
tracing::info!("Debug console window opened");
} else {
let _ = ShowWindow(hwnd, SW_SHOW);
tracing::info!("Debug console window shown");
}
}
}
#[cfg(not(windows))]
fn show_debug_console() {
// No-op on non-Windows platforms
}
use crate::proto::{Message, message, ChatMessage}; use crate::proto::{Message, message, ChatMessage};
use crate::transport::WebSocketTransport; use crate::transport::WebSocketTransport;
use crate::tray::{TrayController, TrayAction}; use crate::tray::{TrayController, TrayAction};
@@ -195,6 +220,9 @@ impl SessionManager {
// TODO: Show a details dialog // TODO: Show a details dialog
tracing::info!("User requested details (not yet implemented)"); tracing::info!("User requested details (not yet implemented)");
} }
TrayAction::ShowDebugWindow => {
show_debug_console();
}
} }
} }

View File

@@ -22,7 +22,7 @@ use windows::Win32::UI::WindowsAndMessaging::{
pub enum TrayAction { pub enum TrayAction {
EndSession, EndSession,
ShowDetails, ShowDetails,
// Future: OpenChat, ShowDebugWindow,
} }
/// Tray icon controller /// Tray icon controller
@@ -30,6 +30,7 @@ pub struct TrayController {
_tray_icon: TrayIcon, _tray_icon: TrayIcon,
menu: Menu, menu: Menu,
end_session_item: MenuItem, end_session_item: MenuItem,
debug_item: MenuItem,
status_item: MenuItem, status_item: MenuItem,
exit_requested: Arc<AtomicBool>, exit_requested: Arc<AtomicBool>,
} }
@@ -57,11 +58,15 @@ impl TrayController {
MenuItem::new("Managed by Administrator", false, None) MenuItem::new("Managed by Administrator", false, None)
}; };
// Debug window option (always available)
let debug_item = MenuItem::new("Show Debug Window", true, None);
// Build menu // Build menu
let menu = Menu::new(); let menu = Menu::new();
menu.append(&status_item)?; menu.append(&status_item)?;
menu.append(&machine_item)?; menu.append(&machine_item)?;
menu.append(&separator)?; menu.append(&separator)?;
menu.append(&debug_item)?;
menu.append(&end_session_item)?; menu.append(&end_session_item)?;
// Create tray icon // Create tray icon
@@ -79,6 +84,7 @@ impl TrayController {
_tray_icon: tray_icon, _tray_icon: tray_icon,
menu, menu,
end_session_item, end_session_item,
debug_item,
status_item, status_item,
exit_requested, exit_requested,
}) })
@@ -107,6 +113,10 @@ impl TrayController {
self.exit_requested.store(true, Ordering::SeqCst); self.exit_requested.store(true, Ordering::SeqCst);
return Some(TrayAction::EndSession); return Some(TrayAction::EndSession);
} }
if event.id == self.debug_item.id() {
info!("Debug window requested from tray menu");
return Some(TrayAction::ShowDebugWindow);
}
} }
// Check for tray icon events (like double-click) // Check for tray icon events (like double-click)