Installer/spm/register_win.go
partisan ca57775f8f
All checks were successful
/ test-on-windows (push) Successful in 20s
/ test-on-alpine (push) Successful in 4s
added --silent and register values in windows registry keys
2025-02-16 22:57:24 +01:00

135 lines
3.9 KiB
Go

// run_windows.go
//go:build windows
// +build windows
package spm
import (
"fmt"
"golang.org/x/sys/windows/registry"
)
// RegisterApp writes the necessary registry keys, making it appear as offically installed app
func RegisterApp() error {
exePath, err := GetInstallDir()
if err != nil {
return fmt.Errorf("failed to get install directory: %w", err)
}
// 1. Create Uninstall/Modify entry
uninstallKeyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`
uk, _, err := registry.CreateKey(registry.LOCAL_MACHINE, uninstallKeyPath, registry.ALL_ACCESS)
if err != nil {
return fmt.Errorf("failed to create uninstall key: %w", err)
}
defer uk.Close()
if err := uk.SetStringValue("DisplayName", "Spitfire"); err != nil {
return err
}
if err := uk.SetStringValue("UninstallString", exePath+" --uninstall"); err != nil {
return err
}
if err := uk.SetStringValue("ModifyPath", exePath+" --modify"); err != nil {
return err
}
if err := uk.SetStringValue("DisplayIcon", exePath); err != nil {
return err
}
// 2. Register as a browser for default apps
clientKeyPath := `Software\Clients\StartMenuInternet\SpitfireBrowser`
ck, _, err := registry.CreateKey(registry.LOCAL_MACHINE, clientKeyPath, registry.ALL_ACCESS)
if err != nil {
return fmt.Errorf("failed to create client key: %w", err)
}
defer ck.Close()
if err := ck.SetStringValue("", "Spitfire"); err != nil {
return err
}
// Create Capabilities subkey
capabilitiesKeyPath := clientKeyPath + `\Capabilities`
capk, _, err := registry.CreateKey(registry.LOCAL_MACHINE, capabilitiesKeyPath, registry.ALL_ACCESS)
if err != nil {
return fmt.Errorf("failed to create capabilities key: %w", err)
}
defer capk.Close()
if err := capk.SetStringValue("ApplicationName", "Spitfire"); err != nil {
return err
}
if err := capk.SetStringValue("ApplicationDescription", "A custom browser"); err != nil {
return err
}
// Set file associations
assocKeyPath := capabilitiesKeyPath + `\FileAssociations`
ak, _, err := registry.CreateKey(registry.LOCAL_MACHINE, assocKeyPath, registry.ALL_ACCESS)
if err != nil {
return fmt.Errorf("failed to create file associations key: %w", err)
}
defer ak.Close()
associations := map[string]string{
".html": "SpitfireBrowserHTML",
"HTTP": "SpitfireBrowserHTML",
"HTTPS": "SpitfireBrowserHTML",
}
for ext, progID := range associations {
if err := ak.SetStringValue(ext, progID); err != nil {
return err
}
}
return nil
}
// UnregisterApp removes the registry entries created by registerApp.
func UnregisterApp() error {
// Remove the Uninstall/Modify entry.
uninstallKeyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`
if err := deleteRegistryTree(registry.LOCAL_MACHINE, uninstallKeyPath); err != nil {
return fmt.Errorf("failed to delete uninstall key: %w", err)
}
// Remove the browser registration entry.
clientKeyPath := `Software\Clients\StartMenuInternet\SpitfireBrowser`
if err := deleteRegistryTree(registry.LOCAL_MACHINE, clientKeyPath); err != nil {
return fmt.Errorf("failed to delete client key: %w", err)
}
return nil
}
// deleteRegistryTree recursively deletes a registry key and all its subkeys.
func deleteRegistryTree(root registry.Key, path string) error {
// Open the key with ALL_ACCESS permissions.
key, err := registry.OpenKey(root, path, registry.ALL_ACCESS)
if err != nil {
// If the key does not exist, there's nothing to do.
if err == registry.ErrNotExist {
return nil
}
return err
}
// Read the names of all subkeys.
subKeys, err := key.ReadSubKeyNames(-1)
key.Close() // Close the key so it can be deleted later.
if err != nil {
return err
}
// Recursively delete each subkey.
for _, subKey := range subKeys {
subKeyPath := path + `\` + subKey
if err := deleteRegistryTree(root, subKeyPath); err != nil {
return err
}
}
// Finally, delete the (now empty) key.
return registry.DeleteKey(root, path)
}