钱文翔的博客

使用网页打开本地程序

浏览器中使用 window.open()打开 URL。当 URL 为特定的前缀的时候(URI Scheme),就会调用注册表中对应的指令。

写入注册表

参考 https://msdn.microsoft.com/en-us/library/aa767914(VS.85).aspx
其中的关键是在注册表中写入如下的注册表项

1
2
3
4
5
6
7
8
9
10
HKEY_CLASSES_ROOT
alert
(Default) = "URL:Alert Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "alert.exe,1"
shell
open
command
(Default) = "C:\Program Files\Alert\alert.exe" "%1

使用 go 操作注册表.path 为程序的地址。uri 为调用程序的 URI Scheme。
使用 js 调用 window.open(“uri://“)就可以打开程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func regKey(path string,uri string) error {
vconsoleKey, ok, err := registry.CreateKey(registry.CLASSES_ROOT, uri, registry.CREATE_SUB_KEY|registry.SET_VALUE)
if err != nil {
logger.Printf("CreateKey console err :%v\n", err)
return err
}
if ok {
return err
}
defer vconsoleKey.Close()
vconsoleKey.SetStringValue("URL Protocol", "")
vconsoleKey.SetStringValue("DefaultIcon", path)
shellKey, _, err := registry.CreateKey(vconsoleKey, `shell`, registry.CREATE_SUB_KEY)
if err != nil {
logger.Printf("CreateKey shell err :%v\n", err)
return err
}
openKey, _, err := registry.CreateKey(shellKey, `open`, registry.CREATE_SUB_KEY)
if err != nil {
logger.Printf("CreateKey open err :%v\n", err)
return err
}
commandKey, _, err := registry.CreateKey(openKey, `command`, registry.CREATE_SUB_KEY|registry.SET_VALUE)
if err != nil {
logger.Printf("CreateKey err :%v\n", err)
return err
}
commandKey.SetStringValue("", path)

return nil
}

获取管理员权限

在注册表中写入注册表项需要管理员权限。

  • go get github.com/akavel/rsrc
  • 把 nac.manifest 文件拷贝到当前 windows 项目根目录
  • rsrc -manifest nac.manifest -o nac.syso
  • go build

nac.mainfest 的内容为:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>