Reputation: 1295
I built a tool that can be run from the console or run in the system tray if the flag -tray
is passed at start. Just running go build <list of go files>
with no build flags will create a binary that can be run in the system tray, but it also spawns a console window. If I pass the build flag -H=windowsgui
then the console window will be hidden, but I still need to pass -tray
to get it to actually run in the system tray.
Is there a way at runtime to detect that the binary was built with the flag -H=windowsgui
so I can automatically do the right thing and enable the tray without the need for the -tray
flag to have been passed?
Upvotes: 1
Views: 1095
Reputation: 12120
According to the Go source, it seems to set Subsystem
of OptionalHeader
when linking.
Therefore, you can obtain it by using debug/pe.
Following code will print it is windows GUI
when compiled with go build -ldflags "-H windowsgui"
, and print it is windows CUI
otherwise.
Note that os.Executable()
may return path for symbolic link, so may not be reliable. Refer to: the document of os.Executable()
package main
import (
"debug/pe"
"fmt"
"os"
)
// these constants are copied from https://github.com/golang/go/blob/6219b48e11f36329de801f62f18448bb4b1cd1a5/src/cmd/link/internal/ld/pe.go#L92-L93
const (
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
)
func main() {
fileName, err := os.Executable()
if err != nil {
panic(err)
}
fl, err := pe.Open(fileName)
if err != nil {
panic(err) // maybe not windows binary, or unreadable for some reasons
}
defer fl.Close()
var subsystem uint16
if header, ok := fl.OptionalHeader.(*pe.OptionalHeader64); ok {
subsystem = header.Subsystem
} else if header, ok := fl.OptionalHeader.(*pe.OptionalHeader32); ok {
subsystem = header.Subsystem
}
if subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI {
fmt.Println("it is windows GUI")
} else if subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI {
fmt.Println("it is windows CUI")
} else {
fmt.Println("binary type unknown")
}
}
Upvotes: 4