WinApi.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. using PTMedicalInsurance.Variables;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12. namespace PTMedicalInsurance.Common
  13. {
  14. class WinApi
  15. {
  16. private bool IsWindowExist(IntPtr handle)
  17. {
  18. return (!(GetWindow(new HandleRef(this, handle), 4) != IntPtr.Zero) && IsWindowVisible(new HandleRef(this, handle)));
  19. }
  20. [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  21. public static extern IntPtr GetWindow(HandleRef hWnd, int uCmd);
  22. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  23. public static extern bool IsWindowVisible(HandleRef hWnd);
  24. /// <summary>
  25. /// 获取应用程序窗口句柄
  26. /// </summary>
  27. /// <param name="processId"></param>
  28. /// <returns></returns>
  29. private IntPtr GetWindowHandle(int processId)
  30. {
  31. var windowHandle = IntPtr.Zero;
  32. EnumThreadWindowsCallback windowsCallback = new EnumThreadWindowsCallback(FindMainWindow);
  33. EnumWindows(windowsCallback, IntPtr.Zero);
  34. //保持循环
  35. GC.KeepAlive(windowsCallback);
  36. bool FindMainWindow(IntPtr handle, IntPtr extraParameter)
  37. {
  38. int num;
  39. GetWindowThreadProcessId(new HandleRef(this, handle), out num);
  40. if (num == processId && IsWindowExist(handle))
  41. {
  42. windowHandle = handle;
  43. return true;
  44. }
  45. return false;
  46. }
  47. return windowHandle;
  48. }
  49. public delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam);
  50. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  51. public static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);
  52. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  53. public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);
  54. public static IntPtr GetWindowsHandle(string WindowName)
  55. {
  56. IntPtr hwnd = IntPtr.Zero;
  57. Process[] procs = Process.GetProcessesByName(WindowName);
  58. if (procs.Length != 0)
  59. {
  60. hwnd = procs[0].MainWindowHandle;
  61. //MessageBox.Show("??" + procs[0].Id.ToString() + "??" + procs[0].MainWindowHandle.ToString());
  62. //Global.writeLog("GetWindowsHandle=>ProcessID:" + procs[0].Id + ",ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString());
  63. //Global.writeLog("GetWindowsHandle=>CurrentProcessID:" + Process.GetCurrentProcess().Id);
  64. }
  65. //Process ps = procs[0];
  66. //Global.writeLog("Start");
  67. //for (int i = 0; i < ps.Threads.Count; i++)
  68. //{
  69. // var thread = ps.Threads[i];
  70. // string str = string.Empty;
  71. // str = str + "标识符(" + i.ToString() + "):"+ thread.Id.ToString() + System.Environment.NewLine;
  72. // //str = str + "标识符:" + thread. + System.Environment.NewLine;
  73. // str = str +"基本优先级:" + thread.BasePriority.ToString() + System.Environment.NewLine;
  74. // str = str +"当前优先级:" + thread.CurrentPriority.ToString() + System.Environment.NewLine;
  75. // str = str +"内存地址:" + thread.StartAddress.ToInt32() + System.Environment.NewLine;
  76. // str = str +"启动时间:" + thread.StartTime.ToString() + System.Environment.NewLine;
  77. // str = str +"使用时间:" + thread.UserProcessorTime.ToString() + System.Environment.NewLine;
  78. // str = str + "当前状态:";
  79. // switch (thread.ThreadState)
  80. // {
  81. // case System.Diagnostics.ThreadState.Initialized:
  82. // str = str +"线程已经初始化但尚未启动";
  83. // break;
  84. // case System.Diagnostics.ThreadState.Ready:
  85. // str = str +"线程准备在下一个可用的处理器上运行";
  86. // break;
  87. // case System.Diagnostics.ThreadState.Running:
  88. // str = str +"当前正在使用处理器";
  89. // break;
  90. // case System.Diagnostics.ThreadState.Standby:
  91. // str = str +"线程将要使用处理器";
  92. // break;
  93. // case System.Diagnostics.ThreadState.Terminated:
  94. // str = str +"线程已完成执行并退出";
  95. // break;
  96. // case System.Diagnostics.ThreadState.Transition:
  97. // str = str +"线程在可以执行钱等待处理器之外的资源";
  98. // break;
  99. // case System.Diagnostics.ThreadState.Unknown:
  100. // str = str +"状态未知";
  101. // break;
  102. // case System.Diagnostics.ThreadState.Wait:
  103. // str = str +"正在等待外围操作完成或者资源释放";
  104. // break;
  105. // default:
  106. // break;
  107. // }
  108. // if (thread.ThreadState == System.Diagnostics.ThreadState.Wait)
  109. // {
  110. // str = str + System.Environment.NewLine +"等待原因:";
  111. // switch (thread.WaitReason)
  112. // {
  113. // case ThreadWaitReason.EventPairHigh:
  114. // str = str +"线程正在等待事件对高";
  115. // break;
  116. // case ThreadWaitReason.EventPairLow:
  117. // str = str +"线程正在等待事件对低";
  118. // break;
  119. // case ThreadWaitReason.ExecutionDelay:
  120. // str = str +"线程执行延迟";
  121. // break;
  122. // case ThreadWaitReason.Executive:
  123. // str = str +"线程正在等待计划程序";
  124. // break;
  125. // case ThreadWaitReason.FreePage:
  126. // str = str +"线程正在等待可用的虚拟内存页";
  127. // break;
  128. // case ThreadWaitReason.LpcReceive:
  129. // str = str +"线程正在等待本地过程调用到达";
  130. // break;
  131. // case ThreadWaitReason.LpcReply:
  132. // str = str +"线程正在等待对本地过程调用的回复到达";
  133. // break;
  134. // case ThreadWaitReason.PageIn:
  135. // str = str +"线程正在等待虚拟内存页到达内存";
  136. // break;
  137. // case ThreadWaitReason.PageOut:
  138. // str = str +"线程正在等待虚拟内存页写入磁盘";
  139. // break;
  140. // case ThreadWaitReason.Suspended:
  141. // str = str +"线程执行暂停";
  142. // break;
  143. // case ThreadWaitReason.SystemAllocation:
  144. // str = str +"线程正在等待系统分配";
  145. // break;
  146. // case ThreadWaitReason.Unknown:
  147. // str = str +"线程因位置原因而等待";
  148. // break;
  149. // case ThreadWaitReason.UserRequest:
  150. // str = str +"线程正在等待用户请求";
  151. // break;
  152. // case ThreadWaitReason.VirtualMemory:
  153. // str = str +"线程正在等待系统分配虚拟内存";
  154. // break;
  155. // default:
  156. // break;
  157. // }
  158. // }
  159. // Global.writeLog("ThreadsInfo:" + procs[0].Id.ToString() + "_" + procs[0].ProcessName, "Count:" + ps.Threads.Count.ToString(), str);
  160. //}
  161. //Global.writeLog("End");
  162. //foreach (Process process in procs)
  163. //{
  164. // if (process.ProcessName.Contains(WindowName))
  165. // {
  166. // MessageBox.Show($"Process_Name = ({process.ProcessName}), Id = {process.Id}");
  167. // }
  168. //}
  169. //return GetCurrentWindowHandle((uint)procs[0].Id);
  170. //Process[] processes = Process.GetProcesses();
  171. //foreach (Process process in processes)
  172. //{
  173. // if (process.ProcessName.Contains(WindowName))
  174. // {
  175. // MessageBox.Show($"ProcessName = ({process.ProcessName}), Id = {process.Id}");
  176. // }
  177. //}
  178. return hwnd;
  179. }
  180. private static Hashtable processWnd = null;
  181. public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
  182. //static User32API()
  183. //{
  184. // if (processWnd == null)
  185. // {
  186. // processWnd = new Hashtable();
  187. // }
  188. //}
  189. [DllImport("user32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
  190. public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
  191. [DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
  192. public static extern IntPtr GetParent(IntPtr hWnd);
  193. [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
  194. public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);
  195. [DllImport("user32.dll", EntryPoint = "IsWindow")]
  196. public static extern bool IsWindow(IntPtr hWnd);
  197. [DllImport("user32.dll", EntryPoint = "EnableWindow")]
  198. public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
  199. [DllImport("user32.dll", EntryPoint = "IsWindowEnabled")]
  200. public static extern bool IsWindowEnabled(IntPtr hWnd);
  201. [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
  202. public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
  203. [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
  204. public static extern bool SetForegroundWindow(IntPtr hWnd);
  205. [DllImport("user32.dll")]
  206. private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  207. [DllImport("user32.dll")]
  208. private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
  209. [DllImport("user32.dll")]
  210. private static extern bool EnumChildWindows(IntPtr hWndParent, WNDENUMPROC lpEnumFunc, IntPtr lParam);
  211. private static IntPtr _comWindowHandle = IntPtr.Zero;
  212. private static string _comWindowTitle = "";
  213. /// <summary>
  214. /// 查找银海COM读卡窗口并置顶
  215. /// </summary>
  216. /// <param name="parentHwnd">父窗口句柄(当前窗体)</param>
  217. /// <returns>找到的窗口句柄</returns>
  218. public static IntPtr FindAndSetTopComWindow(IntPtr parentHwnd)
  219. {
  220. _comWindowHandle = IntPtr.Zero;
  221. _comWindowTitle = "";
  222. // 枚举当前窗体的子窗口
  223. EnumChildWindows(parentHwnd, (hwnd, lParam) =>
  224. {
  225. // 使用更大的缓冲区获取完整标题
  226. StringBuilder title = new StringBuilder(512);
  227. GetWindowText(hwnd, title, 512);
  228. string windowTitle = title.ToString().Trim();
  229. // 检查窗口是否可见
  230. if (!IsWindowVisible(new HandleRef(null, hwnd)))
  231. {
  232. return true; // 不可见窗口跳过
  233. }
  234. // 银海读卡窗口标题包含"社会保障卡"或"统一鉴权"
  235. if (windowTitle.Contains("社会保障卡") || windowTitle.Contains("统一鉴权") ||
  236. windowTitle.Contains("电子社保卡"))
  237. {
  238. _comWindowHandle = hwnd;
  239. _comWindowTitle = windowTitle;
  240. // 置顶窗口
  241. SetWindowPos(hwnd, new IntPtr(-1), 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0040); // SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW
  242. SetForegroundWindow(hwnd);
  243. return false; // 停止枚举
  244. }
  245. // 备选:按类名查找
  246. StringBuilder className = new StringBuilder(256);
  247. GetClassName(hwnd, className, 256);
  248. string[] yinhaiClassNames = { "YHCardReader", "YHCard", "CardReader", "ReadCard", "#32770" };
  249. foreach (var name in yinhaiClassNames)
  250. {
  251. if (className.ToString().Contains(name) || className.ToString().Contains("YH") || className.ToString().Contains("Card"))
  252. {
  253. _comWindowHandle = hwnd;
  254. _comWindowTitle = windowTitle;
  255. // 置顶窗口
  256. SetWindowPos(hwnd, new IntPtr(-1), 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0040);
  257. SetForegroundWindow(hwnd);
  258. return false; // 停止枚举
  259. }
  260. }
  261. return true; // 继续枚举
  262. }, IntPtr.Zero);
  263. return _comWindowHandle;
  264. }
  265. /// <summary>
  266. /// 查找银海COM读卡窗口并置顶(枚举系统所有窗口)
  267. /// </summary>
  268. /// <param name="parentHwnd">父窗口句柄(用于参考,可传0)</param>
  269. /// <returns>找到的窗口句柄</returns>
  270. public static IntPtr FindAndSetTopComWindowAll(IntPtr parentHwnd)
  271. {
  272. _comWindowHandle = IntPtr.Zero;
  273. _comWindowTitle = "";
  274. // 枚举系统中所有顶级窗口
  275. EnumWindows((hwnd, lParam) =>
  276. {
  277. // 使用更大的缓冲区获取完整标题
  278. StringBuilder title = new StringBuilder(512);
  279. GetWindowText(hwnd, title, 512);
  280. string windowTitle = title.ToString().Trim();
  281. // 检查窗口是否可见
  282. if (!IsWindowVisible(new HandleRef(null, hwnd)))
  283. {
  284. return true; // 不可见窗口跳过
  285. }
  286. // 银海读卡窗口标题包含"社会保障卡"或"统一鉴权"
  287. if (windowTitle.Contains("社会保障卡") || windowTitle.Contains("统一鉴权") ||
  288. windowTitle.Contains("电子社保卡"))
  289. {
  290. _comWindowHandle = hwnd;
  291. _comWindowTitle = windowTitle;
  292. // 置顶窗口
  293. SetWindowPos(hwnd, new IntPtr(-1), 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0040); // SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW
  294. SetForegroundWindow(hwnd);
  295. return false; // 停止枚举
  296. }
  297. // 备选:按类名查找
  298. StringBuilder className = new StringBuilder(256);
  299. GetClassName(hwnd, className, 256);
  300. string[] yinhaiClassNames = { "YHCardReader", "YHCard", "CardReader", "ReadCard" };
  301. foreach (var name in yinhaiClassNames)
  302. {
  303. if (className.ToString().Contains(name) || className.ToString().Contains("YH"))
  304. {
  305. _comWindowHandle = hwnd;
  306. _comWindowTitle = windowTitle;
  307. // 置顶窗口
  308. SetWindowPos(hwnd, new IntPtr(-1), 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0040);
  309. SetForegroundWindow(hwnd);
  310. return false; // 停止枚举
  311. }
  312. }
  313. return true; // 继续枚举
  314. }, IntPtr.Zero);
  315. return _comWindowHandle;
  316. }
  317. /// <summary>
  318. /// 获取最后找到的COM窗口标题
  319. /// </summary>
  320. public static string GetComWindowTitle()
  321. {
  322. return _comWindowTitle;
  323. }
  324. [DllImport("kernel32.dll", EntryPoint = "SetLastError")]
  325. public static extern void SetLastError(uint dwErrCode);
  326. public static IntPtr GetCurrentWindowHandle()
  327. {
  328. IntPtr ptrWnd = IntPtr.Zero;
  329. uint uiPid = (uint)Process.GetCurrentProcess().Id; // 当前进程 ID
  330. object objWnd = processWnd[uiPid];
  331. if (objWnd != null)
  332. {
  333. ptrWnd = (IntPtr)objWnd;
  334. if (ptrWnd != IntPtr.Zero && IsWindow(ptrWnd)) // 从缓存中获取句柄
  335. {
  336. return ptrWnd;
  337. }
  338. else
  339. {
  340. ptrWnd = IntPtr.Zero;
  341. }
  342. }
  343. bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), uiPid);
  344. // 枚举窗口返回 false 并且没有错误号时表明获取成功
  345. if (!bResult && Marshal.GetLastWin32Error() == 0)
  346. {
  347. objWnd = processWnd[uiPid];
  348. if (objWnd != null)
  349. {
  350. ptrWnd = (IntPtr)objWnd;
  351. }
  352. }
  353. return ptrWnd;
  354. }
  355. private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
  356. {
  357. uint uiPid = 0;
  358. if (GetParent(hwnd) == IntPtr.Zero)
  359. {
  360. GetWindowThreadProcessId(hwnd, ref uiPid);
  361. if (uiPid == lParam) // 找到进程对应的主窗口句柄
  362. {
  363. processWnd[uiPid] = hwnd; // 把句柄缓存起来
  364. SetLastError(0); // 设置无错误
  365. return false; // 返回 false 以终止枚举窗口
  366. }
  367. }
  368. return true;
  369. }
  370. public static IntPtr GetCurrentWindowHandle(uint proid)
  371. {
  372. IntPtr ptrWnd = IntPtr.Zero;
  373. uint uiPid = proid;
  374. object objWnd = processWnd[uiPid];
  375. if (objWnd != null)
  376. {
  377. ptrWnd = (IntPtr)objWnd;
  378. if (ptrWnd != IntPtr.Zero && IsWindow(ptrWnd)) // 从缓存中获取句柄
  379. {
  380. return ptrWnd;
  381. }
  382. else
  383. {
  384. ptrWnd = IntPtr.Zero;
  385. }
  386. }
  387. bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), uiPid);
  388. // 枚举窗口返回 false 并且没有错误号时表明获取成功
  389. if (!bResult && Marshal.GetLastWin32Error() == 0)
  390. {
  391. objWnd = processWnd[uiPid];
  392. if (objWnd != null)
  393. {
  394. ptrWnd = (IntPtr)objWnd;
  395. }
  396. }
  397. return ptrWnd;
  398. }
  399. }
  400. }