| package process | |
| import ( | |
| "os" | |
| "golang.org/x/sys/windows" | |
| ) | |
| func alive(pid int) bool { | |
| h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid)) | |
| if err != nil { | |
| return false | |
| } | |
| var c uint32 | |
| err = windows.GetExitCodeProcess(h, &c) | |
| _ = windows.CloseHandle(h) | |
| if err != nil { | |
| // From the GetExitCodeProcess function (processthreadsapi.h) API docs: | |
| // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess | |
| // | |
| // The GetExitCodeProcess function returns a valid error code defined by the | |
| // application only after the thread terminates. Therefore, an application should | |
| // not use STILL_ACTIVE (259) as an error code (STILL_ACTIVE is a macro for | |
| // STATUS_PENDING (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as | |
| // an error code, then applications that test for that value could interpret it | |
| // to mean that the thread is still running, and continue to test for the | |
| // completion of the thread after the thread has terminated, which could put | |
| // the application into an infinite loop. | |
| return c == uint32(windows.STATUS_PENDING) | |
| } | |
| return true | |
| } | |
| func kill(pid int) error { | |
| p, err := os.FindProcess(pid) | |
| if err == nil { | |
| err = p.Kill() | |
| if err != nil && err != os.ErrProcessDone { | |
| return err | |
| } | |
| } | |
| return nil | |
| } |