这里是golang 初学者.

问题:

  • exec.Command()为执行C:\Windows\System32\notepad.exe而工作
  • exec.Command()不适用于执行C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\winget.exe.失败并显示错误消息:
  • 然而,os.StartProcess()适用于执行C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\winget.exe

有人能告诉我为什么吗?

代码:

此代码片段不起作用.winget.exe还没有发布.

wingetPath := filepath.Join(os.Getenv("LOCALAPPDATA"),
    "Microsoft\\WindowsApps\\winget.exe")
cmd := exec.Command(wingetPath, "--version")
err := cmd.Start()
fmt.Println(err)
// exec: "C:\\Users\\<username>\\AppData\\Local\\Microsoft\\WindowsApps\\winget.exe": file does not exist

但这是可行的:

wingetPath := filepath.Join(os.Getenv("LOCALAPPDATA"),
    "Microsoft\\WindowsApps\\winget.exe")
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, nil, nil}

// The argv slice will become os.Args in the new process,
// so it normally starts with the program name
_, err := os.StartProcess(wingetPath, []string{wingetPath, "--version"}, procAttr)
fmt.Println(err)
// <nil>

Go版本:

> go version
go version go1.18 windows/amd64

推荐答案

golang 的虫子

显然,这是Go的Windows实现中的一个bug,已经在GitHub上提交了很多次——我能找到的最古老的是这issue年前提交的.

这个错误是由exec.Command()内部读取uses os.Stat()而导致的,它不能正确读取reparse points的文件.os.Lstat()罐.

Windows应用store 应用程序使用App Execution Aliases,基本上是具有重分析点的零字节文件.这post有一些额外的细节.

权变措施

  • Workaround is to use os.StartProces() - a lower level API which can be a bit painful to use especially when compared to os.Exec().
    Important: In os.StartProcess(), the argv slice will become os.Args in the new process, so you should normally pass the program name as the first argument:
wingetPath := filepath.Join(os.Getenv("LOCALAPPDATA"),
    "Microsoft\\WindowsApps\\winget.exe")
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, nil, nil}
/*
To redirect IO, pass in stdin, stdout, stderr as required
procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
*/

args = []string { "install", "git.git" }

// The argv slice will become os.Args in the new process,
// so it normally starts with the program name
proc, err := os.StartProcess(wingetPath,
   append([]string{wingetPath}, arg...), procAttr)
fmt.Println(err) // nil
  • 解决这个错误的另一种方法是(创建并)执行一个.cmd文件(例如),该文件将(正确解析并)执行带有重分析点的文件.参见this(以及本directory)中的示例.

Go相关问答推荐

如何在jsonrpc服务器的服务器端捕获错误?

Go Regexp:匹配完整的单词或子字符串,或者根本不匹配

在不耗尽资源的情况下处理S3文件下载

golang 的持久隐蔽服务

如何防止程序B存档/删除围棋中程序A当前打开的文件?

显示GUI时后台处理功能

从 eBPF LRU 哈希映射中错误驱逐的元素

如何以干净的方式在中间件中注入 repo 或服务?

我的神经网络(从头开始)训练,让它离目标更远

如何使用泛型将接口转换为指定类型

CBC Decrypter 解密加密文本,但部分文本被随机字符替换

在 Go GRPC 服务器流式拦截器上修改元数据

我相信我正确地在 sRGB 和线性 RGB 之间进行了转换,那么为什么深色的结果看起来更糟呢?

如何将具有嵌入式 struct 的 struct 展平为 json

为什么时间很短.睡眠时间比基准测试中要求的(约 300 ns)长?

Gorm 在保存/创建时序列化 struct

如何从 Go 1.18 中的单个方法返回两种不同的具体类型?

出于某种原因,Golang (Go) AES CBC 密文被填充了 16 个 0x00 字节

具有多个嵌入式 struct 的 Go MarshalJSON 行为

gob 解码器仅返回数组中的第一个元素