我有一个应用程序通常在后台silent运行,所以我用

go build -ldflags -H=windowsgui <gofile>

要在命令行判断版本,我希望将-V标志传递给命令行,以便将保存版本的字符串打印到命令提示符,然后让应用程序退出.我添加了旗帜包和代码.当我用它测试它的时候

go run <gofile> -V

...它可以很好地打印版本.当我编译exe时,它只是退出,不打印任何内容.我怀疑是编译标志导致它无法访问控制台,并将我的文本发送到位存储桶.

我try 使用println、fprintf和os.stderr.write将变量打印到stderr和stdout,但编译后的应用程序没有显示任何内容.在使用这些标志进行编译时,我应该如何try 将字符串打印到命令提示符?

推荐答案

The problem is that when a process is created using an executable which has the "subsystem" variable in its PE header set to "Windows", the process has its three standard handles closed and it is not associated with any console—no matter if you run it from the console or not. (In fact, if you run an executable which has its subsystem set to "console" not from a console, a console is forcibly created for that process and the process is attached to it—you usually see it as a console window popping up all of a sudden.)

因此,要从Windows上的GUI进程将任何内容打印到控制台,您必须显式地将该进程连接到附加到其父进程(如果它有父进程)的控制台,例如,如解释here所示.为此,您需要调用AttachConsoleAPI函数.对于GO,这可以使用syscall包来完成:

package main

import (
    "fmt"
    "syscall"
)

const (
    ATTACH_PARENT_PROCESS = ^uint32(0) // (DWORD)-1
)

var (
    modkernel32 = syscall.NewLazyDLL("kernel32.dll")

    procAttachConsole = modkernel32.NewProc("AttachConsole")

)

func AttachConsole(dwParentProcess uint32) (ok bool) {
    r0, _, _ := syscall.Syscall(procAttachConsole.Addr(), 1, uintptr(dwParentProcess), 0, 0)
    ok = bool(r0 != 0)
    return
}

func main() {
    ok := AttachConsole(ATTACH_PARENT_PROCESS)
    if ok {
        fmt.Println("Okay, attached")
    }
}

要真正完整,当AttachConsole()失败时,此代码可能应该采取以下两种途径之一:

  • 呼叫AllocConsole()以获取为其创建的自己的控制台窗口.

    它会说,这对于显示版本信息几乎毫无用处,因为这个过程通常会在打印后退出,由此产生的用户体验将是一个控制台窗口弹出并立即消失;超级用户会得到一个提示,他们应该从控制台重新运行应用程序,但仅仅是普通人可能无法应对.

  • 发布一个显示相同信息的GUI对话框.

    我认为这正是所需要的:请注意,显示帮助/用法消息以响应用户指定的一些命令行参数在控制台中通常是mentally associated,但这不是一个需要遵循的教条:例如,try 在控制台上运行msiexec.exe /?,看看会发生什么.

Go相关问答推荐

无法找到与golang、nginx和postquist进行的docker-compose./主要

使用GO从RDPMC获得价值

是否可以将 http.ServeHttp 包装在 go 中以使用 alexedwards/scs/v2 添加会话

Golang 创建一个带有处理程序的模拟数据库并使用接口调用数据库

如何使用泛型将接口转换为指定类型

也许在 golang 中包(字符串和字符串类型不匹配)

Protobuf.Any - 从 json.RawMessage 解组

如何将文件上传到 Google Drive,并与使用服务帐户和 Golang 的任何人共享

Golang模板无法访问embedFS中的文件

在 docker kill --signal=SIGX 上以这种方式关闭容器内运行的 go 应用程序是否安全?

为什么时间很短.睡眠时间比基准测试中要求的(约 300 ns)长?

为什么 0 big.Int 的 .Bytes() 值是空切片?

如何使用 math/big 对 bigInt 进行取模?

通用函数与外部包中的常见成员一起处理不同的 struct ?

使用 delve 在容器中调试 Golang:container_linux.go:380:启动容器进程导致:exec:/dlv:stat /dlv:没有这样的文件或目录

在 Golang 中使用 OR 条件验证 struct 的两个字段

如何排除溢出矩阵的坐标

如何从字符串中删除多个换行符`\n`但只保留一个?

为什么 go-cmp Equal() 说 struct 不是完全相等的,即使所有字段都非常相等?

Scanner.Buffer - 最大值对自定义拆分没有影响?