被 golang 坑了一下午, win 平台无法正常调用外部程序看这里。

2022-04-08 17:33:43 +08:00
 zeronofreya

很简单的调用:

cmd := exec.Command( "TeraCopy.exe", fmt.Sprintf(`*"%s" "%s"`, copyPaths, targetDir) )
err := cmd.Start()

报错:

---------------------------
 TeraCopy - Error
---------------------------
File not found:
\e:\**\tc.tmp \E:\**\b\
---------------------------
确定   
---------------------------

??? 啥玩意 ???

本着出了问题先找自身原因的混帐话优良传统,控制台与 TeraCopy 软件试了各种参数,都正常……

感觉是转义出了问题,谷歌了半天,除了复制粘贴就没别的了。

米田共里淘金终于发现了一片文章:Go 在 windows 上调用本地进程传参时的一个天坑

MD ,最终 tm 还是 go 的问题,一直不敢往那想,属实被喷怕了。 摘抄一下:

On Windows, processes receive the whole command line as a single string and do their own parsing. Command combines and quotes Args into a command line string with an algorithm compatible with applications using CommandLineToArgvW (which is the most common way). Notable exceptions are msiexec.exe and cmd.exe (and thus, all batch files), which have a different unquoting algorithm. In these or other similar cases, you can do the quoting yourself and provide the full command line in SysProcAttr.CmdLine, leaving Args empty.

反正我看不懂,看人家的解释:

也就是说,针对 cmd 参数加的引号参数会有不同的逻辑,必须在 SysProcAttr.CmdLine 中写入原始参数了,但是 Args 留空,又会导致 SysProcAttr 值为 nil ,所以简单赋值也是不行的

改了一下代码:

cmdLine := fmt.Sprintf(`copy *"%s" "%s"`, copyPaths, targetDir)
cmd := exec.Command("TeraCopy.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c " + cmdLine}
err := cmd.Start()

解决。

学习 go 一段时间,觉得它的开发者很矛盾,比如三元运算符,很多人都想要它,但官方却以语法统一、可能会导致阅读困难之类的理由推脱。 但

return r ? true : false

不比你 if 要整洁易读? 对多字节的处理也很费劲,我到现在不知道怎样查找某个中文的位置,IndexRune 报错,也没谷歌到答案

fmt.Println(strings.IndexRune("学习", "习"))


Error
./prog.go:9:42: cannot use "习" (untyped string constant) as rune value in argument to strings.IndexRune

是不是有人要说,爱用用,不用滚呢?

6996 次点击
所在节点    程序员
65 条回复
actar
2022-04-09 21:29:49 +08:00
const TeraCopy = "D:\\TeraCopy\\TeraCopy.exe"

func main() {
copyPaths := os.Args[1]
targetDir := os.Args[2]
command := exec.Command(TeraCopy, "copy", fmt.Sprintf("*%s", copyPaths), targetDir)
if err := command.Run(); err != nil {
panic(err)
}
}


可以这样写,亲测可行

TeraCopy.exe copy *"G:\1 source.txt" "G:\target\"
等价于
TeraCopy.exe copy "*G:\1 source.txt" "G:\target\"

exec.Command 传递参数的时候,不需要引号括起来
actar
2022-04-09 21:32:54 +08:00
终端环境的参数两边的引号,是由终端进行处理的。传递进程序,是不带两边的引号的
KousukeSakurako
2022-04-09 23:54:29 +08:00
怎么回事,黑不到点子上啊我看着都急
kkbblzq
2022-04-10 07:56:48 +08:00
说实话,前半段看下来还好,但是你加了后半段,看起来就很尴尬了,因为非常明显的报错😂,感觉这不是 go 不 go 的问题了,换个语言报错你确定你能看得出来?
borpubi
2022-04-12 16:37:12 +08:00
对于一个伪 IT 来说,三元运算符确实没有 if 易读易懂好解释。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://yangjunhui.monster/t/845764

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX