fix(windows): register HKCU ProgIDs + Capabilities for portable .exe default-app support
For MSI installs the installer already writes HKLM Capabilities + RegisteredApplications, so the "Set as default" dialog works. For portable .exe builds those registry keys are never created, so the IApplicationAssociationRegistrationUI dialog silently does nothing. register_handler() now also writes: - HKCU\Software\Classes\Applications\OpenCADStudio.exe (Open-with list) - HKCU\Software\Classes\OpenCADStudio.DWG / .DXF (ProgIDs + icon + open cmd) - HKCU\Software\Classes\.dwg|.dxf\OpenWithProgids - HKCU\Software\Open CAD Studio\Capabilities (AssociationToasts shown) - HKCU\Software\RegisteredApplications (Windows Default Programs) This makes the "Yes, set as default" button work correctly for portable builds on all supported Windows versions. https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
This commit is contained in:
parent
5ba7101022
commit
db607cca1f
1 changed files with 63 additions and 8 deletions
|
|
@ -232,24 +232,79 @@ mod windows_impl {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register the running .exe under HKCU\…\Applications so it shows up in the
|
/// Create a per-user ProgID (`HKCU\Software\Classes\<progid>`) with an icon
|
||||||
/// shell's "Open with" list for .dwg / .dxf. The MSI does this machine-wide
|
/// and an open command, mirroring one of the MSI's per-machine ProgIDs.
|
||||||
/// for installed builds; this covers the portable .exe.
|
fn register_progid(exe: &str, progid: &str, description: &str) -> Result<(), String> {
|
||||||
pub(super) fn register_handler() -> Result<(), String> {
|
let base = format!(r"Software\Classes\{progid}");
|
||||||
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
|
set_string(&base, None, description)?;
|
||||||
let exe = exe.to_string_lossy().to_string();
|
set_string(&format!(r"{base}\DefaultIcon"), None, &format!("\"{exe}\",0"))?;
|
||||||
const BASE: &str = r"Software\Classes\Applications\OpenCADStudio.exe";
|
|
||||||
|
|
||||||
set_string(
|
set_string(
|
||||||
&format!(r"{BASE}\shell\open\command"),
|
&format!(r"{base}\shell\open\command"),
|
||||||
None,
|
None,
|
||||||
&format!("\"{exe}\" \"%1\""),
|
&format!("\"{exe}\" \"%1\""),
|
||||||
)?;
|
)?;
|
||||||
set_string(BASE, Some("FriendlyAppName"), "Open CAD Studio")?;
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register the running .exe (per-user, HKCU) so the portable build matches
|
||||||
|
/// what the MSI provides machine-wide:
|
||||||
|
/// * an `Applications\OpenCADStudio.exe` entry → listed under "Open with";
|
||||||
|
/// * ProgIDs + a Capabilities / RegisteredApplications block → the app is
|
||||||
|
/// a default-app candidate, so the in-app "set as default" prompt's OS
|
||||||
|
/// dialog (LaunchAdvancedAssociationUI "Open CAD Studio") finds it.
|
||||||
|
pub(super) fn register_handler() -> Result<(), String> {
|
||||||
|
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
|
||||||
|
let exe = exe.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
// ── "Open with" exe listing ─────────────────────────────────────────
|
||||||
|
const APP_BASE: &str = r"Software\Classes\Applications\OpenCADStudio.exe";
|
||||||
|
set_string(
|
||||||
|
&format!(r"{APP_BASE}\shell\open\command"),
|
||||||
|
None,
|
||||||
|
&format!("\"{exe}\" \"%1\""),
|
||||||
|
)?;
|
||||||
|
set_string(APP_BASE, Some("FriendlyAppName"), "Open CAD Studio")?;
|
||||||
// Listing the extensions under SupportedTypes is what makes the app
|
// Listing the extensions under SupportedTypes is what makes the app
|
||||||
// appear in the "Open with → Choose another app" picker for them.
|
// appear in the "Open with → Choose another app" picker for them.
|
||||||
set_string(&format!(r"{BASE}\SupportedTypes"), Some(".dwg"), "")?;
|
set_string(&format!(r"{APP_BASE}\SupportedTypes"), Some(".dwg"), "")?;
|
||||||
set_string(&format!(r"{BASE}\SupportedTypes"), Some(".dxf"), "")?;
|
set_string(&format!(r"{APP_BASE}\SupportedTypes"), Some(".dxf"), "")?;
|
||||||
|
|
||||||
|
// ── ProgIDs (per-user mirror of the MSI's) ──────────────────────────
|
||||||
|
// The Capabilities entries below point at these, and they must resolve
|
||||||
|
// to a real open command for "set as default" to apply them.
|
||||||
|
register_progid(&exe, "OpenCADStudio.DWG", "DWG Drawing")?;
|
||||||
|
register_progid(&exe, "OpenCADStudio.DXF", "DXF Drawing")?;
|
||||||
|
// Also offer the ProgIDs in each extension's Open-with list.
|
||||||
|
set_string(
|
||||||
|
r"Software\Classes\.dwg\OpenWithProgids",
|
||||||
|
Some("OpenCADStudio.DWG"),
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
set_string(
|
||||||
|
r"Software\Classes\.dxf\OpenWithProgids",
|
||||||
|
Some("OpenCADStudio.DXF"),
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// ── Capabilities + RegisteredApplications ───────────────────────────
|
||||||
|
// Mirrors the MSI's DefaultPrograms component, but per-user, so the
|
||||||
|
// portable build is a Default-Apps candidate too. The value name in
|
||||||
|
// RegisteredApplications must equal the name passed to
|
||||||
|
// LaunchAdvancedAssociationUI ("Open CAD Studio").
|
||||||
|
const CAP: &str = r"Software\Open CAD Studio\Capabilities";
|
||||||
|
set_string(CAP, Some("ApplicationName"), "Open CAD Studio")?;
|
||||||
|
set_string(
|
||||||
|
CAP,
|
||||||
|
Some("ApplicationDescription"),
|
||||||
|
"2D/3D CAD application for DWG and DXF drawings.",
|
||||||
|
)?;
|
||||||
|
set_string(&format!(r"{CAP}\FileAssociations"), Some(".dwg"), "OpenCADStudio.DWG")?;
|
||||||
|
set_string(&format!(r"{CAP}\FileAssociations"), Some(".dxf"), "OpenCADStudio.DXF")?;
|
||||||
|
set_string(
|
||||||
|
r"Software\RegisteredApplications",
|
||||||
|
Some("Open CAD Studio"),
|
||||||
|
r"Software\Open CAD Studio\Capabilities",
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue