Golang如何检测二进制文件是否使用"-H windowsgui"参数编译为Windows GUI程序
Golang如何检测二进制文件是否使用"-H windowsgui"参数编译为Windows GUI程序 我想检测二进制文件是否是通过“-H windowsgui”参数构建的,如果是,则执行GUI逻辑,否则执行控制台逻辑。
这样我就可以在一个地方处理应用程序的GUI和CLI逻辑(这在Linux和Darwin上运行良好),并且我可以为Windows构建两次:
go build -ldflags="-H windowsgui" -o myapp.exe
go build -o myapp-cli.exe
请帮助我。
1 回复
更多关于Golang如何检测二进制文件是否使用"-H windowsgui"参数编译为Windows GUI程序的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Windows上,可以通过检查进程是否附加到控制台来检测二进制文件是否使用-H windowsgui参数编译。以下是实现方法:
package main
import (
"fmt"
"os"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
getConsoleWindow = kernel32.NewProc("GetConsoleWindow")
)
func isGUI() bool {
// 尝试获取控制台窗口句柄
hConsole, _, _ := getConsoleWindow.Call()
// 如果返回0,说明没有控制台窗口(GUI模式)
// 如果返回非0,说明有控制台窗口(控制台模式)
return hConsole == 0
}
func main() {
if isGUI() {
// GUI逻辑
fmt.Println("运行在GUI模式")
// 这里可以调用Windows GUI相关代码
// 例如使用walk或fyne等GUI库
} else {
// 控制台逻辑
fmt.Println("运行在控制台模式")
// 正常的控制台交互逻辑
fmt.Print("请输入内容: ")
var input string
fmt.Scanln(&input)
fmt.Printf("你输入了: %s\n", input)
}
}
更健壮的实现可以结合检查标准输入输出:
package main
import (
"fmt"
"os"
"syscall"
"unsafe"
)
func isWindowsGUI() bool {
// 方法1:检查控制台窗口
kernel32 := syscall.NewLazyDLL("kernel32.dll")
getConsoleWindow := kernel32.NewProc("GetConsoleWindow")
hConsole, _, _ := getConsoleWindow.Call()
if hConsole == 0 {
return true
}
// 方法2:检查标准输入输出
fi, err := os.Stdout.Stat()
if err != nil {
return true
}
// 如果标准输出不是字符设备,可能是GUI程序
return (fi.Mode() & os.ModeCharDevice) == 0
}
func main() {
if isWindowsGUI() {
// GUI应用程序逻辑
runGUI()
} else {
// 控制台应用程序逻辑
runCLI()
}
}
func runGUI() {
fmt.Println("这是GUI应用程序")
// Windows GUI初始化代码
}
func runCLI() {
fmt.Println("这是控制台应用程序")
// 控制台交互代码
}
对于需要处理Windows消息循环的情况:
package main
import (
"fmt"
"syscall"
"unsafe"
)
func main() {
if isCompiledAsGUI() {
// 初始化GUI消息循环
initGUI()
} else {
runConsoleApp()
}
}
func isCompiledAsGUI() bool {
kernel32 := syscall.NewLazyDLL("kernel32.dll")
proc := kernel32.NewProc("GetConsoleWindow")
// 调用GetConsoleWindow
hwnd, _, _ := proc.Call()
// hwnd为0表示没有控制台窗口(GUI程序)
// hwnd非0表示有控制台窗口(控制台程序)
return hwnd == 0
}
func initGUI() {
user32 := syscall.NewLazyDLL("user32.dll")
getMessage := user32.NewProc("GetMessageW")
translateMessage := user32.NewProc("TranslateMessage")
dispatchMessage := user32.NewProc("DispatchMessageW")
var msg struct {
hwnd syscall.Handle
message uint32
wParam uintptr
lParam uintptr
time uint32
pt struct{ x, y int32 }
}
for {
ret, _, _ := getMessage.Call(uintptr(unsafe.Pointer(&msg)), 0, 0, 0)
if ret == 0 {
break
}
translateMessage.Call(uintptr(unsafe.Pointer(&msg)))
dispatchMessage.Call(uintptr(unsafe.Pointer(&msg)))
}
}
func runConsoleApp() {
fmt.Println("控制台模式运行")
// 控制台应用程序逻辑
}
这种方法利用了-H windowsgui参数编译的程序不会附加控制台窗口的特性。当使用该参数编译时,GetConsoleWindow()返回0,否则返回有效的窗口句柄。

