golang 如何正确调用第三方程序,路径引号问题?

参数是前台传过来的,路径自带引号,考虑到空格问题,不能去

我知道可以不经过cmd调用,但出于个人理由此处不使用

// 这是模拟的参数
cmdLine = `"d:/.../i_view64.exe" "E:/465f55d02d.jpg"`
cmd := exec.Command("cmd.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c " + cmdLine}
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
log.Println(fmt.Sprint(err) + ": " + stderr.String())
} else {
log.Println(out.String())
}

输出结果为:
2024/03/19 17:38:41 exit status 1: �ļ�����Ŀ¼���������﷨����ȷ��

乱码我已经放弃了,谷歌了很久没有能解决的,大家有好办法欢迎回答。

改为

cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c echo 123 && " + cmdLine}

很神奇,不报错了,但乱码还是不变的——虽然不知道什么内容

还有一个尝试:

cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c chcp 65001 && " + cmdLine}

修改cmd的编码为utf8,没用!

另外

cmd := exec.Command("cmd.exe", "/c", fmt.Sprintf("chcp 65001 && %s", cmdLine))

这个也试了,直接报错,图片都没打开。

各位有何高见?

谢谢

阅读 1.4k
avatarAI BotBETA

在 Go 中调用第三方程序时,如果参数中包含空格或特殊字符,应该使用 exec.Command 的参数列表来提供这些参数,而不是将它们放入一个单独的字符串中。这是因为当你将它们放入一个字符串中时,你实际上是在创建一个单独的参数,而不是多个参数。

此外,如果你的路径中包含引号,你需要确保在将它们传递给 exec.Command 之前删除这些引号。否则,操作系统可能会误解你的意图,并导致错误。

你的代码应该像这样:

package main

import (
 "bytes"
 "fmt"
 "log"
 "os/exec"
 "strings"
)

func main() {
 // 这是模拟的参数
 cmdLine := `"d:/.../i_view64.exe" "E:/465f55d02d.jpg"`

 // 移除路径中的引号
 cmdLine = strings.ReplaceAll(cmdLine, `"`, "")

 // 使用空格分割参数
 args := strings.Split(cmdLine, " ")

 // 创建命令
 cmd := exec.Command(args[0], args[1:]...)

 var out bytes.Buffer
 var stderr bytes.Buffer
 cmd.Stdout = &out
 cmd.Stderr = &stderr

 if err := cmd.Run(); err != nil {
 log.Println(fmt.Sprint(err) + ": " + stderr.String())
 } else {
 log.Println(out.String())
 }
}

在这个示例中,我们首先使用 strings.ReplaceAll 函数删除了路径中的引号。然后,我们使用 strings.Split 函数以空格为分隔符将命令行字符串分割为参数列表。最后,我们使用 exec.Command 的参数列表形式来创建命令。

这样,无论你的路径中是否包含空格或特殊字符,都应该能够正确地调用第三方程序。

至于你遇到的乱码问题,这可能是由于第三方程序或命令提示符窗口的字符编码设置不正确导致的。你可以尝试在调用第三方程序之前,使用 chcp 65001 命令将命令提示符窗口的字符编码设置为 UTF-8。但是,请注意,这种方法可能并不适用于所有情况,因为并非所有的第三方程序都支持 UTF-8 编码。

如果上述方法仍然无法解决乱码问题,你可能需要查看第三方程序的文档或源代码,以确定它如何处理输入和输出编码。如果可能的话,你可能需要修改第三方程序以支持 UTF-8 编码。

3 个回答
 func main() {
    cmd := exec.Command("cmd", "/C", "cd d:\\web && dir")

    var stdout bytes.Buffer
    cmd.Stdout = &stdout

    err := cmd.Run()
    if err != nil {
        fmt.Println("执行脚本时出错:", err)
        return
    }

    //中文乱码解决
    outBytes, err := simplifiedchinese.GB18030.NewDecoder().Bytes(stdout.Bytes())
    if err != nil {
        fmt.Println("解码输出时出错:", err)
        return
    }

    fmt.Println("脚本输出:", string(outBytes))
}

在 Golang 中,调用第三方程序时,路径引号的使用需要注意。如果路径中包含空格或特殊字符,需要使用引号将路径包围起来。同时,如果路径中包含反斜杠(\),需要使用双反斜杠(\)进行转义。

示例代码:

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    // 使用引号包围路径
    path := `C:\Program Files\ThirdPartyApp\app.exe`

    // 创建命令
    cmd := exec.Command(path, "arg1", "arg2")

    // 执行命令
    err := cmd.Run()
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Command executed successfully")
    }
}

在这个示例中,我们使用了反引号(`)将路径包围起来,以避免因为路径中的空格或特殊字符导致的问题。同时,我们使用了双反斜杠(\)对路径中的反斜杠进行了转义。

新手上路,请多包涵

首先得确认一个问题,参数格式是固定的吗 前面是程序绝对路径后面是参数
第一个问题解决执行程序加参数

//处理乱码字符串
func ConvertByte2String(byte1 []byte, charset Charset) string {

    var str string
    switch charset {
    case GB18030:
        decodeBytes, _ := simplifiedchinese.GB18030.NewDecoder().Bytes(byte1)
        str = string(decodeBytes)
    case UTF8:
        fallthrough
    default:
        str = string(byte1)
    }

    return str
}
// 这个就是程序 我为什么用相对路径是因为下面的cmd.dir参数可以指定路径
// "./"+config.UipathProgram  这个就是程序 后面的都是参数 "exec", uipathProcessName, uipathParam, GetFanhanHash()
cmd := exec.Command("./"+config.UipathProgram, "exec", uipathProcessName, uipathParam, GetFanhanHash())
//指定执行路径
cmd.Dir = filepath.Join(system.GetPathOfProgram(), "uipath_program")
//执行时隐藏控制台(黑框)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout // 标准输出
cmd.Stderr = &stderr // 标准错误
err := cmd.Run()
if err != nil {
  ....
}
//这里就是处理乱码
outStr, errStr := ConvertByte2String(stdout.Bytes(), utils.GB18030), utils.ConvertByte2String(stderr.Bytes(), utils.GB18030)
if errStr != "" {
  ...
}

有些代码可能不需要你自己删一下

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题