1//go:build windows
2// +build windows
3
4package setup
5
6import (
7	"fmt"
8	"golang.org/x/sys/windows/registry"
9	"os"
10	"os/exec"
11	"strings"
12)
13
14// https://stackoverflow.com/a/3964401
15func Install() error {
16	var (
17		err       error
18		keyRoot   registry.Key
19		keyOpener registry.Key
20	)
21
22	keyRoot, _, err = registry.CreateKey(registry.CLASSES_ROOT, PROTOCOL, registry.ALL_ACCESS)
23	if err != nil {
24		// if system wide install fails, use current user's registry
25		keypath := fmt.Sprintf("Software\\Classes\\%s", PROTOCOL)
26		keyRoot, _, err = registry.CreateKey(registry.CURRENT_USER, keypath, registry.ALL_ACCESS)
27		if err != nil {
28			return fmt.Errorf("failed to create root key. %s", err.Error())
29		}
30	}
31
32	err = keyRoot.SetStringValue("", fmt.Sprintf("URL:%s Protocol", PROTOCOL))
33	if err != nil {
34		return err
35	}
36
37	err = keyRoot.SetStringValue("URL Protocol", "")
38	if err != nil {
39		return err
40	}
41
42	keyOpener, _, err = registry.CreateKey(keyRoot, "shell\\open\\command", registry.ALL_ACCESS)
43	if err != nil {
44		return err
45	}
46
47	err = keyOpener.SetStringValue("", fmt.Sprintf("\"%s\" \"%%1\"", os.Args[0]))
48	if err != nil {
49		return err
50	}
51
52	return nil
53}
54
55func Uninstall() error {
56	var (
57		err error
58	)
59
60	// try system wide key first
61	_ = registry.DeleteKey(registry.CLASSES_ROOT, fmt.Sprintf("%s\\shell\\open\\command", PROTOCOL))
62	_ = registry.DeleteKey(registry.CLASSES_ROOT, fmt.Sprintf("%s\\shell\\open", PROTOCOL))
63	_ = registry.DeleteKey(registry.CLASSES_ROOT, fmt.Sprintf("%s\\shell", PROTOCOL))
64	err = registry.DeleteKey(registry.CLASSES_ROOT, fmt.Sprintf("%s", PROTOCOL))
65	if err == nil {
66		return nil
67	}
68
69	// still here? try user key
70	_ = registry.DeleteKey(registry.CURRENT_USER, fmt.Sprintf("Software\\Classes\\%s\\shell\\open\\command", PROTOCOL))
71	_ = registry.DeleteKey(registry.CURRENT_USER, fmt.Sprintf("Software\\Classes\\%s\\shell\\open", PROTOCOL))
72	_ = registry.DeleteKey(registry.CURRENT_USER, fmt.Sprintf("Software\\Classes\\%s\\shell", PROTOCOL))
73	err = registry.DeleteKey(registry.CURRENT_USER, fmt.Sprintf("Software\\Classes\\%s", PROTOCOL))
74
75	if err != nil {
76		return fmt.Errorf("Handler removal failed.\n%s", err.Error())
77	}
78
79	return nil
80}
81
82func PreparePath(path string, isLetter bool) string {
83	return strings.Replace(path, "/", "\\", -1)
84}
85
86func Run(path string) error {
87	// note: the empty parameter is the title of the window and required even though it should be optional
88	out, err := exec.Command("cmd", "/C", "start", "", "/B", path).CombinedOutput()
89
90	if err != nil {
91		return fmt.Errorf("Failed to execute command.\n%s\n%s", err.Error(), out)
92	}
93
94	return nil
95}
96