diff --git a/Cargo.toml b/Cargo.toml index df68f6440..49afc2bd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -196,7 +196,7 @@ uuid = { version = "1.16.0" } version-ranges = { version = "0.1.3", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } which = { version = "8.0.0", features = ["regex"] } -windows = { version = "0.59.0", features = ["std", "Win32_Globalization", "Win32_System_LibraryLoader", "Win32_System_Console", "Win32_System_Kernel", "Win32_System_Diagnostics_Debug", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_Registry", "Win32_System_IO", "Win32_System_Ioctl"] } +windows = { version = "0.59.0", features = ["std", "Win32_Globalization", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_Registry", "Win32_UI_WindowsAndMessaging"] } windows-registry = { version = "0.5.0" } wiremock = { version = "0.6.4" } wmi = { version = "0.16.0", default-features = false } diff --git a/crates/uv-shell/src/windows.rs b/crates/uv-shell/src/windows.rs index 818d5b999..4c3ddb0a4 100644 --- a/crates/uv-shell/src/windows.rs +++ b/crates/uv-shell/src/windows.rs @@ -8,8 +8,11 @@ use std::path::Path; use anyhow::Context; use tracing::warn; -use windows::Win32::Foundation::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_DATA}; -use windows::core::HRESULT; +use windows::Win32::Foundation::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_DATA, LPARAM, WPARAM}; +use windows::Win32::UI::WindowsAndMessaging::{ + HWND_BROADCAST, SMTO_ABORTIFHUNG, SendMessageTimeoutW, WM_SETTINGCHANGE, +}; +use windows::core::{HRESULT, w}; use windows_registry::{CURRENT_USER, HSTRING}; use uv_static::EnvVars; @@ -46,9 +49,35 @@ fn apply_windows_path_var(path: &HSTRING) -> anyhow::Result<()> { environment.set_expand_hstring(EnvVars::PATH, path)?; } + // Notify WM_SETTINGCHANGE listeners + broadcast_environment_changes(); + Ok(()) } +/// Broadcast `WM_SETTINGCHANGE` to notify listeners about environment changes. +/// +/// SAFETY: `SendMessageTimeoutW` is safe to call with these set of parameters. +/// When modifying environment variables we need to broadcast a `WM_SETTINGCHANGE` +/// message with lparam set to the string "Environment" to allow processes such +/// as conhost.exe to pick up the changes made on new sessions. +/// +/// See +#[allow(unsafe_code)] +fn broadcast_environment_changes() { + unsafe { + SendMessageTimeoutW( + HWND_BROADCAST, + WM_SETTINGCHANGE, + WPARAM(0), + LPARAM(w!("Environment").as_ptr() as isize), // null terminated + SMTO_ABORTIFHUNG, + 5000, + None, + ); + } +} + /// Retrieve the windows `PATH` variable from the registry. /// /// Returns `Ok(None)` if the `PATH` variable is not a string.