main.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "os/exec"
  8. "syscall"
  9. "time"
  10. "unsafe"
  11. )
  12. type RequestData struct {
  13. Type string `json:"type"`
  14. Path string `json:"path"`
  15. FileName string `json:"fileName"`
  16. }
  17. // 常量
  18. const (
  19. VK_CONTROL = 0x11
  20. VK_V = 0x56
  21. )
  22. var (
  23. user32 = syscall.NewLazyDLL("user32.dll")
  24. findWindowW = user32.NewProc("FindWindowW")
  25. moveWindow = user32.NewProc("MoveWindow")
  26. setForegroundWindow = user32.NewProc("SetForegroundWindow")
  27. getWindowRect = user32.NewProc("GetWindowRect")
  28. setCursorPos = user32.NewProc("SetCursorPos")
  29. mouse_event = user32.NewProc("mouse_event")
  30. keybd_event = user32.NewProc("keybd_event")
  31. )
  32. type RECT struct {
  33. Left int32
  34. Top int32
  35. Right int32
  36. Bottom int32
  37. }
  38. // 回车键的虚拟键码
  39. const VK_RETURN = 0x0D
  40. const KEYEVENTF_KEYUP = 0x0002
  41. // 简化函数
  42. func FindWindow(title string) (uintptr, error) {
  43. titlePtr, err := syscall.UTF16PtrFromString(title)
  44. if err != nil {
  45. return 0, err
  46. }
  47. hwnd, _, err := findWindowW.Call(0, uintptr(unsafe.Pointer(titlePtr)))
  48. if hwnd == 0 {
  49. return 0, fmt.Errorf("窗口未找到: %v", err)
  50. }
  51. return hwnd, nil
  52. }
  53. func MoveWindow(hwnd uintptr, x, y, w, h int32) error {
  54. ret, _, err := moveWindow.Call(hwnd, uintptr(x), uintptr(y), uintptr(w), uintptr(h), 1)
  55. if ret == 0 {
  56. return fmt.Errorf("移动窗口失败: %v", err)
  57. }
  58. return nil
  59. }
  60. func SetForegroundWindow(hwnd uintptr) error {
  61. ret, _, err := setForegroundWindow.Call(hwnd)
  62. if ret == 0 {
  63. return fmt.Errorf("设置前台窗口失败: %v", err)
  64. }
  65. return nil
  66. }
  67. func GetWindowRect(hwnd uintptr) (RECT, error) {
  68. var rect RECT
  69. ret, _, err := getWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&rect)))
  70. if ret == 0 {
  71. return rect, fmt.Errorf("获取窗口矩形失败: %v", err)
  72. }
  73. return rect, nil
  74. }
  75. func SetCursorPos(x, y int32) error {
  76. ret, _, err := setCursorPos.Call(uintptr(x), uintptr(y))
  77. if ret == 0 {
  78. return fmt.Errorf("设置光标位置失败: %v", err)
  79. }
  80. return nil
  81. }
  82. func MouseClick(x, y int32) error {
  83. // 移动鼠标
  84. if err := SetCursorPos(x, y); err != nil {
  85. return err
  86. }
  87. time.Sleep(100 * time.Millisecond)
  88. // 左键按下 (0x0002 = MOUSEEVENTF_LEFTDOWN)
  89. mouse_event.Call(2, 0, 0, 0, 0)
  90. time.Sleep(50 * time.Millisecond)
  91. // 左键释放 (0x0004 = MOUSEEVENTF_LEFTUP)
  92. mouse_event.Call(4, 0, 0, 0, 0)
  93. return nil
  94. }
  95. func Paste() {
  96. // Ctrl 按下
  97. keybd_event.Call(uintptr(VK_CONTROL), 0, 0, 0)
  98. time.Sleep(50 * time.Millisecond)
  99. // V 按下
  100. keybd_event.Call(uintptr(VK_V), 0, 0, 0)
  101. time.Sleep(50 * time.Millisecond)
  102. // V 释放 (0x0002 = KEYEVENTF_KEYUP)
  103. keybd_event.Call(uintptr(VK_V), 0, 2, 0)
  104. time.Sleep(50 * time.Millisecond)
  105. // Ctrl 释放
  106. keybd_event.Call(uintptr(VK_CONTROL), 0, 2, 0)
  107. }
  108. func PressEnter() {
  109. // 按下回车键
  110. keybd_event.Call(
  111. uintptr(VK_RETURN), // bVk
  112. 0, // bScan
  113. 0, // dwFlags (按下)
  114. 0, // dwExtraInfo
  115. )
  116. time.Sleep(5 * time.Millisecond)
  117. // 释放回车键
  118. keybd_event.Call(
  119. uintptr(VK_RETURN), // bVk
  120. 0, // bScan
  121. uintptr(KEYEVENTF_KEYUP), // dwFlags (释放)
  122. 0, // dwExtraInfo
  123. )
  124. }
  125. // 使用系统命令设置剪贴板(更可靠)
  126. func SetClipboard(text string) error {
  127. // 方法1:使用 clip 命令
  128. cmd := exec.Command("cmd", "/c", fmt.Sprintf("echo %s | clip", text))
  129. if err := cmd.Run(); err == nil {
  130. return nil
  131. }
  132. // 方法2:使用 PowerShell
  133. cmd2 := exec.Command("powershell", "-Command", fmt.Sprintf("Set-Clipboard -Value '%s'", text))
  134. return cmd2.Run()
  135. }
  136. func findAndOperateWindow(title string, filePath string, fileName string) {
  137. fmt.Printf("开始查找窗口: %s\n", title)
  138. var hwnd uintptr
  139. var err error
  140. found := false
  141. // 10秒内每秒尝试查找窗口
  142. for i := 0; i < 10; i++ {
  143. fmt.Printf("尝试第 %d 次查找...\n", i+1)
  144. hwnd, err = FindWindow(title)
  145. if err == nil && hwnd != 0 {
  146. found = true
  147. fmt.Printf("找到窗口: %s (句柄: 0x%X)\n", title, hwnd)
  148. break
  149. }
  150. time.Sleep(1 * time.Second)
  151. }
  152. if !found {
  153. log.Printf("在10秒内未找到窗口: %s", title)
  154. log.Println("请确保:")
  155. log.Println("1. 窗口已经打开")
  156. log.Println("2. 窗口标题完全匹配: " + title)
  157. log.Println("3. 可能需要以管理员身份运行此程序")
  158. return
  159. }
  160. // 激活窗口
  161. if err := SetForegroundWindow(hwnd); err != nil {
  162. log.Printf("激活窗口失败: %v", err)
  163. }
  164. time.Sleep(500 * time.Millisecond)
  165. // 调整窗口大小到800x600
  166. fmt.Println("正在修改窗口大小为800x600...")
  167. if err := MoveWindow(hwnd, 100, 100, 800, 600); err != nil {
  168. log.Printf("调整窗口大小失败: %v", err)
  169. } else {
  170. fmt.Println("窗口大小修改成功")
  171. }
  172. // 获取窗口位置
  173. rect, err := GetWindowRect(hwnd)
  174. if err != nil {
  175. log.Printf("获取窗口位置失败: %v", err)
  176. } else {
  177. fmt.Printf("窗口位置: X=%d, Y=%d\n", rect.Left, rect.Top)
  178. }
  179. // 等待窗口调整完成
  180. time.Sleep(500 * time.Millisecond)
  181. MouseClick(rect.Left+450, rect.Top+60)
  182. SetClipboard(filePath)
  183. time.Sleep(500 * time.Millisecond)
  184. // 粘贴剪贴板内容
  185. fmt.Println("正在粘贴剪贴板内容...")
  186. Paste()
  187. fmt.Println("粘贴完成")
  188. time.Sleep(500 * time.Millisecond)
  189. fmt.Println("按回车键")
  190. PressEnter()
  191. fmt.Println("操作完成")
  192. MouseClick(rect.Left+450, rect.Top+530)
  193. time.Sleep(2 * time.Second)
  194. SetClipboard(fileName)
  195. time.Sleep(500 * time.Millisecond)
  196. Paste()
  197. time.Sleep(500 * time.Millisecond)
  198. PressEnter()
  199. }
  200. func handlePostRequest(w http.ResponseWriter, r *http.Request) {
  201. // 只处理POST请求
  202. if r.Method != http.MethodPost {
  203. http.Error(w, "只支持POST请求", http.StatusMethodNotAllowed)
  204. return
  205. }
  206. // 解析JSON数据
  207. var data RequestData
  208. decoder := json.NewDecoder(r.Body)
  209. if err := decoder.Decode(&data); err != nil {
  210. http.Error(w, "JSON解析错误: "+err.Error(), http.StatusBadRequest)
  211. return
  212. }
  213. defer r.Body.Close()
  214. // 输出接收到的数据
  215. fmt.Println("=== 接收到POST请求数据 ===")
  216. fmt.Printf("类型 (type): %s\n", data.Type)
  217. fmt.Printf("路径 (path): %s\n", data.Path)
  218. fmt.Printf("文件名 (fileName): %s\n", data.FileName)
  219. fmt.Println("==========================")
  220. // 根据type执行不同操作
  221. if data.Type == "openFile" {
  222. // 在新goroutine中执行窗口操作,避免阻塞HTTP响应
  223. go func() {
  224. findAndOperateWindow("打开", data.Path, data.FileName)
  225. }()
  226. // 返回响应
  227. w.Header().Set("Content-Type", "application/json")
  228. response := map[string]interface{}{
  229. "status": "processing",
  230. "message": "正在执行窗口操作",
  231. "data": data,
  232. }
  233. json.NewEncoder(w).Encode(response)
  234. return
  235. }
  236. // 返回成功响应
  237. w.Header().Set("Content-Type", "application/json")
  238. response := map[string]interface{}{
  239. "status": "success",
  240. "message": "数据接收成功",
  241. "data": data,
  242. }
  243. json.NewEncoder(w).Encode(response)
  244. }
  245. func main() {
  246. fmt.Println("窗口操作服务启动...")
  247. fmt.Println("注意:某些窗口操作可能需要管理员权限")
  248. fmt.Println("如果需要,请以管理员身份运行此程序")
  249. fmt.Println()
  250. // 设置处理POST请求的路由
  251. http.HandleFunc("/", handlePostRequest)
  252. // 设置服务器监听8866端口
  253. port := ":8866"
  254. fmt.Printf("服务器正在监听端口 %s ...\n", port)
  255. fmt.Println("等待POST请求...")
  256. fmt.Println()
  257. // 启动HTTP服务器
  258. if err := http.ListenAndServe(port, nil); err != nil {
  259. log.Fatal("服务器启动失败:", err)
  260. }
  261. }
  262. // 前端JS请求示例
  263. // const myHeaders = new Headers();
  264. // myHeaders.append("Content-Type", "application/json");
  265. // const raw = JSON.stringify({
  266. // "type": "openFile",
  267. // "path": "C:\\Users\\mail\\Downloads",
  268. // "fileName": "128.png"
  269. // });
  270. // const requestOptions = {
  271. // method: "POST",
  272. // headers: myHeaders,
  273. // body: raw,
  274. // };
  275. // fetch("http://127.0.0.1:8866/", requestOptions)
  276. // .then((response) => response.text())
  277. // .then((result) => console.log(result))
  278. // .catch((error) => console.error(error));