This package will tell you whether or not a golang application was opened in the terminal. Very useful for `fyne` or any other UI libs, when you plan on having both a GUI and a CLI. We're using this to make an app that can be used heedlessly, for the advanced users, and with a GUI using fyne so the less experienced users can use the tool too.
// +build windows | |
package opened | |
import ( | |
"syscall" | |
"unsafe" | |
) | |
// <Unsafe> | |
var ( | |
// TODO: | |
// Replace these calls with golang.org/x/sys/windows | |
// Right now, syscall.NewLazyDLL is subjected to potential DLL preloading | |
// attacks. | |
moduser32 = syscall.NewLazyDLL("user32.dll") | |
modkernel32 = syscall.NewLazyDLL("kernel32.dll") | |
getConsoleWindowProc = modkernel32.NewProc("GetConsoleWindow") | |
getCurrentProcessIDProc = modkernel32.NewProc("GetCurrentProcessId") | |
getWindowThreadProcessIDProc = moduser32.NewProc("GetWindowThreadProcessId") | |
) | |
func getWindowThreadProcessID(hwnd uintptr) (uintptr, uint32) { | |
var processID uint32 | |
ret, _, _ := getWindowThreadProcessIDProc.Call( | |
hwnd, | |
uintptr(unsafe.Pointer(&processID)), | |
) | |
return ret, processID | |
} | |
func getCurrentProcessID() uint32 { | |
id, _, _ := getCurrentProcessIDProc.Call() | |
return uint32(id) | |
} | |
func getConsoleWindow() uintptr { | |
// Note: | |
// If you build with -ldflags -H=windowsgui | |
// You will need to check the error, it'll be like "The handle is invalid." | |
hwnd, _, _ := getConsoleWindowProc.Call() | |
return hwnd | |
} | |
// </Unsafe> | |
// WithTerminal returns if the application was opened with a terminal or with | |
// the desktop. | |
func WithTerminal() bool { | |
console := getConsoleWindow() | |
if console != 0 { | |
_, consoleProcID := getWindowThreadProcessID(console) | |
if getCurrentProcessID() == consoleProcID { | |
return false | |
} | |
} | |
return true | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment