项目
就是获取和设置这个脚本地址, 包括下图"使用设置脚本"的开/关
pac
在pac-cmd外面用Go语言封装了一层
特点
- 只有3个函数/方法可用
pac.EnsureHelperToolPresent(fullPath, prompt, iconFullPath)
pac.On(pacUrl string)
pac.Off()
不足
- pac-cmd可以通过重定向获得pacUrl,这个pac好像没有对应的Show方法/函数,就是没办法获得操作系统当前的pacUrl
- 把二进制文件直接读出字节写死在Go源码里,应该可以有更好的的方式
- 上面一步的字节切片和已有的文件的比较,逐个字节比较
解读
EnsureHelperToolPresent
保证pac-cmd的二进制文件的存在,核心函数
- 第二个参数,只在苹果系统上有用, 苹果会弹出提示框
- 第一个if判断windows系统上的后缀名是_386.exe还是_amd64.exe
- 其中Asset()只是把string转为[]byte,见收获(2)
- byteexec.New()就是把第2步生成的文件写入到了filepath.Join(os.Getenv(“APPDATA”), “byteexec”)(如: C:\Users\Administrator\AppData\Roaming\byteexec)下面,这其中,判断了如果文件存在,是否一致的情况,不一致就重新写入,但是他这个判断是否一致,是一个字节一个字节的判断的.感觉应该有更好的方式
- ensureElevatedOnDarwin,只是在苹果系统上才会进行条件编译
- 总结下: 以windows系统为例,就是在指定的目录下生成了个exe的可执行文件,这个exe的源码以string的形式写死在Go源代码里了
// EnsureHelperToolPresent checks if helper tool exists and extracts it if not.
// On Mac OS, it also checks and set the file's owner to root:wheel and the setuid bit,
// it will request user to input password through a dialog to gain the rights to do so.
// path: absolute or relative path of the file to be checked and generated if
// not exists. Note - relative paths are resolved relative to the system-
// specific folder for aplication resources.
// prompt: the message to be shown on the dialog.
// iconPath: the full path of the icon to be shown on the dialog.
func EnsureHelperToolPresent(path string, prompt string, iconFullPath string) (err error) {
mu.Lock()
defer mu.Unlock()
assertName := "pac"
// Load different binaries for 32bit and 64bit Windows respectively.
if runtime.GOOS == "windows" {
suffix := "_386.exe"
// https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/
if strings.EqualFold(os.Getenv("PROCESSOR_ARCHITECTURE"), "amd64") ||
strings.EqualFold(os.Getenv("PROCESSOR_ARCHITEW6432"), "amd64") {
suffix = "_amd64.exe"
}
assertName = assertName + suffix
}
pacBytes, err := Asset(assertName)
if err != nil {
return fmt.Errorf("Unable to access pac asset: %v", err)
}
be, err = byteexec.New(pacBytes, path)
if err != nil {
return fmt.Errorf("Unable to extract helper tool: %v", err)
}
return ensureElevatedOnDarwin(be, prompt, iconFullPath)
}
pac.On和pac.Off
就是简单的命令行调用,调用EnsureHelperToolPresent生成的二进制文件.在windows下就相当于sysproxy-cmd.exe on xxxx这样
pac-cmd
就是一个C语言写的跨平台的改变操作系统的自动代理设置, 不同的平台有不同的二进制文件
特点
只是个二进制文件,单独执行这个二进制文件是不会在命令行有任何输出的,需要把输出进行重定向
pac_amd64.exe show > 1.txt
如何做到无控制台输出的
比如show命令,源码里是printf了的:
if ((options.pOptions[0].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) > 0) {
if (options.pOptions[1].Value.pszValue != NULL) {
printf("%s\n", options.pOptions[1].Value.pszValue);
}
}
是通过编译选项控制的
Makefile里有如下控制:
LDFLAGS += -l rasapi32 -l wininet -Wl,–subsystem,windows
就是 -Wl,–subsystem,windows 做到的无控制台输出
Go语言里如何获取上面的输出
上面的C语言在链接的时候控制了不向命令行输出
可以用如下代码
func show(){
cmd := exec.Command("pac_amd64.exe", "show")
b,err:=cmd.CombinedOutput()
if err!=nil{
panic(err)
}
fmt.Println(string(b))
}
收获
-
strings.EqualFold()比较的unicode码,而且忽略大小写
-
string转[]byte更有效率的方式->Feature: provide no-copy conversion from []byte to string
-
[]byte相等比较用bytes.Compare
-
文件的Sync When to flush a file in Go?,感觉就如这个回复说的一样,只是为了尽可能的保证文件的写入的完整性,因为有可能在你Close之前程序崩溃了,导致文件没写入
When you want to ensure data integrity as much as possible. For example, what happens if your program crashes before it comes to closing the file?
-
在Golang里要借助跨平台的二进制可执行文件,可以把二进制文件都读出来,以string的方式写死在Go源代码里,要用的时候再写为对应平台的二进制文件
-
C语言控制控制台无输出及Go语言获取这种输出