dqqpf32897 2014-05-19 16:56
浏览 722
已采纳

使用-ldflags -H = windowsgui编译golang应用程序时,将输出打印到命令窗口

I have an application that usually runs silent in the background, so I compile it with

go build -ldflags -H=windowsgui <gofile>

To check the version at the command line, I wanted to pass a -V flag to the command line to get the string holding the version to be printed to the command prompt then have the application exit. I added the flag package and code. When I test it with

go run <gofile> -V

...it prints the version fine. When I compile the exe, it just exits, printing nothing. I suspect it's the compilation flag causing it to not access the console and sending my text into the bit bucket.

I've tried variations to print to stderr and stdout, using println and fprintf and os.stderr.write, but nothing appears from the compiled application. How should I try printing a string to the command prompt when compiled with those flags?

  • 写回答

4条回答 默认 最新

  • dongming6201 2014-05-19 18:05
    关注

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

    Hence, to print anything to the console from a GUI process on Windows you have to explicitly connect that process to the console which is attached to its parent process (if it has one), like explained here for instance. To do this, you call the AttachConsole API function. With Go, this can be done using the syscall package:

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

    To be truly complete, when AttachConsole() fails, this code should probably take one of these two routes:

    • Call AllocConsole() to get its own console window created for it.

      It'd say this is pretty much useless for displaying version information as the process usually quits after printing it, and the resulting user experience will be a console window popping up and immediately disappearing; power users will get a hint that they should re-run the application from the console but mere mortals won't probably cope.

    • Post a GUI dialog displaying the same information.

      I think this is just what's needed: note that displaying help/usage messages in response to the user specifying some command-line argument is quite often mentally associated with the console, but this is not a dogma to follow: for instance, try running msiexec.exe /? at the console and see what happens.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴
  • ¥15 下列c语言代码为何输出了多余的空格