简体   繁体   中英

Running windows command in golang

I have seen the existing solutions to run a windows command from a Golang program but none works for me. My aim is to open a .png file from the go program.

Below is sample program. It does not open the image file. I am just trying with dir for testing.

package main

import (
    "log"
    "os"
    "os/exec"
    "runtime"
)

func main() {
    cmd := exec.Command("ls", "-lah")
    if runtime.GOOS == "windows" {
        cmd = exec.Command("cmd", "dir")
    }
    cmd.Stdout = os.Stdout

    err := cmd.Run()
    if err != nil {
        log.Fatalf("cmd.Run() failed with %s\n", err)
    }
}

I have also tried cmd = exec.Command("dir") in line 13. The program just exists without any error or output. Seems like a successful execution as there is no error being shown to me. I tried a few variations but no success.

I am using VSCode and tried running this program through built-in cmd and wsl in VSCode. When I use wsl to run the program, it shows the output of ls -lah but nothing for cmd . I don't know if there is some way to direct windows output. Any help is appreciated. Thanks.

cmd.exe is the windows command interpreter; if you wish to pass it a command to run you need to use the /c parameter - eg cmd /c dir . If you enter cmd dir at a command prompt you will get the same result as your current go application (except that the cmd prompt will not automatically close due to the lack of stdin). If you run cmd /? this is explained as:

/C Carries out the command specified by string and then terminates

So to fix your application use the following:

cmd = exec.Command("cmd", "/c", "dir")

An alternative way of doing this is to pass the command in via stdin:

cmd := exec.Command("cmd")
cmd.Stdout = os.Stdout
stdin, err := cmd.StdinPipe()
if err != nil {
    log.Fatal(err)
}
go func() {
    defer stdin.Close()
    io.WriteString(stdin, "dir\n")
}()
err = cmd.Run()
if err != nil {
    log.Fatalf("cmd.Run() failed with %s\n", err)
}

A simple way to open your BMP file is cmd = exec.Command("explorer.exe", "test.bmp") (this will open it with whatever the default application is).

Note: The reason you need to run cmd in the first place is that dir is an internal command provided by cmd.exe (if you run dir dir.* /s in the windows folder you won't find anything because there is no dir.exe or similar; its embedded in cmd.exe ).

Note2: If you are were running ls/dir in this way to get the contents of a folder (rather than as an example) then ioutil.ReadDir is a better option.

As explained by Brits, the error seems to manifest only when a Windows internal command is request. So, to circumvent the check done on the file path, I created a local batch file with the same name as the Windows internal command, eg if I wanted to run an "ECHO" command, I can create a echo.bat file that contains "@ECHO %1". Just tested and the same code is now working on both Windows and Linux, eg:

    cmd := exec.Command(os.Args[1], os.Args[2:]...)

    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    cmd.Run()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM