| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- 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) // NUL-free strings; ignore impossible error
- 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) {
- err := exec.Command("notepad.exe", path).Start()
- if err != nil {
- showMessageBox("错误", "无法打开记事本: "+err.Error())
- }
- }
- // relaunchInUserSession 若当前进程在 Session 0(如服务)中运行,
- // 则在活跃用户会话中重新启动自身,然后退出当前进程。
- // 调用方应在 main() 最开始调用此函数。
- func relaunchInUserSession() {
- sessionID, _, _ := consoleSessionID.Call()
- if sessionID == 0 {
- // 当前已在用户会话或 sessionID 获取失败,不做处理
- return
- }
- // 仅在 Session 0 时才需要重新启动
- 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))
- // 获取当前 EXE 路径
- exePath, err := os.Executable()
- if err != nil {
- return
- }
- exePtr := mustUTF16Ptr(exePath)
- // 准备 STARTUPINFO 和 PROCESS_INFORMATION
- 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, // no extra flags; -H windowsgui already linked
- 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)
- }
|