jm33_m0
jm33_m0

Reputation: 615

How to hide command prompt window when using Exec in Golang?

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

Upvotes: 17

Views: 15398

Answers (3)

gonutz
gonutz

Reputation: 5582

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/w32/v2"

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.

Upvotes: 4

Andrew McKinlay
Andrew McKinlay

Reputation: 2631

Instead of hiding the console window, you should be able to prevent it with:

cmd := exec.Command(...)
cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 0x08000000} // CREATE_NO_WINDOW

Upvotes: 7

Yu Chen
Yu Chen

Reputation: 386

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/

Upvotes: 27

Related Questions