跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

浏览文件

Win32API.cs

362 行 · 12.8 KB历史下载
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5using System.Runtime.InteropServices;
6using System.Text;
7using System.Threading.Tasks;
8using System.Windows;
9
10namespace Core.Librarys
11{
12 public static class Win32API
13 {
14 [DllImport("user32.dll")]
15 public static extern IntPtr GetForegroundWindow();
16 [DllImport("user32.dll")]
17 public static extern IntPtr SetForegroundWindow(IntPtr hwnd);
18 public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
19 IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
20 [DllImport("user32.dll")]
21 public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
22 hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
23 uint idThread, uint dwFlags);
24
25 [DllImport("user32.dll")]
26 public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
27
28 [DllImport("user32.dll", CharSet = CharSet.Auto)]
29 public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
30
31 [DllImport("psapi.dll", SetLastError = true)]
32 public static extern int GetModuleFileNameExA(IntPtr hProcess, IntPtr hModule, StringBuilder lpFilename, int nSize);
33 //[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
34 //static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpExeName, ref uint lpdwSize);
35
36 [DllImport("kernel32.dll", SetLastError = true)]
37 public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
38
39 [DllImport("kernel32.dll", SetLastError = true)]
40 public static extern bool CloseHandle(UIntPtr hObject);
41 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
42 public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
43
44
45 internal struct WINDOWINFO
46 {
47 public uint ownerpid;
48 public uint childpid;
49 }
50
51 [DllImport("user32.dll", SetLastError = true)]
52 public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
53
54 [DllImport("user32", SetLastError = true)]
55 [return: MarshalAs(UnmanagedType.Bool)]
56 public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);
57
58
59
60 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
61 public static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
62
63
64 public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
65
66 public const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
67 public const UInt32 PROCESS_VM_READ = 0x010;
68
69 //private const uint WINEVENT_OUTOFCONTEXT = 0;
70 //private const uint EVENT_SYSTEM_FOREGROUND = 3;
71 public static string UWP_AppName(IntPtr hWnd, uint pID)
72 {
73 WINDOWINFO windowinfo = new WINDOWINFO();
74 windowinfo.ownerpid = pID;
75 windowinfo.childpid = windowinfo.ownerpid;
76
77 IntPtr pWindowinfo = Marshal.AllocHGlobal(Marshal.SizeOf(windowinfo));
78
79 Marshal.StructureToPtr(windowinfo, pWindowinfo, false);
80
81 EnumWindowProc lpEnumFunc = new EnumWindowProc(EnumChildWindowsCallback);
82 EnumChildWindows(hWnd, lpEnumFunc, pWindowinfo);
83
84 windowinfo = (WINDOWINFO)Marshal.PtrToStructure(pWindowinfo, typeof(WINDOWINFO));
85 if (windowinfo.childpid == windowinfo.ownerpid)
86 {
87 return null;
88 }
89 IntPtr proc;
90 if ((proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, (int)windowinfo.childpid)) == IntPtr.Zero) return null;
91
92 int capacity = 2000;
93 StringBuilder sb = new StringBuilder(capacity);
94 QueryFullProcessImageName(proc, 0, sb, ref capacity);
95
96 Marshal.FreeHGlobal(pWindowinfo);
97
98 return sb.ToString(0, capacity);
99 }
100
101 private static bool EnumChildWindowsCallback(IntPtr hWnd, IntPtr lParam)
102 {
103 WINDOWINFO info = (WINDOWINFO)Marshal.PtrToStructure(lParam, typeof(WINDOWINFO));
104
105 uint pID;
106 GetWindowThreadProcessId(hWnd, out pID);
107
108 if (pID != info.ownerpid) info.childpid = pID;
109
110 Marshal.StructureToPtr(info, lParam, true);
111
112 return true;
113 }
114
115
116 /// <summary>
117 /// 获取鼠标坐标
118 /// </summary>
119 /// <param name="lpPoint"></param>
120 /// <returns></returns>
121 [DllImport("user32.dll", SetLastError = true)]
122 [return: MarshalAs(UnmanagedType.Bool)]
123 private static extern bool GetCursorPos(out POINT lpPoint);
124
125 [StructLayout(LayoutKind.Sequential)]
126 public struct POINT
127 {
128 public int X;
129 public int Y;
130
131 public static implicit operator Point(POINT point)
132 {
133 return new Point(point.X, point.Y);
134 }
135 }
136
137 public static Point GetCursorPosition()
138 {
139 POINT lpPoint;
140 GetCursorPos(out lpPoint);
141 return lpPoint;
142 }
143
144 #region 声音判断
145 /// <summary>
146 /// 指示系统当前是否在播放声音
147 /// </summary>
148 /// <returns></returns>
149 public static bool IsWindowsPlayingSound()
150 {
151 try
152 {
153 IMMDeviceEnumerator enumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
154 IMMDevice speakers = enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
155 IAudioMeterInformation meter = (IAudioMeterInformation)speakers.Activate(typeof(IAudioMeterInformation).GUID, 0, IntPtr.Zero);
156 if (meter != null)
157 {
158
159 float value = meter.GetPeakValue();
160
161 // this is a bit tricky. 0 is the official "no sound" value
162 // but for example, if you open a video and plays/stops with it (w/o killing the app/window/stream),
163 // the value will not be zero, but something really small (around 1E-09)
164 // so, depending on your context, it is up to you to decide
165 // if you want to test for 0 or for a small value
166 return value > 1E-08;
167 }
168 else
169 {
170 return false;
171 }
172 }
173 catch (Exception ec)
174 {
175 Logger.Error(ec.Message);
176 return false;
177 }
178 }
179
180 [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
181 private class MMDeviceEnumerator
182 {
183 }
184
185 private enum EDataFlow
186 {
187 eRender,
188 eCapture,
189 eAll,
190 }
191
192 private enum ERole
193 {
194 eConsole,
195 eMultimedia,
196 eCommunications,
197 }
198
199 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
200 private interface IMMDeviceEnumerator
201 {
202 void NotNeeded();
203 IMMDevice GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role);
204 // the rest is not defined/needed
205 }
206
207 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D666063F-1587-4E43-81F1-B948E807363F")]
208 private interface IMMDevice
209 {
210 [return: MarshalAs(UnmanagedType.IUnknown)]
211 object Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams);
212 // the rest is not defined/needed
213 }
214
215 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064")]
216 private interface IAudioMeterInformation
217 {
218 float GetPeakValue();
219 // the rest is not defined/needed
220 }
221 #endregion
222
223 #region 键盘钩子
224 [StructLayout(LayoutKind.Sequential)]
225 public class KeyboardHookStruct
226 {
227 public int vkCode; //定一个虚拟键码。该代码必须有一个价值的范围1至254
228 public int scanCode; // 指定的硬件扫描码的关键
229 public int flags; // 键标志
230 public int time; // 指定的时间戳记的这个讯息
231 public int dwExtraInfo; // 指定额外信息相关的信息
232 }
233
234 private const int WH_KEYBOARD_LL = 13;
235 public const int WM_KEYDOWN = 0x0100;
236 private const int WH_MOUSE_LL = 14;
237 public const int WM_LBUTTONDBLCLK = 0x202;
238 public const int WM_WHEEL = 0x20a;
239 public const int WM_KEYUP = 0x101;
240 public const int WM_SYSKEYDOWN = 0x104;
241 public const int WM_SYSKEYUP = 0x105;
242 /// <summary>
243 /// 设置键盘钩子
244 /// </summary>
245 /// <param name="proc"></param>
246 /// <returns></returns>
247 public static IntPtr SetKeyboardHook(LowLevelKeyboardProc proc)
248 {
249 using (Process curProcess = Process.GetCurrentProcess())
250 using (ProcessModule curModule = curProcess.MainModule)
251 {
252 return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
253 GetModuleHandle(curModule.ModuleName), 0);
254 }
255 }
256
257
258 /// <summary>
259 /// 设置鼠标钩子
260 /// </summary>
261 /// <param name="proc"></param>
262 /// <returns></returns>
263 public static IntPtr SetMouseHook(LowLevelKeyboardProc proc)
264 {
265 using (Process curProcess = Process.GetCurrentProcess())
266 using (ProcessModule curModule = curProcess.MainModule)
267 {
268 return SetWindowsHookEx(WH_MOUSE_LL, proc,
269 GetModuleHandle(curModule.ModuleName), 0);
270 }
271 }
272 public delegate IntPtr LowLevelKeyboardProc(
273 int nCode, IntPtr wParam, IntPtr lParam);
274
275
276
277 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
278 public static extern IntPtr SetWindowsHookEx(int idHook,
279 LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
280
281 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
282 [return: MarshalAs(UnmanagedType.Bool)]
283 public static extern bool UnhookWindowsHookEx(IntPtr hhk);
284
285 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
286 public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
287 IntPtr wParam, IntPtr lParam);
288
289 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
290 public static extern IntPtr GetModuleHandle(string lpModuleName);
291 #endregion
292
293 #region 获取窗口信息
294 [DllImport("user32.dll")]
295 [return: MarshalAs(UnmanagedType.Bool)]
296 public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
297
298 [StructLayout(LayoutKind.Sequential)]
299 public struct RECT
300 {
301 public int Left; // x position of upper-left corner
302 public int Top; // y position of upper-left corner
303 public int Right; // x position of lower-right corner
304 public int Bottom; // y position of lower-right corner
305
306 public int Width
307 {
308 get
309 {
310 return Right - Left;
311 }
312 }
313 public int Height
314 {
315 get
316 {
317 return Bottom - Top;
318 }
319 }
320
321 }
322 public static RECT GetWindowRect(IntPtr handle_)
323 {
324 try
325 {
326 GetWindowRect(handle_, out RECT rect);
327 return rect;
328
329 }
330 catch (Exception e)
331 {
332 return new RECT()
333 {
334 Left = 0,
335 Bottom = 0,
336 Right = 0,
337 Top = 0
338 };
339 }
340 }
341 #endregion
342
343 [DllImport("user32.dll", CharSet = CharSet.Auto)]
344 public static extern int GetWindowTextLength(IntPtr hWnd);
345 [DllImport("user32.dll", CharSet = CharSet.Auto)]
346 public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
347 public static string GetWindowClassName(IntPtr handle_)
348 {
349 try
350 {
351 StringBuilder stringBuilder = new StringBuilder(256);
352 GetClassName(handle_, stringBuilder, stringBuilder.Capacity);
353
354 return stringBuilder.ToString();
355 }
356 catch (Exception e)
357 {
358 return string.Empty;
359 }
360 }
361 }
362}