diff --git a/crates/engine/src/cmd/file_cmds/tests.rs b/crates/engine/src/cmd/file_cmds/tests.rs
--- a/crates/engine/src/cmd/file_cmds/tests.rs
+++ b/crates/engine/src/cmd/file_cmds/tests.rs
@@ -1531,10 +1531,26 @@ fn reveal_in_finder_on_windows_passes_the_clicked_tabs_saved_path() {
     s.execute("file.new", json!({"width": 8, "height": 8, "name": "other"})).unwrap();
 
     let r = s.execute("file.revealInFinder", json!({"document": 0, "dryRun": true})).unwrap();
-    assert_eq!(r["program"], "explorer");
+    // The Windows Explorer by full path: a bare name would first find an explorer.exe in the app's folder.
+    let explorer = crate::layer_menu_cmds::windows_root(std::env::var_os("SystemRoot")).join("explorer.exe");
+    assert_eq!(r["program"], json!(explorer.to_string_lossy()));
     assert_eq!(r["args"], json!(["/select,", r"C:\项目 图片\海报 🖼.png"]));
 }
 
+/// Windows tools run from the Windows folder `SystemRoot` names, and from `C:\Windows` when it is
+/// unset or relative (which would resolve against the working directory).
+#[cfg(windows)]
+#[test]
+fn the_windows_folder_falls_back_when_system_root_is_unset_or_relative() {
+    use crate::layer_menu_cmds::windows_root;
+    use std::path::PathBuf;
+    assert_eq!(windows_root(Some(r"D:\WinNT".into())), PathBuf::from(r"D:\WinNT"));
+    assert_eq!(windows_root(None), PathBuf::from(r"C:\Windows"));
+    assert_eq!(windows_root(Some(r"Windows".into())), PathBuf::from(r"C:\Windows"));
+    assert_eq!(windows_root(Some(r"\Windows".into())), PathBuf::from(r"C:\Windows"));
+    assert_eq!(windows_root(Some("".into())), PathBuf::from(r"C:\Windows"));
+}
+
 /// "Include All Subfolders" (AUTO-219-5, #3753): Batch and Image Processor take the images in
 /// subfolders too, each result keeping its subfolder under the output folder (so same-named files
 /// don't collide), and skip the output folder when it sits inside the input folder.
diff --git a/crates/engine/src/cmd/layer_menu_cmds.rs b/crates/engine/src/cmd/layer_menu_cmds.rs
--- a/crates/engine/src/cmd/layer_menu_cmds.rs
+++ b/crates/engine/src/cmd/layer_menu_cmds.rs
@@ -392,8 +392,8 @@ pub(crate) fn reveal(path: &str, dry_run: bool) -> Result<Value> {
     if dry_run {
         return Ok(json!({"program": program, "args": args}));
     }
-    ensure_folder(program, &args)?;
-    spawn(program, &args)?;
+    ensure_folder(&program, &args)?;
+    spawn(&program, &args)?;
     Ok(json!({"path": path}))
 }
 
@@ -411,8 +411,28 @@ fn ensure_folder(program: &str, args: &[String]) -> Result<()> {
 }
 
 /// The file-manager invocation that selects `path` on this platform.
-pub fn reveal_command(path: &str) -> Result<(&'static str, Vec<String>)> {
-    reveal_command_on(std::env::consts::OS, path)
+pub fn reveal_command(path: &str) -> Result<(String, Vec<String>)> {
+    let (program, args) = reveal_command_on(std::env::consts::OS, path)?;
+    Ok((system_program(program), args))
+}
+
+/// Windows tools run by full path: by bare name, Windows first looks in the app's own folder, so
+/// an `explorer.exe` lying next to a portable PhotoCraft would start instead (#9666).
+#[cfg(windows)]
+fn system_program(program: &str) -> String {
+    windows_root(std::env::var_os("SystemRoot")).join(format!("{program}.exe")).to_string_lossy().into_owned()
+}
+
+/// The Windows folder for the `SystemRoot` value `system_root`: `C:\Windows` when it is unset or
+/// not an absolute path (a relative one would resolve against the working directory).
+#[cfg(windows)]
+pub(crate) fn windows_root(system_root: Option<std::ffi::OsString>) -> std::path::PathBuf {
+    system_root.map(std::path::PathBuf::from).filter(|p| p.is_absolute()).unwrap_or_else(|| std::path::PathBuf::from(r"C:\Windows"))
+}
+
+#[cfg(not(windows))]
+fn system_program(program: &str) -> String {
+    program.to_string()
 }
 
 /// [`reveal_command`] on the platform `os` (a `std::env::consts::OS` value).
diff --git a/crates/text/src/cjk.rs b/crates/text/src/cjk.rs
--- a/crates/text/src/cjk.rs
+++ b/crates/text/src/cjk.rs
@@ -136,18 +136,30 @@ fn os_locale() -> Option<String> {
 
 #[cfg(target_os = "windows")]
 fn os_locale() -> Option<String> {
-    use std::os::windows::process::CommandExt;
-    const CREATE_NO_WINDOW: u32 = 0x0800_0000;
-    let out = std::process::Command::new("reg")
-        .args(["query", "HKCU\\Control Panel\\International", "/v", "LocaleName"])
-        .creation_flags(CREATE_NO_WINDOW)
-        .output()
-        .ok()?;
+    let out = locale_query().output().ok()?;
     let text = String::from_utf8_lossy(&out.stdout);
     // "    LocaleName    REG_SZ    ja-JP"
     text.lines().find(|l| l.contains("LocaleName")).and_then(|l| l.split_whitespace().last()).map(str::to_string)
 }
 
+/// `reg query` for the UI locale, with `reg.exe` by full path: by bare name, Windows first looks in
+/// the app's own folder, so a `reg.exe` lying next to a portable PhotoCraft would start (#9666).
+#[cfg(target_os = "windows")]
+fn locale_query() -> std::process::Command {
+    use std::os::windows::process::CommandExt;
+    const CREATE_NO_WINDOW: u32 = 0x0800_0000;
+    let mut cmd = std::process::Command::new(windows_root(std::env::var_os("SystemRoot")).join("System32").join("reg.exe"));
+    cmd.args(["query", "HKCU\\Control Panel\\International", "/v", "LocaleName"]).creation_flags(CREATE_NO_WINDOW);
+    cmd
+}
+
+/// The Windows folder for the `SystemRoot` value `system_root`: `C:\Windows` when it is unset or
+/// not an absolute path (a relative one would resolve against the working directory).
+#[cfg(target_os = "windows")]
+fn windows_root(system_root: Option<std::ffi::OsString>) -> std::path::PathBuf {
+    system_root.map(std::path::PathBuf::from).filter(|p| p.is_absolute()).unwrap_or_else(|| std::path::PathBuf::from(r"C:\Windows"))
+}
+
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 fn os_locale() -> Option<String> {
     None
@@ -654,6 +666,30 @@ mod tests {
     use super::*;
     use CjkScript::*;
 
+    /// `reg.exe` runs from System32, not from wherever a bare name would find one first (#9666),
+    /// and the query still answers the UI locale.
+    #[cfg(target_os = "windows")]
+    #[test]
+    fn locale_query_runs_the_system_reg() {
+        let cmd = locale_query();
+        let system = windows_root(std::env::var_os("SystemRoot")).join("System32").join("reg.exe");
+        assert_eq!(std::path::Path::new(cmd.get_program()), system);
+        assert!(os_locale().is_some_and(|l| !l.is_empty()));
+    }
+
+    /// `SystemRoot` unset or relative (which would resolve against the working directory) falls
+    /// back to `C:\Windows`.
+    #[cfg(target_os = "windows")]
+    #[test]
+    fn the_windows_folder_falls_back_when_system_root_is_unset_or_relative() {
+        use std::path::PathBuf;
+        assert_eq!(windows_root(Some(r"D:\WinNT".into())), PathBuf::from(r"D:\WinNT"));
+        assert_eq!(windows_root(None), PathBuf::from(r"C:\Windows"));
+        assert_eq!(windows_root(Some(r"Windows".into())), PathBuf::from(r"C:\Windows"));
+        assert_eq!(windows_root(Some(r"\Windows".into())), PathBuf::from(r"C:\Windows"));
+        assert_eq!(windows_root(Some("".into())), PathBuf::from(r"C:\Windows"));
+    }
+
     #[test]
     fn explicit_locale_scripts_are_distinct_from_the_non_cjk_default() {
         assert_eq!(locale_script(Some("ja_JP.UTF-8")), Some(Japanese));
