From 5bb5116b92f6bbae327fbc9cd15809d0edf601e3 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Sun, 28 Dec 2025 17:09:15 -0700 Subject: [PATCH] Hide console window, add Debug Window tray option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- agent/Cargo.toml | 1 + agent/src/main.rs | 30 ++++++++++++++++++++++++++++++ agent/src/session/mod.rs | 28 ++++++++++++++++++++++++++++ agent/src/tray/mod.rs | 12 +++++++++++- 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/agent/Cargo.toml b/agent/Cargo.toml index a6a1076..06fc1a4 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -72,6 +72,7 @@ windows = { version = "0.58", features = [ "Win32_System_LibraryLoader", "Win32_System_Threading", "Win32_System_Registry", + "Win32_System_Console", "Win32_Security", "Win32_Storage_FileSystem", ]} diff --git a/agent/src/main.rs b/agent/src/main.rs index 3ea37c8..580dc77 100644 --- a/agent/src/main.rs +++ b/agent/src/main.rs @@ -8,6 +8,9 @@ //! If a support code is provided, the agent will connect using that code //! 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 chat; mod config; @@ -34,6 +37,10 @@ use windows::core::PCWSTR; use windows::Win32::Security::{GetTokenInformation, TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY}; #[cfg(windows)] 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. /// 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 } +/// 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] async fn main() -> Result<()> { // Initialize logging diff --git a/agent/src/session/mod.rs b/agent/src/session/mod.rs index d5750ad..2977fdf 100644 --- a/agent/src/session/mod.rs +++ b/agent/src/session/mod.rs @@ -6,11 +6,36 @@ //! - Frame capture and encoding loop //! - 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::chat::{ChatController, ChatMessage as ChatMsg}; use crate::config::Config; use crate::encoder::{self, Encoder}; 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::transport::WebSocketTransport; use crate::tray::{TrayController, TrayAction}; @@ -195,6 +220,9 @@ impl SessionManager { // TODO: Show a details dialog tracing::info!("User requested details (not yet implemented)"); } + TrayAction::ShowDebugWindow => { + show_debug_console(); + } } } diff --git a/agent/src/tray/mod.rs b/agent/src/tray/mod.rs index 5d958c9..03d8049 100644 --- a/agent/src/tray/mod.rs +++ b/agent/src/tray/mod.rs @@ -22,7 +22,7 @@ use windows::Win32::UI::WindowsAndMessaging::{ pub enum TrayAction { EndSession, ShowDetails, - // Future: OpenChat, + ShowDebugWindow, } /// Tray icon controller @@ -30,6 +30,7 @@ pub struct TrayController { _tray_icon: TrayIcon, menu: Menu, end_session_item: MenuItem, + debug_item: MenuItem, status_item: MenuItem, exit_requested: Arc, } @@ -57,11 +58,15 @@ impl TrayController { MenuItem::new("Managed by Administrator", false, None) }; + // Debug window option (always available) + let debug_item = MenuItem::new("Show Debug Window", true, None); + // Build menu let menu = Menu::new(); menu.append(&status_item)?; menu.append(&machine_item)?; menu.append(&separator)?; + menu.append(&debug_item)?; menu.append(&end_session_item)?; // Create tray icon @@ -79,6 +84,7 @@ impl TrayController { _tray_icon: tray_icon, menu, end_session_item, + debug_item, status_item, exit_requested, }) @@ -107,6 +113,10 @@ impl TrayController { self.exit_requested.store(true, Ordering::SeqCst); 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)