【问题标题】:How to hide command prompt window when using Exec in Golang?在 Golang 中使用 Exec 时如何隐藏命令提示符窗口?
【发布时间】:2017-07-18 22:35:15
【问题描述】:

假设我有以下代码,使用syscall 隐藏命令行窗口

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

但是当我编译它并尝试在 Windows 中运行它时,命令行窗口又出现了

如何防止命令行窗口出现?

PS 我已经知道如何使用 go build -ldflags -H=windowsgui 将 golang 源代码编译成 Windows GUI 可执行文件,但这样做只能确保程序本身不会弹出命令行窗口,Exec 无论如何都会显示这些窗口

【问题讨论】:

  • 您能否更准确地说明您要隐藏的提示?您已经说过正确的命令隐藏了 Go 命令行窗口和 exec 生成的窗口。目前我最好的猜测是你正在执行的命令会产生一个额外的窗口。
  • 也有可能,我要检查哪个命令产生了命令提示符(不过很快就会消失)
  • @jm33_m0 我刚刚尝试过,您的问题中的 sysProcAttr 方法,它是一个巨大的改进——windows 只会短暂闪烁。你有没有找到完全防止闪光的解决方案

标签: windows go command-line system-calls


【解决方案1】:

There 是一个更好的解决方案,它可以运行exec.Command() 而不产生可见窗口,( ͡° ͜ʖ ͡°)。

这是我的代码:

首先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()

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

【讨论】:

  • 这实际上回答了这个问题。谢谢!
  • 在目录中使用os.Getenv("windir") 可能更安全。
  • @KarelBílek 是的,但我还没有看到 Windows 系统中的 cmd 不在那个地方:)。
  • 我不知道该怎么感谢你。从昨天开始,我已经尝试了至少 50 种隐藏此终端窗口的方法。我对终端窗口感到沮丧,我开始讨厌现实生活中的黑色。再次感谢。你是救世主。
【解决方案2】:

如果您使用-ldflags -H=windowsgui 构建,每个 exec.Command 都会生成一个新的控制台窗口。

如果您在没有标志的情况下构建,您将获得 一个 控制台窗口,并且所有 exec.Commands 都会打印到该窗口中。

因此,我当前的解决方案是构建不带标志,即在程序启动时有一个控制台窗口,然后在我的程序开始时立即使用此代码隐藏控制台窗口:

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)
    }
}

有关进程 ID 的详细信息,请参阅this thread

现在所有的 exec.Commands 都将它们的输出打印到隐藏的控制台窗口,而不是生成它们自己的。

这里的折衷方案是,您的程序会在您启动它时闪烁一次控制台窗口,但只会在它隐藏之前短暂闪烁。

【讨论】:

  • 我只在 win 7 上看到了一个问题,而不是 8,但我只是在 Windows 7 机器上重新测试了它,它确实可以按照描述在那里工作 - 我不知道为什么我在我之前尝试过 - 删除评论以避免混淆。回答赞成,因为我现在将使用这种方法
【解决方案3】:

您应该能够通过以下方式阻止它,而不是隐藏控制台窗口:

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

【讨论】:

  • 这似乎在 Windows 中工作,但在 WSL ubuntu 中,当我编译(使用旧版本的 golang)时,我得到了csrc/sclaunch.go:759:42: unknown field 'CreationFlags' in struct literal of type syscall.SysProcAttr
  • CreationFlags 仅适用于 Windows,不适用于 Linux
猜你喜欢
  • 1970-01-01
  • 2015-12-11
  • 2015-09-13
  • 2022-11-23
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
相关资源
最近更新 更多