首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Go中,为什么exec.Command()失败而os.StartProcess()成功地启动了"winget.exe"?

在Go中,为什么exec.Command()失败而os.StartProcess()成功地启动了"winget.exe"?
EN

Stack Overflow用户
提问于 2022-04-14 00:59:47
回答 1查看 397关注 0票数 7
  • exec.Command()用于执行C:\Windows\System32\notepad.exe
  • 但是exec.Command()不适用于执行C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\winget.exe。错误消息失败:
    • exec: "C:\\Users\\<username>\\AppData\\Local\\Microsoft\\WindowsApps\\winget.exe": file does not exist

  • 但是,os.StartProcess()用于执行C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\winget.exe

谁能告诉我原因吗?

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

代码语言:javascript
复制
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

但这样做是可行的:

代码语言:javascript
复制
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版本:

代码语言:javascript
复制
> go version
go version go1.18 windows/amd64
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-14 16:09:10

戈朗虫

因此,很明显,这是Go的Windows实现中的一个bug,并多次在GitHub上注册--我能找到的最古老的问题是几年前提交的这个问题

该错误是由于exec.Command()内部使用 os.Stat()无法正确读取修复点文件造成的。os.Lstat()可以。

Windows应用程序使用App执行别名,它本质上是具有解析点的零字节文件。这个帖子有一些额外的细节。

解决办法

  • 解决办法是使用os.StartProces() --这是一个较低级别的API,使用起来可能有点痛苦,特别是与os.Exec()相比。 :在os.StartProcess()中,argv片将成为新进程中的os.Args,因此通常应该传递程序名作为第一个参数:
代码语言:javascript
复制
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文件(例如),它将(正确地解析和)执行带有解析点的文件。有关示例,请参见 (以及此目录)。
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71865309

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档