windows.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package main
  2. import (
  3. "os"
  4. "os/exec"
  5. "syscall"
  6. "unsafe"
  7. )
  8. var (
  9. user32 = syscall.NewLazyDLL("user32.dll")
  10. kernel32 = syscall.NewLazyDLL("kernel32.dll")
  11. wtsapi32 = syscall.NewLazyDLL("wtsapi32.dll")
  12. msgBoxW = user32.NewProc("MessageBoxW")
  13. consoleSessionID = kernel32.NewProc("WTSGetActiveConsoleSessionId")
  14. queryUserToken = wtsapi32.NewProc("WTSQueryUserToken")
  15. createEnvBlock = user32.NewProc("CreateEnvironmentBlock")
  16. destroyEnvBlock = user32.NewProc("DestroyEnvironmentBlock")
  17. createAsUser = kernel32.NewProc("CreateProcessAsUserW")
  18. )
  19. const (
  20. mbOK = 0x00000000
  21. mbIconWarning = 0x00000030
  22. mbSetForeground = 0x00010000
  23. mbTopmost = 0x00040000
  24. )
  25. func mustUTF16Ptr(s string) *uint16 {
  26. p, _ := syscall.UTF16PtrFromString(s)
  27. return p
  28. }
  29. func showMessageBox(title, msg string) {
  30. msgBoxW.Call(0,
  31. uintptr(unsafe.Pointer(mustUTF16Ptr(msg))),
  32. uintptr(unsafe.Pointer(mustUTF16Ptr(title))),
  33. uintptr(mbOK|mbIconWarning|mbSetForeground|mbTopmost),
  34. )
  35. }
  36. func runNotepad(path string) {
  37. if err := exec.Command("notepad.exe", path).Start(); err != nil {
  38. showMessageBox("错误", "无法打开记事本: "+err.Error())
  39. }
  40. }
  41. // openBrowser launches the default browser at url without a console window.
  42. func openBrowser(url string) error {
  43. return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
  44. }
  45. // relaunchInUserSession relaunches the process in the active user session when
  46. // the current process runs in Session 0 (e.g. started by a Windows service).
  47. func relaunchInUserSession() {
  48. sessionID, _, _ := consoleSessionID.Call()
  49. if sessionID == 0 {
  50. return
  51. }
  52. var ourSession uint32
  53. kernel32.NewProc("ProcessIdToSessionId").Call(
  54. uintptr(os.Getpid()), uintptr(unsafe.Pointer(&ourSession)),
  55. )
  56. if ourSession != 0 {
  57. return
  58. }
  59. var token syscall.Handle
  60. ret, _, _ := queryUserToken.Call(sessionID, uintptr(unsafe.Pointer(&token)))
  61. if ret == 0 || token == 0 {
  62. return
  63. }
  64. defer syscall.CloseHandle(token)
  65. var envBlock unsafe.Pointer
  66. ret, _, _ = createEnvBlock.Call(uintptr(unsafe.Pointer(&envBlock)), uintptr(token), 0)
  67. if ret == 0 {
  68. return
  69. }
  70. defer destroyEnvBlock.Call(uintptr(envBlock))
  71. exePath, err := os.Executable()
  72. if err != nil {
  73. return
  74. }
  75. exePtr := mustUTF16Ptr(exePath)
  76. var si syscall.StartupInfo
  77. si.Cb = uint32(unsafe.Sizeof(si))
  78. var pi syscall.ProcessInformation
  79. ret, _, _ = createAsUser.Call(
  80. uintptr(token),
  81. 0,
  82. uintptr(unsafe.Pointer(exePtr)),
  83. 0,
  84. 0,
  85. 0,
  86. 0,
  87. uintptr(unsafe.Pointer(envBlock)),
  88. 0,
  89. uintptr(unsafe.Pointer(&si)),
  90. uintptr(unsafe.Pointer(&pi)),
  91. )
  92. if ret != 0 {
  93. syscall.CloseHandle(pi.Thread)
  94. syscall.CloseHandle(pi.Process)
  95. }
  96. os.Exit(0)
  97. }