package main import ( "os" "os/exec" "syscall" "unsafe" ) var ( user32 = syscall.NewLazyDLL("user32.dll") kernel32 = syscall.NewLazyDLL("kernel32.dll") wtsapi32 = syscall.NewLazyDLL("wtsapi32.dll") msgBoxW = user32.NewProc("MessageBoxW") consoleSessionID = kernel32.NewProc("WTSGetActiveConsoleSessionId") queryUserToken = wtsapi32.NewProc("WTSQueryUserToken") createEnvBlock = user32.NewProc("CreateEnvironmentBlock") destroyEnvBlock = user32.NewProc("DestroyEnvironmentBlock") createAsUser = kernel32.NewProc("CreateProcessAsUserW") ) const ( mbOK = 0x00000000 mbIconWarning = 0x00000030 mbSetForeground = 0x00010000 mbTopmost = 0x00040000 ) func mustUTF16Ptr(s string) *uint16 { p, _ := syscall.UTF16PtrFromString(s) return p } func showMessageBox(title, msg string) { msgBoxW.Call(0, uintptr(unsafe.Pointer(mustUTF16Ptr(msg))), uintptr(unsafe.Pointer(mustUTF16Ptr(title))), uintptr(mbOK|mbIconWarning|mbSetForeground|mbTopmost), ) } func runNotepad(path string) { if err := exec.Command("notepad.exe", path).Start(); err != nil { showMessageBox("错误", "无法打开记事本: "+err.Error()) } } // openBrowser launches the default browser at url without a console window. func openBrowser(url string) error { return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() } // relaunchInUserSession relaunches the process in the active user session when // the current process runs in Session 0 (e.g. started by a Windows service). func relaunchInUserSession() { sessionID, _, _ := consoleSessionID.Call() if sessionID == 0 { return } var ourSession uint32 kernel32.NewProc("ProcessIdToSessionId").Call( uintptr(os.Getpid()), uintptr(unsafe.Pointer(&ourSession)), ) if ourSession != 0 { return } var token syscall.Handle ret, _, _ := queryUserToken.Call(sessionID, uintptr(unsafe.Pointer(&token))) if ret == 0 || token == 0 { return } defer syscall.CloseHandle(token) var envBlock unsafe.Pointer ret, _, _ = createEnvBlock.Call(uintptr(unsafe.Pointer(&envBlock)), uintptr(token), 0) if ret == 0 { return } defer destroyEnvBlock.Call(uintptr(envBlock)) exePath, err := os.Executable() if err != nil { return } exePtr := mustUTF16Ptr(exePath) var si syscall.StartupInfo si.Cb = uint32(unsafe.Sizeof(si)) var pi syscall.ProcessInformation ret, _, _ = createAsUser.Call( uintptr(token), 0, uintptr(unsafe.Pointer(exePtr)), 0, 0, 0, 0, uintptr(unsafe.Pointer(envBlock)), 0, uintptr(unsafe.Pointer(&si)), uintptr(unsafe.Pointer(&pi)), ) if ret != 0 { syscall.CloseHandle(pi.Thread) syscall.CloseHandle(pi.Process) } os.Exit(0) }