14 // defined by the Win32 API
15 th32cs_snapprocess uintptr = 0x2
19 kernel = syscall.MustLoadDLL("kernel32.dll")
20 CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
21 Process32First = kernel.MustFindProc("Process32FirstW")
22 Process32Next = kernel.MustFindProc("Process32NextW")
25 // ProcessEntry32 structure defined by the Win32 API
26 type processEntry32 struct {
33 th32ParentProcessID uint32
36 szExeFile [syscall.MAX_PATH]uint16
39 func getProcessEntry(pid int) (pe *processEntry32, err error) {
40 snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))
41 if snapshot == uintptr(syscall.InvalidHandle) {
42 err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
45 defer syscall.CloseHandle(syscall.Handle(snapshot))
47 var processEntry processEntry32
48 processEntry.dwSize = uint32(unsafe.Sizeof(processEntry))
49 ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
51 err = fmt.Errorf("Process32First: %v", e1)
56 if processEntry.th32ProcessID == uint32(pid) {
61 ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
63 err = fmt.Errorf("Process32Next: %v", e1)
69 func getppid() (pid int, err error) {
70 pe, err := getProcessEntry(os.Getpid())
75 pid = int(pe.th32ParentProcessID)
79 // StartedByExplorer returns true if the program was invoked by the user double-clicking
80 // on the executable from explorer.exe
82 // It is conservative and returns false if any of the internal calls fail.
83 // It does not guarantee that the program was run from a terminal. It only can tell you
84 // whether it was launched from explorer.exe
85 func StartedByExplorer() bool {
86 ppid, err := getppid()
91 pe, err := getProcessEntry(ppid)
96 name := syscall.UTF16ToString(pe.szExeFile[:])
97 return name == "explorer.exe"