在Golang中使用Exec时如何隐藏命令提示符窗口?

say i have the following code, using syscall to hide command line window

process := exec.Command(name, args...)
process.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
err := process.Start()
if err != nil {
    log.Print(err)
}

but when i compiled it and tried to run it in Windows, command line window showed up again

what can i do to prevent command line window from appearing?

PS i already know how to compile golang source into a Windows GUI executable using go build -ldflags -H=windowsgui, but doing so only ensures the program itself doesn't bring up a command line window, Exec will show those windows anyway

There is a better solution, which can run exec.Command() without spawn a visible window, ( ͡° ͜ʖ ͡°).

Here is my code:

Firstly import "syscall"

cmd_path := "C:\\Windows\\system32\\cmd.exe"
cmd_instance := exec.Command(cmd_path, "/c", "notepad")
cmd_instance.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd_output, err := cmd_instance.Output()

Origin: https://www.reddit.com/r/golang/comments/2c1g3x/build_golang_app_reverse_shell_to_run_in_windows/

If you build with -ldflags -H=windowsgui, each exec.Command will spawn a new console window.

If you build without the flag, you get one console window and all exec.Commands print into that one.

My current solution is thus to build without the flag, i.e. have a console window on program start, then immediately hide the console window with this code at the start of my program:

import "github.com/gonutz/ide/w32"

func hideConsole() {
    console := w32.GetConsoleWindow()
    if console == 0 {
        return // no console attached
    }
    // If this application is the process that created the console window, then
    // this program was not compiled with the -H=windowsgui flag and on start-up
    // it created a console along with the main application window. In this case
    // hide the console window.
    // See
    // http://stackoverflow.com/questions/9009333/how-to-check-if-the-program-is-run-from-a-console
    _, consoleProcID := w32.GetWindowThreadProcessId(console)
    if w32.GetCurrentProcessId() == consoleProcID {
        w32.ShowWindowAsync(console, w32.SW_HIDE)
    }
}

See this thread for the details about the process ID stuff.

What happens is that all exec.Commands now print their output to the hidden console window instead of spawning their own.

The compromise here is that your program will flash a console window once when you start it, but only for a brief moment before it goes into hiding.