github.com/Mrs4s/go-cqhttp@v1.2.0/global/terminal/double_click_windows.go (about) 1 package terminal 2 3 import ( 4 "os" 5 "path/filepath" 6 "unsafe" 7 8 "golang.org/x/sys/windows" 9 10 "github.com/pkg/errors" 11 ) 12 13 // RunningByDoubleClick 检查是否通过双击直接运行 14 func RunningByDoubleClick() bool { 15 kernel32 := windows.NewLazySystemDLL("kernel32.dll") 16 lp := kernel32.NewProc("GetConsoleProcessList") 17 if lp != nil { 18 var ids [2]uint32 19 var maxCount uint32 = 2 20 ret, _, _ := lp.Call(uintptr(unsafe.Pointer(&ids)), uintptr(maxCount)) 21 if ret > 1 { 22 return false 23 } 24 } 25 return true 26 } 27 28 // NoMoreDoubleClick 提示用户不要双击运行,并生成安全启动脚本 29 func NoMoreDoubleClick() error { 30 toHighDPI() 31 r := boxW(getConsoleWindows(), "请勿通过双击直接运行本程序, 这将导致一些非预料的后果.\n请在shell中运行./go-cqhttp.exe\n点击确认将释出安全启动脚本,点击取消则关闭程序", "警告", 0x00000030|0x00000001) 32 if r == 2 { 33 return nil 34 } 35 r = boxW(0, "点击确认将覆盖go-cqhttp.bat,点击取消则关闭程序", "警告", 0x00000030|0x00000001) 36 if r == 2 { 37 return nil 38 } 39 f, err := os.OpenFile("go-cqhttp.bat", os.O_CREATE|os.O_RDWR, 0o666) 40 if err != nil { 41 return err 42 } 43 if err != nil { 44 return errors.Errorf("打开go-cqhttp.bat失败: %v", err) 45 } 46 _ = f.Truncate(0) 47 48 ex, _ := os.Executable() 49 exPath := filepath.Base(ex) 50 _, err = f.WriteString("%Created by go-cqhttp. DO NOT EDIT ME!%\nstart cmd /K \"" + exPath + "\"") 51 if err != nil { 52 return errors.Errorf("写入go-cqhttp.bat失败: %v", err) 53 } 54 f.Close() 55 boxW(0, "安全启动脚本已生成,请双击go-cqhttp.bat启动", "提示", 0x00000040|0x00000000) 56 return nil 57 } 58 59 // BoxW of Win32 API. Check https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw for more detail. 60 func boxW(hwnd uintptr, caption, title string, flags uint) int { 61 captionPtr, _ := windows.UTF16PtrFromString(caption) 62 titlePtr, _ := windows.UTF16PtrFromString(title) 63 u32 := windows.NewLazySystemDLL("user32.dll") 64 ret, _, _ := u32.NewProc("MessageBoxW").Call( 65 hwnd, 66 uintptr(unsafe.Pointer(captionPtr)), 67 uintptr(unsafe.Pointer(titlePtr)), 68 uintptr(flags)) 69 70 return int(ret) 71 } 72 73 // GetConsoleWindows retrieves the window handle used by the console associated with the calling process. 74 func getConsoleWindows() (hWnd uintptr) { 75 hWnd, _, _ = windows.NewLazySystemDLL("kernel32.dll").NewProc("GetConsoleWindow").Call() 76 return 77 } 78 79 // toHighDPI tries to raise DPI awareness context to DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED 80 func toHighDPI() { 81 systemAware := ^uintptr(2) + 1 82 unawareGDIScaled := ^uintptr(5) + 1 83 u32 := windows.NewLazySystemDLL("user32.dll") 84 proc := u32.NewProc("SetThreadDpiAwarenessContext") 85 if proc.Find() != nil { 86 return 87 } 88 for i := unawareGDIScaled; i <= systemAware; i++ { 89 _, _, _ = u32.NewProc("SetThreadDpiAwarenessContext").Call(i) 90 } 91 }