我有一个通常在后台运行的应用程序,所以我用它编译它
go build -ldflags -H=windowsgui <gofile>
Run Code Online (Sandbox Code Playgroud)
要在命令行检查版本,我想将-V标志传递给命令行,以获取保存要打印到命令提示符的版本的字符串,然后让应用程序退出.我添加了标志包和代码.当我测试它时
go run <gofile> -V
Run Code Online (Sandbox Code Playgroud)
...打印版本很好.当我编译exe时,它只是退出,什么都不打印.我怀疑它是编译标志,导致它无法访问控制台并将我的文本发送到位桶.
我已尝试使用println和fprintf以及os.stderr.write打印到stderr和stdout的变体,但编译的应用程序中没有任何内容.在使用这些标志编译时,我应该如何尝试将字符串打印到命令提示符?
kos*_*tix 21
问题是当使用可执行文件创建进程时,其PE标头中的"子系统"变量设置为"Windows",该进程关闭了三个标准句柄,并且它与任何控制台无关 - 如果你是否从控制台运行它.(实际上,如果您运行的子系统设置为"控制台"的可执行文件不是来自控制台,则会强制为该进程创建一个控制台,并将该进程附加到该控制台上 - 您通常将其视为一个控制台窗口,弹出所有突然间.)
因此,要打印任何东西从Windows上的GUI程序,你必须是明确的流程连接到其连接到它的父进程(如果有的话)的控制台控制台,像解释这里的实例.为此,您可以调用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")
}
}
Run Code Online (Sandbox Code Playgroud)
要真正完成,当AttachConsole()失败时,此代码应该采用以下两个路由之一:
调用AllocConsole()为其创建自己的控制台窗口.
它说这对于显示版本信息几乎没用,因为该过程通常在打印后退出,并且最终的用户体验将是一个控制台窗口弹出并立即消失; 高级用户会得到一个提示,他们应该从控制台重新运行应用程序,但凡人不会应对.
发布显示相同信息的GUI对话框.
我认为这仅仅是我们所需要的:请注意,以响应用户指定一些命令行参数往往显示帮助/用法消息精神上关联与控制台,但是这不是教条遵循:例如,尝试运行msiexec.exe /?在控制台,看看会发生什么.
| 归档时间: |
|
| 查看次数: |
3392 次 |
| 最近记录: |