提交记录新增Core/Enums/AppType.cs+27 −0看文件
新增Core/Event/AppActiveChangedEventArgs.cs+34 −0看文件
新增Core/Event/AppDurationUpdatedEventArgs.cs+47 −0看文件
新增Core/Event/AppObserverEventHandler.cs+8 −0看文件
新增Core/Event/AppTimerEventHandler.cs+8 −0看文件
修改Core/Librarys/Win32API.cs+34 −1看文件
新增Core/Models/AppObserver/AppInfo.cs+57 −0看文件
新增Core/Models/AppObserver/WindowInfo.cs+54 −0看文件
新增Core/Servicers/Instances/AppManager.cs+354 −0看文件
修改Core/Servicers/Instances/AppObserver.cs+70 −139看文件
新增Core/Servicers/Instances/AppTimerServicer.cs+170 −0看文件
修改Core/Servicers/Instances/Data.cs+114 −64看文件
修改Core/Servicers/Instances/Main.cs+43 −124看文件
新增Core/Servicers/Instances/WindowManager.cs+57 −0看文件
新增Core/Servicers/Interfaces/IAppManager.cs+20 −0看文件
修改Core/Servicers/Interfaces/IAppObserver.cs+1 −1看文件
新增Core/Servicers/Interfaces/IAppTimerServicer.cs+31 −0看文件
修改Core/Servicers/Interfaces/IData.cs+1 −1看文件
新增Core/Servicers/Interfaces/IWindowManager.cs+20 −0看文件
修改UI/App.xaml.cs+5 −2看文件
修改UI/Servicers/StatusBarIconServicer.cs+3 −2看文件
| @@ -0,0 +1,27 @@ | ||
| 1 | 新增:using System; | |
| 2 | 新增:using System.Collections.Generic; | |
| 3 | 新增:using System.Linq; | |
| 4 | 新增:using System.Text; | |
| 5 | 新增:using System.Threading.Tasks; | |
| 6 | 新增: | |
| 7 | 新增:namespace Core.Enums | |
| 8 | 新增:{ | |
| 9 | 新增: /// <summary> | |
| 10 | 新增: /// 应用类型 | |
| 11 | 新增: /// </summary> | |
| 12 | 新增: public enum AppType | |
| 13 | 新增: { | |
| 14 | 新增: /// <summary> | |
| 15 | 新增: /// 传统应用 | |
| 16 | 新增: /// </summary> | |
| 17 | 新增: Win32, | |
| 18 | 新增: /// <summary> | |
| 19 | 新增: /// UWP | |
| 20 | 新增: /// </summary> | |
| 21 | 新增: UWP, | |
| 22 | 新增: /// <summary> | |
| 23 | 新增: /// 系统组件,如任务栏、开始菜单、状态栏、系统登录界面等 | |
| 24 | 新增: /// </summary> | |
| 25 | 新增: SystemComponent | |
| 26 | 新增: } | |
| 27 | 新增:} | |
| @@ -0,0 +1,34 @@ | ||
| 1 | 新增:using Core.Models.AppObserver; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增: | |
| 8 | 新增:namespace Core.Event | |
| 9 | 新增:{ | |
| 10 | 新增: /// <summary> | |
| 11 | 新增: /// 应用活跃状态变更事件参数 | |
| 12 | 新增: /// </summary> | |
| 13 | 新增: public class AppActiveChangedEventArgs | |
| 14 | 新增: { | |
| 15 | 新增: /// <summary> | |
| 16 | 新增: /// 激活时间 | |
| 17 | 新增: /// </summary> | |
| 18 | 新增: public DateTime ActiveTime { get; } | |
| 19 | 新增: /// <summary> | |
| 20 | 新增: /// 应用信息 | |
| 21 | 新增: /// </summary> | |
| 22 | 新增: public AppInfo App { get; } | |
| 23 | 新增: /// <summary> | |
| 24 | 新增: /// 窗口信息 | |
| 25 | 新增: /// </summary> | |
| 26 | 新增: public WindowInfo Window { get; } | |
| 27 | 新增: public AppActiveChangedEventArgs(AppInfo app_, WindowInfo window_, DateTime activeTime_) | |
| 28 | 新增: { | |
| 29 | 新增: App = app_; | |
| 30 | 新增: Window = window_; | |
| 31 | 新增: ActiveTime = activeTime_; | |
| 32 | 新增: } | |
| 33 | 新增: } | |
| 34 | 新增:} | |
| @@ -0,0 +1,47 @@ | ||
| 1 | 新增:using Core.Models.AppObserver; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增: | |
| 8 | 新增:namespace Core.Event | |
| 9 | 新增:{ | |
| 10 | 新增: public class AppDurationUpdatedEventArgs | |
| 11 | 新增: { | |
| 12 | 新增: /// <summary> | |
| 13 | 新增: /// 使用时长 | |
| 14 | 新增: /// </summary> | |
| 15 | 新增: public int Duration { get; } | |
| 16 | 新增: /// <summary> | |
| 17 | 新增: /// 激活时间 | |
| 18 | 新增: /// </summary> | |
| 19 | 新增: public DateTime ActiveTime { get; } | |
| 20 | 新增: /// <summary> | |
| 21 | 新增: /// 结束时间 | |
| 22 | 新增: /// </summary> | |
| 23 | 新增: public DateTime EndTime { get; } | |
| 24 | 新增: /// <summary> | |
| 25 | 新增: /// 应用信息 | |
| 26 | 新增: /// </summary> | |
| 27 | 新增: public AppInfo App { get; } | |
| 28 | 新增: /// <summary> | |
| 29 | 新增: /// 窗口信息 | |
| 30 | 新增: /// </summary> | |
| 31 | 新增: public WindowInfo Window { get; } | |
| 32 | 新增: public AppDurationUpdatedEventArgs(int duration_, AppInfo app_, WindowInfo window_, DateTime activeTime_, DateTime endTime_) | |
| 33 | 新增: { | |
| 34 | 新增: Duration = duration_; | |
| 35 | 新增: App = app_; | |
| 36 | 新增: Window = window_; | |
| 37 | 新增: ActiveTime = activeTime_; | |
| 38 | 新增: EndTime = endTime_; | |
| 39 | 新增: } | |
| 40 | 新增: | |
| 41 | 新增: public override string ToString() | |
| 42 | 新增: { | |
| 43 | 新增: return $"Duration:{Duration},App:{App},Window:{Window},ActiveTime:{ActiveTime},EndTime:{EndTime}"; | |
| 44 | 新增: | |
| 45 | 新增: } | |
| 46 | 新增: } | |
| 47 | 新增:} | |
| @@ -0,0 +1,8 @@ | ||
| 1 | 新增:using Core.Event; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增: | |
| 8 | 新增:public delegate void AppObserverEventHandler(object sender, AppActiveChangedEventArgs e); | |
| @@ -0,0 +1,8 @@ | ||
| 1 | 新增:using Core.Event; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增: | |
| 8 | 新增:public delegate void AppTimerEventHandler(object sender, AppDurationUpdatedEventArgs e); | |
| @@ -38,7 +38,8 @@ namespace Core.Librarys | ||
| 38 | 38 | |
| 39 | 39 | [DllImport("kernel32.dll", SetLastError = true)] |
| 40 | 40 | public static extern bool CloseHandle(UIntPtr hObject); |
| 41 | 删除: | |
| 41 | 新增: [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
| 42 | 新增: public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); | |
| 42 | 43 | |
| 43 | 44 | |
| 44 | 45 | internal struct WINDOWINFO |
| @@ -318,12 +319,44 @@ namespace Core.Librarys | ||
| 318 | 319 | } |
| 319 | 320 | |
| 320 | 321 | } |
| 322 | 新增: public static RECT GetWindowRect(IntPtr handle_) | |
| 323 | 新增: { | |
| 324 | 新增: try | |
| 325 | 新增: { | |
| 326 | 新增: GetWindowRect(handle_, out RECT rect); | |
| 327 | 新增: return rect; | |
| 321 | 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 | 新增: } | |
| 322 | 341 | #endregion |
| 323 | 342 | |
| 324 | 343 | [DllImport("user32.dll", CharSet = CharSet.Auto)] |
| 325 | 344 | public static extern int GetWindowTextLength(IntPtr hWnd); |
| 326 | 345 | [DllImport("user32.dll", CharSet = CharSet.Auto)] |
| 327 | 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 | 新增: } | |
| 328 | 361 | } |
| 329 | 362 | } |
| @@ -0,0 +1,57 @@ | ||
| 1 | 新增:using Core.Enums; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Security.AccessControl; | |
| 6 | 新增:using System.Text; | |
| 7 | 新增:using System.Threading.Tasks; | |
| 8 | 新增: | |
| 9 | 新增:namespace Core.Models.AppObserver | |
| 10 | 新增:{ | |
| 11 | 新增: /// <summary> | |
| 12 | 新增: /// 应用信息 | |
| 13 | 新增: /// </summary> | |
| 14 | 新增: public class AppInfo | |
| 15 | 新增: { | |
| 16 | 新增: /// <summary> | |
| 17 | 新增: /// 进程ID | |
| 18 | 新增: /// </summary> | |
| 19 | 新增: public int PID { get; } | |
| 20 | 新增: /// <summary> | |
| 21 | 新增: /// 应用类型 | |
| 22 | 新增: /// </summary> | |
| 23 | 新增: public AppType Type { get; } | |
| 24 | 新增: /// <summary> | |
| 25 | 新增: /// 进程名称 | |
| 26 | 新增: /// </summary> | |
| 27 | 新增: public string Process { get; } | |
| 28 | 新增: /// <summary> | |
| 29 | 新增: /// 应用描述 | |
| 30 | 新增: /// </summary> | |
| 31 | 新增: public string Description { get; } | |
| 32 | 新增: /// <summary> | |
| 33 | 新增: /// 可执行文件路径 | |
| 34 | 新增: /// </summary> | |
| 35 | 新增: public string ExecutablePath { get; } | |
| 36 | 新增: /// <summary> | |
| 37 | 新增: /// 窗口句柄 | |
| 38 | 新增: /// </summary> | |
| 39 | 新增: public IntPtr WindowHandle { get; } | |
| 40 | 新增: public AppInfo(IntPtr windowHandle_, int pid_, string process_, string description_, string executablePath_, AppType type_ = AppType.Win32) | |
| 41 | 新增: { | |
| 42 | 新增: WindowHandle = windowHandle_; | |
| 43 | 新增: PID = pid_; | |
| 44 | 新增: Process = process_; | |
| 45 | 新增: Description = description_; | |
| 46 | 新增: ExecutablePath = executablePath_; | |
| 47 | 新增: Type = type_; | |
| 48 | 新增: } | |
| 49 | 新增: | |
| 50 | 新增: public override string ToString() | |
| 51 | 新增: { | |
| 52 | 新增: return $"WindowHandle:{WindowHandle},PID:{PID},ProcessName:{Process},Description:{Description},ExecutablePath:{ExecutablePath},Type:{Type}"; | |
| 53 | 新增: } | |
| 54 | 新增: | |
| 55 | 新增: public static AppInfo Empty = new AppInfo(IntPtr.Zero, 0, string.Empty, string.Empty, string.Empty); | |
| 56 | 新增: } | |
| 57 | 新增:} | |
| @@ -0,0 +1,54 @@ | ||
| 1 | 新增:using System; | |
| 2 | 新增:using System.Collections.Generic; | |
| 3 | 新增:using System.Linq; | |
| 4 | 新增:using System.Text; | |
| 5 | 新增:using System.Threading.Tasks; | |
| 6 | 新增: | |
| 7 | 新增:namespace Core.Models.AppObserver | |
| 8 | 新增:{ | |
| 9 | 新增: /// <summary> | |
| 10 | 新增: /// 窗口信息 | |
| 11 | 新增: /// </summary> | |
| 12 | 新增: public class WindowInfo | |
| 13 | 新增: { | |
| 14 | 新增: /// <summary> | |
| 15 | 新增: /// 窗口类名 | |
| 16 | 新增: /// </summary> | |
| 17 | 新增: public string ClassName { get; } | |
| 18 | 新增: /// <summary> | |
| 19 | 新增: /// 窗口标题 | |
| 20 | 新增: /// </summary> | |
| 21 | 新增: public string Title { get; } | |
| 22 | 新增: /// <summary> | |
| 23 | 新增: /// 窗口句柄 | |
| 24 | 新增: /// </summary> | |
| 25 | 新增: public IntPtr Handle { get; } | |
| 26 | 新增: /// <summary> | |
| 27 | 新增: /// 窗口宽度 | |
| 28 | 新增: /// </summary> | |
| 29 | 新增: public int Width { get; } | |
| 30 | 新增: /// <summary> | |
| 31 | 新增: /// 窗口高度 | |
| 32 | 新增: /// </summary> | |
| 33 | 新增: public int Height { get; } | |
| 34 | 新增: public int X { get; } | |
| 35 | 新增: public int Y { get; } | |
| 36 | 新增: | |
| 37 | 新增: public WindowInfo(string className_, string title_, IntPtr handle_, int width_, int height_, int x_, int y_) | |
| 38 | 新增: { | |
| 39 | 新增: ClassName = className_; | |
| 40 | 新增: Title = title_; | |
| 41 | 新增: Handle = handle_; | |
| 42 | 新增: Width = width_; | |
| 43 | 新增: Height = height_; | |
| 44 | 新增: X = x_; | |
| 45 | 新增: Y = y_; | |
| 46 | 新增: } | |
| 47 | 新增: | |
| 48 | 新增: public override string ToString() | |
| 49 | 新增: { | |
| 50 | 新增: return $"ClassName:{ClassName},Title:{Title},Handle:{Handle},Width:{Width},Height:{Height},X:{X},Y:{Y}"; | |
| 51 | 新增: } | |
| 52 | 新增: public static WindowInfo Empty = new WindowInfo(string.Empty, string.Empty, IntPtr.Zero, 0, 0, 0, 0); | |
| 53 | 新增: } | |
| 54 | 新增:} | |
| @@ -0,0 +1,354 @@ | ||
| 1 | 新增:using Core.Enums; | |
| 2 | 新增:using Core.Librarys; | |
| 3 | 新增:using Core.Models.AppObserver; | |
| 4 | 新增:using Core.Servicers.Interfaces; | |
| 5 | 新增:using System; | |
| 6 | 新增:using System.Collections.Generic; | |
| 7 | 新增:using System.Diagnostics; | |
| 8 | 新增:using System.IO; | |
| 9 | 新增:using System.Linq; | |
| 10 | 新增:using System.Management; | |
| 11 | 新增:using System.Runtime.InteropServices; | |
| 12 | 新增:using System.Text; | |
| 13 | 新增:using System.Text.RegularExpressions; | |
| 14 | 新增:using System.Threading; | |
| 15 | 新增:using System.Threading.Tasks; | |
| 16 | 新增: | |
| 17 | 新增:namespace Core.Servicers.Instances | |
| 18 | 新增:{ | |
| 19 | 新增: public class AppManager : IAppManager | |
| 20 | 新增: { | |
| 21 | 新增: #region win32api | |
| 22 | 新增: [DllImport("user32.dll", CharSet = CharSet.Auto)] | |
| 23 | 新增: public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); | |
| 24 | 新增: [DllImport("kernel32.dll", SetLastError = true)] | |
| 25 | 新增: public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId); | |
| 26 | 新增: [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
| 27 | 新增: public static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize); | |
| 28 | 新增: public const int PROCESS_QUERY_INFORMATION = 0x0400; | |
| 29 | 新增: public const int PROCESS_VM_READ = 0x0010; | |
| 30 | 新增: | |
| 31 | 新增: [DllImport("psapi.dll", SetLastError = true)] | |
| 32 | 新增: public static extern uint GetModuleBaseName(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, ref uint nSize); | |
| 33 | 新增: | |
| 34 | 新增: [DllImport("kernel32.dll", SetLastError = true)] | |
| 35 | 新增: public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); | |
| 36 | 新增: | |
| 37 | 新增: [DllImport("kernel32.dll", SetLastError = true)] | |
| 38 | 新增: [return: MarshalAs(UnmanagedType.Bool)] | |
| 39 | 新增: public static extern bool CloseHandle(IntPtr hObject); | |
| 40 | 新增: | |
| 41 | 新增: [StructLayout(LayoutKind.Sequential)] | |
| 42 | 新增: public struct GUITHREADINFO | |
| 43 | 新增: { | |
| 44 | 新增: public uint cbSize; | |
| 45 | 新增: public uint flags; | |
| 46 | 新增: public IntPtr hwndActive; | |
| 47 | 新增: public IntPtr hwndFocus; | |
| 48 | 新增: public IntPtr hwndCapture; | |
| 49 | 新增: public IntPtr hwndMenuOwner; | |
| 50 | 新增: public IntPtr hwndMoveSize; | |
| 51 | 新增: public IntPtr hwndCaret; | |
| 52 | 新增: public RECT rcCaret; | |
| 53 | 新增: } | |
| 54 | 新增: | |
| 55 | 新增: [StructLayout(LayoutKind.Sequential)] | |
| 56 | 新增: public struct RECT | |
| 57 | 新增: { | |
| 58 | 新增: public int Left; | |
| 59 | 新增: public int Top; | |
| 60 | 新增: public int Right; | |
| 61 | 新增: public int Bottom; | |
| 62 | 新增: } | |
| 63 | 新增: | |
| 64 | 新增: [DllImport("user32.dll")] | |
| 65 | 新增: [return: MarshalAs(UnmanagedType.Bool)] | |
| 66 | 新增: public static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui); | |
| 67 | 新增: #endregion | |
| 68 | 新增: | |
| 69 | 新增: private Dictionary<string, AppInfo> _apps; | |
| 70 | 新增: private int _outTime = 5000; | |
| 71 | 新增: //private string _windowsVersionName; | |
| 72 | 新增: public AppManager() | |
| 73 | 新增: { | |
| 74 | 新增: _apps = new Dictionary<string, AppInfo>(); | |
| 75 | 新增: //_windowsVersionName = SystemCommon.GetWindowsVersionName(); | |
| 76 | 新增: } | |
| 77 | 新增: | |
| 78 | 新增: public AppInfo GetAppInfo(IntPtr hwnd_) | |
| 79 | 新增: { | |
| 80 | 新增: try | |
| 81 | 新增: { | |
| 82 | 新增: AppInfo app; | |
| 83 | 新增: var sw = Stopwatch.StartNew(); | |
| 84 | 新增: GetWindowThreadProcessId(hwnd_, out int processId); | |
| 85 | 新增: sw = Stopwatch.StartNew(); | |
| 86 | 新增: string processName = GetAppProcessName(processId); | |
| 87 | 新增: string executablePath = string.Empty; | |
| 88 | 新增: string description = string.Empty; | |
| 89 | 新增: AppType appType = AppType.Win32; | |
| 90 | 新增: | |
| 91 | 新增: sw = Stopwatch.StartNew(); | |
| 92 | 新增: if (string.IsNullOrEmpty(processName)) | |
| 93 | 新增: { | |
| 94 | 新增: return AppInfo.Empty; | |
| 95 | 新增: } | |
| 96 | 新增: else if (_apps.ContainsKey(processName)) | |
| 97 | 新增: { | |
| 98 | 新增: return _apps[processName]; | |
| 99 | 新增: } | |
| 100 | 新增: else if (processName == "ApplicationFrameHost") | |
| 101 | 新增: { | |
| 102 | 新增: // uwp应用 | |
| 103 | 新增: // 尝试直接获取可执行文件路径,如果为空表示刚启动或者全屏状态 | |
| 104 | 新增: executablePath = GetUWPAPPExecutablePath(hwnd_, (uint)processId); | |
| 105 | 新增: appType = AppType.UWP; | |
| 106 | 新增: | |
| 107 | 新增: if (string.IsNullOrEmpty(executablePath)) | |
| 108 | 新增: { | |
| 109 | 新增: // 刚启动的程序需要延迟获取 | |
| 110 | 新增: int duration = 0; | |
| 111 | 新增: while (processName == "ApplicationFrameHost") | |
| 112 | 新增: { | |
| 113 | 新增: Thread.Sleep(100); | |
| 114 | 新增: duration += 100; | |
| 115 | 新增: if (duration >= _outTime) | |
| 116 | 新增: { | |
| 117 | 新增: break; | |
| 118 | 新增: } | |
| 119 | 新增: executablePath = GetUWPAPPExecutablePath(hwnd_, (uint)processId); | |
| 120 | 新增: | |
| 121 | 新增: if (string.IsNullOrEmpty(executablePath)) | |
| 122 | 新增: { | |
| 123 | 新增: // 可能是全屏状态 | |
| 124 | 新增: int pid = GetFullScreenUWPPID(); | |
| 125 | 新增: string name = GetAppProcessName(pid); | |
| 126 | 新增: | |
| 127 | 新增: processName = string.IsNullOrEmpty(name) ? processName : name; | |
| 128 | 新增: executablePath = GetAppExecutablePath(pid); | |
| 129 | 新增: processId = pid; | |
| 130 | 新增: } | |
| 131 | 新增: else | |
| 132 | 新增: { | |
| 133 | 新增: processName = Path.GetFileNameWithoutExtension(executablePath); | |
| 134 | 新增: } | |
| 135 | 新增: } | |
| 136 | 新增: } | |
| 137 | 新增: else | |
| 138 | 新增: { | |
| 139 | 新增: processName = Path.GetFileNameWithoutExtension(executablePath); | |
| 140 | 新增: } | |
| 141 | 新增: } | |
| 142 | 新增: //else if (_windowsVersionName.Contains("Windows 7") && processName == "dllhost") | |
| 143 | 新增: //{ | |
| 144 | 新增: // // Windows7的COM应用 | |
| 145 | 新增: | |
| 146 | 新增: //} | |
| 147 | 新增: else | |
| 148 | 新增: { | |
| 149 | 新增: executablePath = GetAppExecutablePath(processId); | |
| 150 | 新增: } | |
| 151 | 新增: | |
| 152 | 新增: if (!string.IsNullOrEmpty(executablePath)) | |
| 153 | 新增: { | |
| 154 | 新增: FileVersionInfo info = FileVersionInfo.GetVersionInfo(executablePath); | |
| 155 | 新增: description = info.FileDescription; | |
| 156 | 新增: } | |
| 157 | 新增: | |
| 158 | 新增: appType = IsSystemComponent(processName, hwnd_) ? AppType.SystemComponent : AppType.Win32; | |
| 159 | 新增: app = new AppInfo(hwnd_, processId, processName, description, executablePath, appType); | |
| 160 | 新增: if (processName != "explorer" && !_apps.ContainsKey(processName)) | |
| 161 | 新增: { | |
| 162 | 新增: _apps.Add(processName, app); | |
| 163 | 新增: } | |
| 164 | 新增: return app; | |
| 165 | 新增: } | |
| 166 | 新增: catch (Exception ex) | |
| 167 | 新增: { | |
| 168 | 新增: Logger.Error(ex.ToString()); | |
| 169 | 新增: return AppInfo.Empty; | |
| 170 | 新增: } | |
| 171 | 新增: } | |
| 172 | 新增: | |
| 173 | 新增: private string GetAppProcessName(int processId_) | |
| 174 | 新增: { | |
| 175 | 新增: Process process = Process.GetProcessById(processId_); | |
| 176 | 新增: return process.ProcessName; | |
| 177 | 新增: } | |
| 178 | 新增: | |
| 179 | 新增: private string GetAppExecutablePath(int processId_) | |
| 180 | 新增: { | |
| 181 | 新增: IntPtr processHandle = IntPtr.Zero; | |
| 182 | 新增: processHandle = OpenProcess(0x001F0FFF, false, processId_); | |
| 183 | 新增: string executablePath = string.Empty; | |
| 184 | 新增: if (processHandle != IntPtr.Zero) | |
| 185 | 新增: { | |
| 186 | 新增: int MaxPathLength = 4096; | |
| 187 | 新增: var buffer = new StringBuilder(MaxPathLength); | |
| 188 | 新增: QueryFullProcessImageName(processHandle, 0, buffer, ref MaxPathLength); | |
| 189 | 新增: executablePath = buffer.ToString(); | |
| 190 | 新增: } | |
| 191 | 新增: return executablePath; | |
| 192 | 新增: } | |
| 193 | 新增: | |
| 194 | 新增: internal struct WINDOWINFO | |
| 195 | 新增: { | |
| 196 | 新增: public uint ownerpid; | |
| 197 | 新增: public uint childpid; | |
| 198 | 新增: } | |
| 199 | 新增: | |
| 200 | 新增: private string GetUWPAPPExecutablePath(IntPtr hWnd_, uint pID_) | |
| 201 | 新增: { | |
| 202 | 新增: WINDOWINFO windowinfo = new WINDOWINFO(); | |
| 203 | 新增: windowinfo.ownerpid = pID_; | |
| 204 | 新增: windowinfo.childpid = windowinfo.ownerpid; | |
| 205 | 新增: | |
| 206 | 新增: IntPtr pWindowinfo = Marshal.AllocHGlobal(Marshal.SizeOf(windowinfo)); | |
| 207 | 新增: | |
| 208 | 新增: Marshal.StructureToPtr(windowinfo, pWindowinfo, false); | |
| 209 | 新增: | |
| 210 | 新增: Win32API.EnumWindowProc lpEnumFunc = new Win32API.EnumWindowProc(EnumChildWindowsCallback); | |
| 211 | 新增: Win32API.EnumChildWindows(hWnd_, lpEnumFunc, pWindowinfo); | |
| 212 | 新增: | |
| 213 | 新增: windowinfo = (WINDOWINFO)Marshal.PtrToStructure(pWindowinfo, typeof(WINDOWINFO)); | |
| 214 | 新增: if (windowinfo.childpid == windowinfo.ownerpid) | |
| 215 | 新增: { | |
| 216 | 新增: return null; | |
| 217 | 新增: } | |
| 218 | 新增: IntPtr proc; | |
| 219 | 新增: if ((proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, (int)windowinfo.childpid)) == IntPtr.Zero) return null; | |
| 220 | 新增: | |
| 221 | 新增: int capacity = 2000; | |
| 222 | 新增: StringBuilder sb = new StringBuilder(capacity); | |
| 223 | 新增: QueryFullProcessImageName(proc, 0, sb, ref capacity); | |
| 224 | 新增: | |
| 225 | 新增: Marshal.FreeHGlobal(pWindowinfo); | |
| 226 | 新增: | |
| 227 | 新增: return sb.ToString(0, capacity); | |
| 228 | 新增: } | |
| 229 | 新增: private bool EnumChildWindowsCallback(IntPtr hWnd_, IntPtr lParam_) | |
| 230 | 新增: { | |
| 231 | 新增: WINDOWINFO info = (WINDOWINFO)Marshal.PtrToStructure(lParam_, typeof(WINDOWINFO)); | |
| 232 | 新增: | |
| 233 | 新增: int pID; | |
| 234 | 新增: GetWindowThreadProcessId(hWnd_, out pID); | |
| 235 | 新增: | |
| 236 | 新增: if (pID != info.ownerpid) info.childpid = (uint)pID; | |
| 237 | 新增: | |
| 238 | 新增: Marshal.StructureToPtr(info, lParam_, true); | |
| 239 | 新增: | |
| 240 | 新增: return true; | |
| 241 | 新增: } | |
| 242 | 新增: | |
| 243 | 新增: private IntPtr getThreadWindowHandle(uint dwThreadId_) | |
| 244 | 新增: { | |
| 245 | 新增: IntPtr hWnd; | |
| 246 | 新增: | |
| 247 | 新增: // Get Window Handle and title from Thread | |
| 248 | 新增: var guiThreadInfo = new GUITHREADINFO(); | |
| 249 | 新增: guiThreadInfo.cbSize = (uint)Marshal.SizeOf(guiThreadInfo); | |
| 250 | 新增: | |
| 251 | 新增: GetGUIThreadInfo(dwThreadId_, ref guiThreadInfo); | |
| 252 | 新增: | |
| 253 | 新增: hWnd = guiThreadInfo.hwndFocus; | |
| 254 | 新增: //some times while changing the focus between different windows, it returns Zero so we would return the Active window in that case | |
| 255 | 新增: if (hWnd == IntPtr.Zero) | |
| 256 | 新增: { | |
| 257 | 新增: hWnd = guiThreadInfo.hwndActive; | |
| 258 | 新增: } | |
| 259 | 新增: return hWnd; | |
| 260 | 新增: } | |
| 261 | 新增: | |
| 262 | 新增: #region 获取全屏UWP应用PID | |
| 263 | 新增: /// <summary> | |
| 264 | 新增: /// 获取全屏UWP应用PID | |
| 265 | 新增: /// </summary> | |
| 266 | 新增: /// <returns></returns> | |
| 267 | 新增: private int GetFullScreenUWPPID() | |
| 268 | 新增: { | |
| 269 | 新增: var current = getThreadWindowHandle(0); | |
| 270 | 新增: int processId = 0; | |
| 271 | 新增: GetWindowThreadProcessId(current, out processId); | |
| 272 | 新增: return processId; | |
| 273 | 新增: } | |
| 274 | 新增: #endregion | |
| 275 | 新增: | |
| 276 | 新增: #region 判断应用是否是系统组件 | |
| 277 | 新增: private bool IsSystemComponent(string processName_, IntPtr windowHandle_) | |
| 278 | 新增: { | |
| 279 | 新增: // 系统组件类名 | |
| 280 | 新增: string[] sysClassNameArr = { | |
| 281 | 新增: "Progman", | |
| 282 | 新增: "WorkerW", | |
| 283 | 新增: "Shell_TrayWnd", | |
| 284 | 新增: "XamlExplorerHostIslandWindow", | |
| 285 | 新增: "TopLevelWindowForOverflowXamlIsland", | |
| 286 | 新增: "Shell_InputSwitchTopLevelWindow", | |
| 287 | 新增: "LockScreenControllerProxyWindow", | |
| 288 | 新增: // win7 | |
| 289 | 新增: "DV2ControlHost", | |
| 290 | 新增: "Button" | |
| 291 | 新增: }; | |
| 292 | 新增: // 系统进程名称 | |
| 293 | 新增: string[] sysProcessArr = { | |
| 294 | 新增: "ShellExperienceHost", | |
| 295 | 新增: "StartMenuExperienceHost", | |
| 296 | 新增: "SearchHost", | |
| 297 | 新增: "LockApp" | |
| 298 | 新增: }; | |
| 299 | 新增: | |
| 300 | 新增: // 在windows7下,dllhost进程可能是Windows照片查看器,classname为:Photo_Lightweight_Viewer | |
| 301 | 新增: // 需要单独为windows7写一个判定器,然后加一个转换器,dllhost进程->windows照片查看器 | |
| 302 | 新增: // explorer,class:CabinetWClass在win7下可能是文件夹、控制面板、我的电脑属性 | |
| 303 | 新增: bool isSys; | |
| 304 | 新增: if (processName_ == "explorer") | |
| 305 | 新增: { | |
| 306 | 新增: // 先通过类名判定 | |
| 307 | 新增: string className = Win32API.GetWindowClassName(windowHandle_); | |
| 308 | 新增: Logger.Info($"IsSystemComponent,process:{processName_},className:{className}"); | |
| 309 | 新增: if (!string.IsNullOrEmpty(className)) | |
| 310 | 新增: { | |
| 311 | 新增: isSys = sysClassNameArr.Contains(className); | |
| 312 | 新增: } | |
| 313 | 新增: else | |
| 314 | 新增: { | |
| 315 | 新增: int titleLength = Win32API.GetWindowTextLength(windowHandle_); | |
| 316 | 新增: isSys = titleLength <= 0; | |
| 317 | 新增: } | |
| 318 | 新增: } | |
| 319 | 新增: else | |
| 320 | 新增: { | |
| 321 | 新增: // 通过进程名称判定 | |
| 322 | 新增: isSys = sysProcessArr.Contains(processName_); | |
| 323 | 新增: } | |
| 324 | 新增: return isSys; | |
| 325 | 新增: } | |
| 326 | 新增: #endregion | |
| 327 | 新增: | |
| 328 | 新增: #region 获取COM应用 | |
| 329 | 新增: private AppInfo GetCOMAPP(int processId_) | |
| 330 | 新增: { | |
| 331 | 新增: try | |
| 332 | 新增: { | |
| 333 | 新增: string wmiQuery = string.Format("select ProcessId,CommandLine from Win32_Process where ProcessId='{0}'", processId_); | |
| 334 | 新增: ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery); | |
| 335 | 新增: var enu = searcher.Get().GetEnumerator(); | |
| 336 | 新增: if (enu.MoveNext()) | |
| 337 | 新增: { | |
| 338 | 新增: var commandLine = enu.Current["CommandLine"]; | |
| 339 | 新增: string appId = Regex.Match(commandLine.ToString(), @"\{(.*?)\}").Value; | |
| 340 | 新增: if (!string.IsNullOrEmpty(appId)) | |
| 341 | 新增: { | |
| 342 | 新增: | |
| 343 | 新增: } | |
| 344 | 新增: } | |
| 345 | 新增: } | |
| 346 | 新增: catch (Exception ex) | |
| 347 | 新增: { | |
| 348 | 新增: Logger.Error(ex.ToString()); | |
| 349 | 新增: } | |
| 350 | 新增: return null; | |
| 351 | 新增: } | |
| 352 | 新增: #endregion | |
| 353 | 新增: } | |
| 354 | 新增:} | |
| @@ -11,176 +11,107 @@ using System.Runtime.InteropServices; | ||
| 11 | 11 | using System.Text; |
| 12 | 12 | using System.Threading; |
| 13 | 13 | using System.Threading.Tasks; |
| 14 | 新增:using System.Timers; | |
| 14 | 15 | |
| 15 | 16 | namespace Core.Servicers.Instances |
| 16 | 17 | { |
| 17 | 18 | public class AppObserver : IAppObserver |
| 18 | 19 | { |
| 19 | 删除: private IntPtr hook; | |
| 20 | 删除: Win32API.WinEventDelegate winEventDelegate; | |
| 21 | 删除: | |
| 22 | 删除: public event ObserverEventHandler OnAppActive; | |
| 23 | 删除: | |
| 24 | 删除: public AppObserver() | |
| 20 | 新增: public event AppObserverEventHandler OnAppActiveChanged; | |
| 21 | 新增: | |
| 22 | 新增: #region win32 api | |
| 23 | 新增: public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, | |
| 24 | 新增: IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); | |
| 25 | 新增: [DllImport("user32.dll")] | |
| 26 | 新增: public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr | |
| 27 | 新增: hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, | |
| 28 | 新增: uint idThread, uint dwFlags); | |
| 29 | 新增: [DllImport("user32.dll")] | |
| 30 | 新增: public static extern bool UnhookWinEvent(IntPtr hWinEventHook); | |
| 31 | 新增: #endregion | |
| 32 | 新增: | |
| 33 | 新增: // 获得焦点事件 | |
| 34 | 新增: private WinEventDelegate _foregroundEventDelegate; | |
| 35 | 新增: private readonly IAppManager _appManager; | |
| 36 | 新增: private readonly IWindowManager _windowManager; | |
| 37 | 新增: private IntPtr _hook; | |
| 38 | 新增: private bool _isStart = false; | |
| 39 | 新增: private System.Timers.Timer _delayDetectTimer; | |
| 40 | 新增: public AppObserver(IAppManager appManager_, IWindowManager windowManager) | |
| 25 | 41 | { |
| 26 | 删除: winEventDelegate = new Win32API.WinEventDelegate(WinEventProc); | |
| 42 | 新增: _appManager = appManager_; | |
| 43 | 新增: _windowManager = windowManager; | |
| 44 | 新增: _foregroundEventDelegate = new WinEventDelegate(ForegroundEventCallback); | |
| 45 | 新增: _delayDetectTimer = new System.Timers.Timer(); | |
| 46 | 新增: _delayDetectTimer.Interval = 1000; | |
| 47 | 新增: _delayDetectTimer.Elapsed += DelayDetectTimer_Elapsed; | |
| 27 | 48 | } |
| 28 | 删除: public void Start() | |
| 29 | 删除: { | |
| 30 | 删除: hook = Win32API.SetWinEventHook(0x0003, 0x0003, IntPtr.Zero, | |
| 31 | 删除: winEventDelegate, 0, 0, 0); | |
| 32 | 49 | |
| 33 | 删除: var window = Win32API.GetForegroundWindow(); | |
| 34 | 删除: Handle(window); | |
| 35 | 删除: } | |
| 36 | 50 | |
| 37 | 删除: private void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) | |
| 38 | 删除: { | |
| 39 | 删除: Handle(hwnd); | |
| 40 | 删除: } | |
| 41 | 51 | |
| 42 | 删除: private async void Handle(IntPtr hwnd) | |
| 52 | 新增: private void ForegroundEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) | |
| 43 | 53 | { |
| 44 | 删除: string processName = String.Empty, processFileName = String.Empty, processDescription = String.Empty; | |
| 45 | 删除: | |
| 46 | 删除: var processResult = await Task.Run(() => | |
| 54 | 新增: _delayDetectTimer?.Stop(); | |
| 55 | 新增: DateTime activeTime = DateTime.Now; | |
| 56 | 新增: var stopwatch = Stopwatch.StartNew(); | |
| 57 | 新增: var args = GetAppInfoEventArgs(hwnd, activeTime); | |
| 58 | 新增: Debug.WriteLine(activeTime); | |
| 59 | 新增: Debug.WriteLine(args.App.ToString()); | |
| 60 | 新增: // 响应事件 | |
| 61 | 新增: OnAppActiveChanged?.Invoke(this, args); | |
| 62 | 新增: if (args.App.Type == Enums.AppType.SystemComponent) | |
| 47 | 63 | { |
| 48 | 删除: try | |
| 49 | 删除: { | |
| 50 | 删除: string[] processInfo = GetProcessInfoByWindowHandle(hwnd); | |
| 51 | 删除: int processID = int.Parse(processInfo[2]); | |
| 52 | 删除: processName = processInfo[0]; | |
| 53 | 删除: processFileName = processInfo[1]; | |
| 54 | 删除: | |
| 55 | 删除: | |
| 56 | 删除: // handle uwp app | |
| 57 | 删除: if (processFileName.IndexOf("ApplicationFrameHost.exe") != -1) | |
| 58 | 删除: { | |
| 59 | 删除: processFileName = Win32API.UWP_AppName(hwnd, (uint)processID); | |
| 60 | 删除: if (processFileName == null) | |
| 61 | 删除: { | |
| 62 | 删除: Thread.Sleep(1500); | |
| 63 | 删除: | |
| 64 | 删除: processFileName = Win32API.UWP_AppName(hwnd, (uint)processID); | |
| 65 | 删除: processName = GetUWPAPPName(processFileName); | |
| 66 | 删除: | |
| 67 | 删除: IntPtr foregeroundHwnd = Win32API.GetForegroundWindow(); | |
| 68 | 删除: | |
| 69 | 删除: if (foregeroundHwnd != hwnd) | |
| 70 | 删除: { | |
| 71 | 删除: // 获取后焦点变了 | |
| 72 | 删除: processInfo = GetProcessInfoByWindowHandle(foregeroundHwnd); | |
| 73 | 删除: processID = int.Parse(processInfo[2]); | |
| 74 | 删除: processName = processInfo[0]; | |
| 75 | 删除: processFileName = processInfo[1]; | |
| 76 | 删除: } | |
| 77 | 删除: | |
| 78 | 删除: } | |
| 79 | 删除: else | |
| 80 | 删除: { | |
| 81 | 删除: processName = GetUWPAPPName(processFileName); | |
| 82 | 删除: } | |
| 83 | 删除: | |
| 84 | 删除: } | |
| 85 | 删除: FileVersionInfo info = FileVersionInfo.GetVersionInfo(processFileName); | |
| 86 | 删除: processDescription = info.FileDescription; | |
| 87 | 删除: | |
| 88 | 删除: | |
| 89 | 删除: int titleCapacity = Win32API.GetWindowTextLength(hwnd) * 2; | |
| 90 | 删除: StringBuilder stringBuilder = new StringBuilder(titleCapacity); | |
| 91 | 删除: Win32API.GetWindowText(hwnd, stringBuilder, stringBuilder.Capacity); | |
| 92 | 删除: | |
| 93 | 删除: | |
| 94 | 删除: if (IsSystemProcess(processName, stringBuilder.ToString())) | |
| 95 | 删除: { | |
| 96 | 删除: // 过滤掉一些系统进程 | |
| 97 | 删除: processName = string.Empty; | |
| 98 | 删除: } | |
| 99 | 删除: } | |
| 100 | 删除: catch (Exception e) | |
| 101 | 删除: { | |
| 102 | 删除: Logger.Warn(e.Message + " | Process Name:" + processName + " | Process File:" + processFileName + " | Process Description:" + processDescription); | |
| 103 | 删除: } | |
| 104 | 删除: return processName; | |
| 105 | 删除: }); | |
| 64 | 新增: _delayDetectTimer?.Start(); | |
| 65 | 新增: } | |
| 106 | 66 | |
| 107 | 删除: EventInvoke(processName, processDescription, processFileName, hwnd); | |
| 108 | 67 | } |
| 109 | 68 | |
| 110 | 删除: /// <summary> | |
| 111 | 删除: /// 指示指定进程是否属于系统进程 | |
| 112 | 删除: /// </summary> | |
| 113 | 删除: /// <param name="processName">进程名称</param> | |
| 114 | 删除: /// <param name="title">窗口标题</param> | |
| 115 | 删除: /// <returns></returns> | |
| 116 | 删除: private bool IsSystemProcess(string processName, string title) | |
| 69 | 新增: private void DelayDetectTimer_Elapsed(object sender, ElapsedEventArgs e) | |
| 117 | 70 | { |
| 118 | 删除: processName = processName.ToLower(); | |
| 119 | 删除: int length = title.Length; | |
| 120 | 删除: string[] titleArr = { "UnlockingWindow", "Program Manager" }; | |
| 121 | 删除: | |
| 122 | 删除: if (processName == "explorer") | |
| 123 | 删除: { | |
| 124 | 删除: if (length == 0) | |
| 125 | 删除: { | |
| 126 | 删除: // 可能是任务栏 | |
| 127 | 删除: return true; | |
| 128 | 删除: } | |
| 129 | 删除: return titleArr.Contains(title); | |
| 130 | 删除: | |
| 131 | 删除: } | |
| 132 | 删除: return false; | |
| 71 | 新增: _delayDetectTimer?.Stop(); | |
| 72 | 新增: DelayDetect(); | |
| 133 | 73 | } |
| 134 | 74 | |
| 135 | 删除: private string GetUWPAPPName(string processFileName) | |
| 75 | 新增: private void DelayDetect() | |
| 136 | 76 | { |
| 137 | 删除: string processName = string.Empty; | |
| 138 | 删除: if (!string.IsNullOrEmpty(processFileName) && processFileName.IndexOf("\\") != -1) | |
| 77 | 新增: DateTime activeTime = DateTime.Now; | |
| 78 | 新增: IntPtr w = Win32API.GetForegroundWindow(); | |
| 79 | 新增: var args = GetAppInfoEventArgs(w, activeTime); | |
| 80 | 新增: if (args.App.Type != Enums.AppType.SystemComponent) | |
| 139 | 81 | { |
| 140 | 删除: processName = processFileName.Split('\\').Last(); | |
| 141 | 删除: processName = processName.Replace(".exe", ""); | |
| 82 | 新增: // 响应事件 | |
| 83 | 新增: OnAppActiveChanged?.Invoke(this, args); | |
| 142 | 84 | } |
| 143 | 删除: return processName; | |
| 144 | 85 | } |
| 145 | 删除: /// <summary> | |
| 146 | 删除: /// 通过窗口句柄获取进程信息 | |
| 147 | 删除: /// </summary> | |
| 148 | 删除: /// <param name="hwnd"></param> | |
| 149 | 删除: /// <returns></returns> | |
| 150 | 删除: private string[] GetProcessInfoByWindowHandle(IntPtr hwnd) | |
| 151 | 删除: { | |
| 152 | 删除: string processName, processFileName = string.Empty; | |
| 153 | 86 | |
| 154 | 删除: int processID = 0; | |
| 155 | 删除: Win32API.GetWindowThreadProcessId(hwnd, out processID); | |
| 156 | 删除: Process process = Process.GetProcessById(processID); | |
| 157 | 删除: processName = process.ProcessName; | |
| 87 | 新增: private AppActiveChangedEventArgs GetAppInfoEventArgs(IntPtr handle_, DateTime activeTime_) | |
| 88 | 新增: { | |
| 89 | 新增: var app = _appManager.GetAppInfo(handle_); | |
| 90 | 新增: var window = _windowManager.GetWindowInfo(handle_); | |
| 91 | 新增: return new AppActiveChangedEventArgs(app, window, activeTime_); | |
| 92 | 新增: } | |
| 158 | 93 | |
| 159 | 删除: IntPtr processHandle = IntPtr.Zero; | |
| 160 | 删除: processHandle = Win32API.OpenProcess(0x001F0FFF, false, processID); | |
| 94 | 新增: private void HandleForegroundWindow() | |
| 95 | 新增: { | |
| 96 | 新增: IntPtr w = Win32API.GetForegroundWindow(); | |
| 97 | 新增: ForegroundEventCallback(IntPtr.Zero, 0, w, 0, 0, 0, 0); | |
| 98 | 新增: } | |
| 161 | 99 | |
| 162 | 删除: if (processHandle != IntPtr.Zero) | |
| 163 | 删除: { | |
| 164 | 删除: int MaxPathLength = 4096; | |
| 165 | 删除: var buffer = new StringBuilder(MaxPathLength); | |
| 166 | 删除: Win32API.QueryFullProcessImageName(processHandle, 0, buffer, ref MaxPathLength); | |
| 167 | 删除: processFileName = buffer.ToString(); | |
| 168 | 删除: } | |
| 169 | 删除: else | |
| 100 | 新增: public void Start() | |
| 101 | 新增: { | |
| 102 | 新增: if (_isStart) | |
| 170 | 103 | { |
| 171 | 删除: Logger.Warn($"无法获取进程:{processName}的句柄,请尝试以管理员身份运行Tai。"); | |
| 104 | 新增: return; | |
| 172 | 105 | } |
| 173 | 删除: return new string[] { processName, processFileName, processID.ToString() }; | |
| 174 | 删除: } | |
| 175 | 删除: private void EventInvoke(string processName, string description, string filename, IntPtr handle) | |
| 176 | 删除: { | |
| 177 | 删除: var args = new AppObserverEventArgs(processName, description, filename, handle); | |
| 178 | 删除: OnAppActive?.Invoke(args); | |
| 106 | 新增: _isStart = true; | |
| 107 | 新增: _hook = SetWinEventHook(0x0003, 0x0003, IntPtr.Zero, _foregroundEventDelegate, 0, 0, 0); | |
| 108 | 新增: HandleForegroundWindow(); | |
| 179 | 109 | } |
| 180 | 110 | |
| 181 | 111 | public void Stop() |
| 182 | 112 | { |
| 183 | 删除: Win32API.UnhookWinEvent(hook); | |
| 113 | 新增: _isStart = false; | |
| 114 | 新增: UnhookWinEvent(_hook); | |
| 184 | 115 | } |
| 185 | 116 | } |
| 186 | 117 | } |
| @@ -0,0 +1,170 @@ | ||
| 1 | 新增:using Core.Enums; | |
| 2 | 新增:using Core.Event; | |
| 3 | 新增:using Core.Models.AppObserver; | |
| 4 | 新增:using Core.Servicers.Interfaces; | |
| 5 | 新增:using System; | |
| 6 | 新增:using System.Collections.Generic; | |
| 7 | 新增:using System.Diagnostics; | |
| 8 | 新增:using System.Linq; | |
| 9 | 新增:using System.Text; | |
| 10 | 新增:using System.Threading.Tasks; | |
| 11 | 新增:using System.Timers; | |
| 12 | 新增: | |
| 13 | 新增:namespace Core.Servicers.Instances | |
| 14 | 新增:{ | |
| 15 | 新增: public class AppTimerServicer : IAppTimerServicer | |
| 16 | 新增: { | |
| 17 | 新增: public event AppTimerEventHandler OnAppDurationUpdated; | |
| 18 | 新增: | |
| 19 | 新增: private readonly IAppObserver _appObserver; | |
| 20 | 新增: | |
| 21 | 新增: private bool _isStart = false; | |
| 22 | 新增: private int _appDuration = 0; | |
| 23 | 新增: private DateTime _startTime = DateTime.MinValue; | |
| 24 | 新增: private DateTime _endTime = DateTime.MinValue; | |
| 25 | 新增: private string _activeProcess; | |
| 26 | 新增: | |
| 27 | 新增: private Dictionary<string, AppData> _appData; | |
| 28 | 新增: private System.Timers.Timer _timer; | |
| 29 | 新增: private AppDurationUpdatedEventArgs _lastInvokeEventArgs; | |
| 30 | 新增: | |
| 31 | 新增: public struct AppData | |
| 32 | 新增: { | |
| 33 | 新增: public AppInfo App { get; set; } | |
| 34 | 新增: public WindowInfo Window { get; set; } | |
| 35 | 新增: | |
| 36 | 新增: } | |
| 37 | 新增: public AppTimerServicer(IAppObserver appObserver_) | |
| 38 | 新增: { | |
| 39 | 新增: _appObserver = appObserver_; | |
| 40 | 新增: | |
| 41 | 新增: } | |
| 42 | 新增: | |
| 43 | 新增: private void Init() | |
| 44 | 新增: { | |
| 45 | 新增: _appData = new Dictionary<string, AppData>(); | |
| 46 | 新增: _appDuration = 0; | |
| 47 | 新增: _activeProcess = string.Empty; | |
| 48 | 新增: | |
| 49 | 新增: _timer = new System.Timers.Timer(); | |
| 50 | 新增: _timer.Interval = 1000; | |
| 51 | 新增: _timer.Elapsed += Timer_Elapsed; | |
| 52 | 新增: } | |
| 53 | 新增: | |
| 54 | 新增: | |
| 55 | 新增: | |
| 56 | 新增: public void Start() | |
| 57 | 新增: { | |
| 58 | 新增: if (_isStart) { return; } | |
| 59 | 新增: | |
| 60 | 新增: Init(); | |
| 61 | 新增: | |
| 62 | 新增: _isStart = true; | |
| 63 | 新增: _appObserver.OnAppActiveChanged += AppObserver_OnAppActiveChanged; | |
| 64 | 新增: } | |
| 65 | 新增: | |
| 66 | 新增: | |
| 67 | 新增: public void Stop() | |
| 68 | 新增: { | |
| 69 | 新增: _isStart = false; | |
| 70 | 新增: StopTimer(); | |
| 71 | 新增: _appObserver.OnAppActiveChanged -= AppObserver_OnAppActiveChanged; | |
| 72 | 新增: } | |
| 73 | 新增: | |
| 74 | 新增: private void AppObserver_OnAppActiveChanged(object sender, AppActiveChangedEventArgs e) | |
| 75 | 新增: { | |
| 76 | 新增: string processName = e.App.Process; | |
| 77 | 新增: bool isStatistical = IsStatistical(e.App); | |
| 78 | 新增: | |
| 79 | 新增: Debug.WriteLine(processName+ " -> " + _activeProcess); | |
| 80 | 新增: if (processName != _activeProcess) | |
| 81 | 新增: { | |
| 82 | 新增: StopTimer(); | |
| 83 | 新增: InvokeEvent(); | |
| 84 | 新增: | |
| 85 | 新增: if (isStatistical) | |
| 86 | 新增: { | |
| 87 | 新增: StartTimer(); | |
| 88 | 新增: } | |
| 89 | 新增: | |
| 90 | 新增: _activeProcess = e.App.Type == AppType.SystemComponent ? string.Empty : processName; | |
| 91 | 新增: } | |
| 92 | 新增: | |
| 93 | 新增: if (isStatistical) | |
| 94 | 新增: { | |
| 95 | 新增: var data = new AppData() | |
| 96 | 新增: { | |
| 97 | 新增: App = e.App, | |
| 98 | 新增: Window = e.Window, | |
| 99 | 新增: }; | |
| 100 | 新增: if (!_appData.ContainsKey(processName)) | |
| 101 | 新增: { | |
| 102 | 新增: // 缓存应用信息 | |
| 103 | 新增: _appData.Add(processName, data); | |
| 104 | 新增: } | |
| 105 | 新增: else | |
| 106 | 新增: { | |
| 107 | 新增: // 更新缓存 | |
| 108 | 新增: _appData[processName] = data; | |
| 109 | 新增: } | |
| 110 | 新增: } | |
| 111 | 新增: } | |
| 112 | 新增: | |
| 113 | 新增: private void Timer_Elapsed(object sender, ElapsedEventArgs e) | |
| 114 | 新增: { | |
| 115 | 新增: _appDuration++; | |
| 116 | 新增: } | |
| 117 | 新增: | |
| 118 | 新增: private void StartTimer() | |
| 119 | 新增: { | |
| 120 | 新增: _timer.Start(); | |
| 121 | 新增: _startTime = DateTime.Now; | |
| 122 | 新增: _appDuration = 0; | |
| 123 | 新增: } | |
| 124 | 新增: | |
| 125 | 新增: private void StopTimer() | |
| 126 | 新增: { | |
| 127 | 新增: _timer.Stop(); | |
| 128 | 新增: _endTime = DateTime.Now; | |
| 129 | 新增: } | |
| 130 | 新增: | |
| 131 | 新增: private void InvokeEvent() | |
| 132 | 新增: { | |
| 133 | 新增: var info = GetAppDuration(); | |
| 134 | 新增: if (info != null) | |
| 135 | 新增: { | |
| 136 | 新增: if (_lastInvokeEventArgs?.ActiveTime.ToString() != _startTime.ToString() || _lastInvokeEventArgs?.EndTime.ToString() != _endTime.ToString()) | |
| 137 | 新增: { | |
| 138 | 新增: Debug.WriteLine("【计时更新】" + info); | |
| 139 | 新增: OnAppDurationUpdated?.Invoke(this, info); | |
| 140 | 新增: } | |
| 141 | 新增: else | |
| 142 | 新增: { | |
| 143 | 新增: Debug.WriteLine("【重复!!】" + _lastInvokeEventArgs + ",【now】" + info); | |
| 144 | 新增: } | |
| 145 | 新增: _lastInvokeEventArgs = info; | |
| 146 | 新增: } | |
| 147 | 新增: } | |
| 148 | 新增: | |
| 149 | 新增: /// <summary> | |
| 150 | 新增: /// 判断应用是否需要被统计 | |
| 151 | 新增: /// </summary> | |
| 152 | 新增: /// <param name="app_"></param> | |
| 153 | 新增: /// <returns>需要统计时返回 true </returns> | |
| 154 | 新增: private bool IsStatistical(AppInfo app_) | |
| 155 | 新增: { | |
| 156 | 新增: return !string.IsNullOrEmpty(app_.Process) && app_.Type != AppType.SystemComponent && !string.IsNullOrEmpty(app_.ExecutablePath); | |
| 157 | 新增: } | |
| 158 | 新增: | |
| 159 | 新增: public AppDurationUpdatedEventArgs GetAppDuration() | |
| 160 | 新增: { | |
| 161 | 新增: if (_appDuration > 0 && !string.IsNullOrEmpty(_activeProcess) && _appData.ContainsKey(_activeProcess)) | |
| 162 | 新增: { | |
| 163 | 新增: var data = _appData[_activeProcess]; | |
| 164 | 新增: var args = new AppDurationUpdatedEventArgs(_appDuration, data.App, data.Window, _startTime, _endTime); | |
| 165 | 新增: return args; | |
| 166 | 新增: } | |
| 167 | 新增: return null; | |
| 168 | 新增: } | |
| 169 | 新增: } | |
| 170 | 新增:} | |
| @@ -14,6 +14,7 @@ using System.IO; | ||
| 14 | 14 | using CsvHelper; |
| 15 | 15 | using System.Globalization; |
| 16 | 16 | using System.Threading.Tasks; |
| 17 | 新增:using System.Windows; | |
| 17 | 18 | |
| 18 | 19 | namespace Core.Servicers.Instances |
| 19 | 20 | { |
| @@ -28,100 +29,149 @@ namespace Core.Servicers.Instances | ||
| 28 | 29 | _database = database_; |
| 29 | 30 | } |
| 30 | 31 | |
| 31 | 删除: public void SaveAppDuration(string processName_, int duration_, DateTime startDateTime_) | |
| 32 | 新增: public void UpdateAppDuration(string process_, int duration_, DateTime startTime_) | |
| 32 | 33 | { |
| 33 | 删除: // 过滤无效数据 | |
| 34 | 删除: if (string.IsNullOrEmpty(processName_) || duration_ <= 0) return; | |
| 34 | 新增: // 过滤无效值 | |
| 35 | 新增: if (string.IsNullOrEmpty(process_) || duration_ <= 0 || startTime_ == DateTime.MinValue) return; | |
| 36 | 新增: | |
| 37 | 新增: Logger.Info($"UpdateAppDuration,process:{process_},duration:{duration_},start:{startTime_}"); | |
| 38 | 新增: // 开始时间剩余最大统计时长 | |
| 39 | 新增: int startTimeMaxHoursDuration = (59 - startTime_.Minute) * 60 + (60 - startTime_.Second); | |
| 40 | 新增: // 开始时间使用时长 | |
| 41 | 新增: int startTimeHoursDuration = duration_ > startTimeMaxHoursDuration ? startTimeMaxHoursDuration : duration_; | |
| 42 | 新增: // 剩余时长 | |
| 43 | 新增: int outHoursDuration = duration_ - startTimeHoursDuration; | |
| 44 | 新增: // 结束时间 | |
| 45 | 新增: DateTime endTime = new DateTime(startTime_.Year, startTime_.Month, startTime_.Day, startTime_.Hour, 0, 0); | |
| 46 | 新增: // 时段使用数据 | |
| 47 | 新增: Dictionary<DateTime, int> durationHoursData = new Dictionary<DateTime, int> | |
| 48 | 新增: { | |
| 49 | 新增: { endTime, startTimeHoursDuration } | |
| 50 | 新增: }; | |
| 51 | 新增: // 计算时段数据 | |
| 52 | 新增: if (outHoursDuration > 0) | |
| 53 | 新增: { | |
| 54 | 新增: int outHours = outHoursDuration / 3600; | |
| 55 | 新增: | |
| 56 | 新增: DateTime outStartTime = new DateTime(startTime_.Year, startTime_.Month, startTime_.Day, startTime_.Hour, 0, 0); | |
| 57 | 新增: for (int i = 0; i < outHours; i++) | |
| 58 | 新增: { | |
| 59 | 新增: outStartTime = outStartTime.AddHours(1); | |
| 60 | 新增: int duration = 3600; | |
| 61 | 新增: durationHoursData.Add(outStartTime, duration); | |
| 62 | 新增: } | |
| 63 | 新增: if (outHoursDuration % 3600 > 0) | |
| 64 | 新增: { | |
| 65 | 新增: outStartTime = outStartTime.AddHours(1); | |
| 66 | 新增: int duration = outHoursDuration - outHours * 3600; | |
| 67 | 新增: durationHoursData.Add(outStartTime, duration); | |
| 68 | 新增: } | |
| 69 | 新增: endTime = outStartTime; | |
| 70 | 新增: } | |
| 35 | 71 | |
| 36 | 删除: Task.Run(() => | |
| 72 | 新增: // 计算每日统计数据 | |
| 73 | 新增: DateTime nextDayTime = new DateTime(startTime_.Year, startTime_.Month, startTime_.Day, 0, 0, 0).AddDays(1); | |
| 74 | 新增: int startTimeMaxDayDuration = (int)(nextDayTime - startTime_).TotalSeconds; | |
| 75 | 新增: // 开始时间使用时长 | |
| 76 | 新增: int startTimeDayDuration = duration_ > startTimeMaxDayDuration ? startTimeMaxDayDuration : duration_; | |
| 77 | 新增: // 剩余时长 | |
| 78 | 新增: int outDayDuration = duration_ - startTimeDayDuration; | |
| 79 | 新增: // 结束时间 | |
| 80 | 新增: DateTime endDayTime = startTime_.Date; | |
| 81 | 新增: // 每日使用数据 | |
| 82 | 新增: Dictionary<DateTime, int> durationDayData = new Dictionary<DateTime, int> | |
| 37 | 83 | { |
| 38 | 删除: try | |
| 84 | 新增: { startTime_.Date, startTimeDayDuration } | |
| 85 | 新增: }; | |
| 86 | 新增: if (outDayDuration > 0) | |
| 87 | 新增: { | |
| 88 | 新增: int outDays = outDayDuration / 86400; | |
| 89 | 新增: | |
| 90 | 新增: DateTime outStartTime = new DateTime(startTime_.Year, startTime_.Month, startTime_.Day, 0, 0, 0); | |
| 91 | 新增: for (int i = 0; i < outDays; i++) | |
| 39 | 92 | { |
| 40 | 删除: if (startDateTime_.Minute == 59 && startDateTime_.Second >= 58) | |
| 41 | 删除: { | |
| 42 | 删除: // 当记录开始时间接近59分59秒时划到下一个小时时段 | |
| 43 | 删除: startDateTime_ = startDateTime_.AddSeconds(2); | |
| 44 | 删除: startDateTime_ = new DateTime(startDateTime_.Year, startDateTime_.Month, startDateTime_.Day, startDateTime_.Hour, 0, 0); | |
| 45 | 删除: } | |
| 93 | 新增: outStartTime = outStartTime.AddDays(1); | |
| 94 | 新增: int duration = 86400; | |
| 95 | 新增: durationDayData.Add(outStartTime, duration); | |
| 96 | 新增: } | |
| 97 | 新增: if (outDayDuration % 86400 > 0) | |
| 98 | 新增: { | |
| 99 | 新增: outStartTime = outStartTime.AddDays(1); | |
| 100 | 新增: int duration = outDayDuration - outDays * 86400; | |
| 101 | 新增: durationDayData.Add(outStartTime, duration); | |
| 102 | 新增: } | |
| 103 | 新增: endDayTime = outStartTime.Date; | |
| 104 | 新增: } | |
| 46 | 105 | |
| 47 | 删除: using (var db = _database.GetWriterContext()) | |
| 106 | 新增: // 开始写入数据 | |
| 107 | 新增: try | |
| 108 | 新增: { | |
| 109 | 新增: using (var db = _database.GetWriterContext()) | |
| 110 | 新增: { | |
| 111 | 新增: var app = db.App.Where(m => m.Name == process_).FirstOrDefault(); | |
| 112 | 新增: if (app == null) | |
| 48 | 113 | { |
| 49 | 删除: var app = db.App.Where(m => m.Name == processName_).FirstOrDefault(); | |
| 50 | 删除: if (app == null) | |
| 51 | 删除: { | |
| 52 | 删除: _database.CloseWriter(); | |
| 53 | 删除: return; | |
| 54 | 删除: } | |
| 55 | 删除: | |
| 56 | 删除: // 当前时段最大可记录时长 | |
| 57 | 删除: int nowHoursMaxDuration = (60 - startDateTime_.Minute) * 60; | |
| 58 | 删除: duration_ = duration_ > nowHoursMaxDuration ? nowHoursMaxDuration : duration_; | |
| 114 | 新增: _database.CloseWriter(); | |
| 115 | 新增: return; | |
| 116 | 新增: } | |
| 59 | 117 | |
| 60 | 删除: // 更新app累计时长 | |
| 61 | 删除: app.TotalTime += duration_; | |
| 118 | 新增: // 更新app累计总时长 | |
| 119 | 新增: app.TotalTime += duration_; | |
| 62 | 120 | |
| 63 | 删除: // 更新每日数据 | |
| 64 | 删除: var dailyLog = db.DailyLog.SingleOrDefault(m => m.Date == startDateTime_.Date && m.AppModelID == app.ID); | |
| 65 | 删除: if (dailyLog == null) | |
| 121 | 新增: // 更新每日数据 | |
| 122 | 新增: var dailyLogs = db.DailyLog.Where(m => m.Date >= startTime_.Date && m.Date <= endDayTime && m.AppModelID == app.ID).ToList(); | |
| 123 | 新增: foreach (var item in durationDayData) | |
| 124 | 新增: { | |
| 125 | 新增: var log = dailyLogs.Where(m => m.Date == item.Key).FirstOrDefault(); | |
| 126 | 新增: if (log == null) | |
| 66 | 127 | { |
| 67 | 128 | //数据库中没有时则创建 |
| 68 | 129 | db.DailyLog.Add(new DailyLogModel() |
| 69 | 130 | { |
| 70 | 删除: Date = startDateTime_.Date, | |
| 131 | 新增: Date = item.Key, | |
| 71 | 132 | AppModelID = app.ID, |
| 72 | 删除: Time = duration_ > 86400 ? 86400 : duration_, | |
| 133 | 新增: Time = item.Value, | |
| 73 | 134 | }); |
| 74 | 135 | } |
| 75 | 136 | else |
| 76 | 137 | { |
| 77 | 删除: if (dailyLog.Time + duration_ > 86400) | |
| 78 | 删除: { | |
| 79 | 删除: dailyLog.Time = 86400; | |
| 80 | 删除: } | |
| 81 | 删除: else | |
| 82 | 删除: { | |
| 83 | 删除: dailyLog.Time += duration_; | |
| 84 | 删除: } | |
| 138 | 新增: int time = log.Time + item.Value; | |
| 139 | 新增: log.Time = time > 86400 ? 86400 : time; | |
| 85 | 140 | } |
| 86 | 删除: | |
| 87 | 删除: // 更新时段数据 | |
| 88 | 删除: var time = new DateTime(startDateTime_.Year, startDateTime_.Month, startDateTime_.Day, startDateTime_.Hour, 0, 0); | |
| 89 | 删除: var hoursLog = db.HoursLog.SingleOrDefault(m => m.DataTime == time && m.AppModelID == app.ID); | |
| 90 | 删除: if (hoursLog == null) | |
| 141 | 新增: } | |
| 142 | 新增: // 更新时段数据 | |
| 143 | 新增: var startDataTime = new DateTime(startTime_.Year, startTime_.Month, startTime_.Day, startTime_.Hour, 0, 0); | |
| 144 | 新增: var hoursLogs = db.HoursLog.Where(m => m.DataTime >= startDataTime && startDataTime <= endTime && m.AppModelID == app.ID).ToList(); | |
| 145 | 新增: foreach (var item in durationHoursData) | |
| 146 | 新增: { | |
| 147 | 新增: var log = hoursLogs.Where(m => startDataTime == item.Key).FirstOrDefault(); | |
| 148 | 新增: if (log == null) | |
| 91 | 149 | { |
| 92 | 150 | // 没有记录时创建 |
| 93 | 151 | db.HoursLog.Add(new HoursLogModel() |
| 94 | 152 | { |
| 95 | 删除: DataTime = time, | |
| 153 | 新增: DataTime = item.Key, | |
| 96 | 154 | AppModelID = app.ID, |
| 97 | 删除: Time = duration_ | |
| 155 | 新增: Time = item.Value | |
| 98 | 156 | }); |
| 99 | 157 | } |
| 100 | 158 | else |
| 101 | 159 | { |
| 102 | 删除: if (hoursLog.Time + duration_ > 3600) | |
| 103 | 删除: { | |
| 104 | 删除: hoursLog.Time = 3600; | |
| 105 | 删除: } | |
| 106 | 删除: else | |
| 107 | 删除: { | |
| 108 | 删除: hoursLog.Time += duration_; | |
| 109 | 删除: } | |
| 160 | 新增: int time = log.Time + item.Value; | |
| 161 | 新增: log.Time = time > 3600 ? 3600 : time; | |
| 110 | 162 | } |
| 111 | 删除: | |
| 112 | 删除: db.SaveChanges(); | |
| 113 | 删除: Logger.Info($"Save app time done.Process:{processName_},Duration:{duration_},StartDateTime:{startDateTime_},AppID:{app.ID}"); | |
| 114 | 163 | } |
| 164 | 新增: db.SaveChanges(); | |
| 115 | 165 | } |
| 116 | 删除: catch (Exception e) | |
| 117 | 删除: { | |
| 118 | 删除: Logger.Error($"Save app time error!Process:{processName_},Duration:{duration_},StartDateTime:{startDateTime_}.\r\nError:\r\n{e.Message}"); | |
| 119 | 删除: } | |
| 120 | 删除: finally | |
| 121 | 删除: { | |
| 122 | 删除: _database.CloseWriter(); | |
| 123 | 删除: } | |
| 124 | 删除: }); | |
| 166 | 新增: } | |
| 167 | 新增: catch (Exception e) | |
| 168 | 新增: { | |
| 169 | 新增: Logger.Error($"UpdateAppDuration error!Process:{process_},Duration:{duration_},StartDateTime:{startTime_}.\r\nError:\r\n{e.Message}"); | |
| 170 | 新增: } | |
| 171 | 新增: finally | |
| 172 | 新增: { | |
| 173 | 新增: _database.CloseWriter(); | |
| 174 | 新增: } | |
| 125 | 175 | } |
| 126 | 176 | |
| 127 | 177 | public List<DailyLogModel> GetTodaylogList() |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | using Core.Enums; |
| 2 | 新增:using Core.Event; | |
| 2 | 3 | using Core.Librarys; |
| 3 | 4 | using Core.Librarys.SQLite; |
| 4 | 5 | using Core.Models; |
| @@ -22,14 +23,14 @@ namespace Core.Servicers.Instances | ||
| 22 | 23 | public class Main : IMain |
| 23 | 24 | { |
| 24 | 25 | private readonly IAppObserver appObserver; |
| 25 | 删除: private readonly IBrowserObserver browserObserver; | |
| 26 | 26 | private readonly IData data; |
| 27 | 27 | private readonly ISleepdiscover sleepdiscover; |
| 28 | 28 | private readonly IAppConfig appConfig; |
| 29 | 删除: private readonly IDateTimeObserver dateTimeObserver; | |
| 30 | 29 | private readonly IAppData appData; |
| 31 | 30 | private readonly ICategorys categories; |
| 32 | 31 | private readonly IWebFilter _webFilter; |
| 32 | 新增: private readonly IAppTimerServicer _appTimer; | |
| 33 | 新增: private readonly IWebServer _webServer; | |
| 33 | 34 | // 忽略的进程 |
| 34 | 35 | private readonly string[] DefaultIgnoreProcess = new string[] { |
| 35 | 36 | "Tai", |
| @@ -45,16 +46,6 @@ namespace Core.Servicers.Instances | ||
| 45 | 46 | "SystemSettingsAdminFlows" |
| 46 | 47 | }; |
| 47 | 48 | |
| 48 | 删除: /// <summary> | |
| 49 | 删除: /// 当前聚焦进程 | |
| 50 | 删除: /// </summary> | |
| 51 | 删除: private string activeProcess = null; | |
| 52 | 删除: | |
| 53 | 删除: /// <summary> | |
| 54 | 删除: /// 焦点开始时间 | |
| 55 | 删除: /// </summary> | |
| 56 | 删除: private DateTime activeStartTime = DateTime.Now; | |
| 57 | 删除: | |
| 58 | 49 | /// <summary> |
| 59 | 50 | /// 睡眠状态 |
| 60 | 51 | /// </summary> |
| @@ -92,42 +83,27 @@ namespace Core.Servicers.Instances | ||
| 92 | 83 | IAppConfig appConfig, |
| 93 | 84 | IDateTimeObserver dateTimeObserver, |
| 94 | 85 | IAppData appData, ICategorys categories, |
| 95 | 删除: IBrowserObserver browserObserver, | |
| 96 | 删除: IWebFilter webFilter_) | |
| 86 | 新增: IWebFilter webFilter_, | |
| 87 | 新增: IAppTimerServicer appTimer_, | |
| 88 | 新增: IWebServer webServer_) | |
| 97 | 89 | { |
| 98 | 90 | this.appObserver = appObserver; |
| 99 | 91 | this.data = data; |
| 100 | 92 | this.sleepdiscover = sleepdiscover; |
| 101 | 93 | this.appConfig = appConfig; |
| 102 | 删除: this.dateTimeObserver = dateTimeObserver; | |
| 103 | 94 | this.appData = appData; |
| 104 | 95 | this.categories = categories; |
| 105 | 删除: this.browserObserver = browserObserver; | |
| 106 | 96 | _webFilter = webFilter_; |
| 97 | 新增: _appTimer = appTimer_; | |
| 98 | 新增: _webServer = webServer_; | |
| 107 | 99 | |
| 108 | 100 | IgnoreProcessCacheList = new List<string>(); |
| 109 | 101 | ConfigIgnoreProcessRegxList = new List<string>(); |
| 110 | 102 | ConfigIgnoreProcessList = new List<string>(); |
| 111 | 103 | |
| 112 | 删除: appObserver.OnAppActive += AppObserver_OnAppActive; | |
| 113 | 104 | sleepdiscover.SleepStatusChanged += Sleepdiscover_SleepStatusChanged; |
| 114 | 105 | appConfig.ConfigChanged += AppConfig_ConfigChanged; |
| 115 | 删除: dateTimeObserver.OnDateTimeChanging += DateTimeObserver_OnDateTimeChanging; | |
| 116 | 删除: } | |
| 117 | 删除: | |
| 118 | 删除: | |
| 119 | 删除: | |
| 120 | 删除: private void DateTimeObserver_OnDateTimeChanging(object sender, DateTime time) | |
| 121 | 删除: { | |
| 122 | 删除: Logger.Info("[time changed] status:" + sleepStatus + ",process:" + activeProcess + ",start:" + activeStartTime.ToString() + ",end:" + DateTime.Now.ToString() + ",time:" + time.ToString()); | |
| 123 | 删除: if (sleepStatus == SleepStatus.Wake) | |
| 124 | 删除: { | |
| 125 | 删除: UpdateTime(); | |
| 126 | 删除: } | |
| 127 | 删除: else | |
| 128 | 删除: { | |
| 129 | 删除: activeStartTime = DateTime.Now; | |
| 130 | 删除: } | |
| 106 | 新增: _appTimer.OnAppDurationUpdated += _appTimer_OnAppDurationUpdated; | |
| 131 | 107 | } |
| 132 | 108 | |
| 133 | 109 | private void AppConfig_ConfigChanged(ConfigModel oldConfig, ConfigModel newConfig) |
| @@ -188,21 +164,16 @@ namespace Core.Servicers.Instances | ||
| 188 | 164 | } |
| 189 | 165 | public void Start() |
| 190 | 166 | { |
| 191 | 删除: activeStartTime = DateTime.Now; | |
| 192 | 删除: activeProcess = null; | |
| 193 | 删除: | |
| 194 | 删除: dateTimeObserver.Start(); | |
| 167 | 新增: // appTimer必须比Observer先启动* | |
| 168 | 新增: _appTimer.Start(); | |
| 195 | 169 | appObserver.Start(); |
| 196 | 删除: | |
| 197 | 删除: if (config.General.IsWebEnabled) | |
| 198 | 删除: { | |
| 199 | 删除: browserObserver.Start(); | |
| 200 | 删除: } | |
| 170 | 新增: _webServer.Start(); | |
| 201 | 171 | } |
| 202 | 172 | public void Stop() |
| 203 | 173 | { |
| 204 | 删除: dateTimeObserver.Stop(); | |
| 205 | 174 | appObserver.Stop(); |
| 175 | 新增: _appTimer.Stop(); | |
| 176 | 新增: _webServer.Stop(); | |
| 206 | 177 | } |
| 207 | 178 | public void Exit() |
| 208 | 179 | { |
| @@ -241,7 +212,7 @@ namespace Core.Servicers.Instances | ||
| 241 | 212 | { |
| 242 | 213 | this.sleepStatus = sleepStatus; |
| 243 | 214 | |
| 244 | 删除: Logger.Info($"[{sleepStatus}] process:{activeProcess},start:{activeStartTime}"); | |
| 215 | 新增: Logger.Info($"[{sleepStatus}]"); | |
| 245 | 216 | if (sleepStatus == SleepStatus.Sleep) |
| 246 | 217 | { |
| 247 | 218 | // 进入睡眠状态 |
| @@ -251,7 +222,7 @@ namespace Core.Servicers.Instances | ||
| 251 | 222 | Stop(); |
| 252 | 223 | |
| 253 | 224 | // 更新时间 |
| 254 | 删除: UpdateTime(); | |
| 225 | 新增: UpdateAppDuration(); | |
| 255 | 226 | } |
| 256 | 227 | else |
| 257 | 228 | { |
| @@ -337,39 +308,6 @@ namespace Core.Servicers.Instances | ||
| 337 | 308 | return true; |
| 338 | 309 | } |
| 339 | 310 | |
| 340 | 删除: private void AppObserver_OnAppActive(Models.AppObserver.AppObserverEventArgs args) | |
| 341 | 删除: { | |
| 342 | 删除: if (sleepStatus == SleepStatus.Sleep) | |
| 343 | 删除: { | |
| 344 | 删除: return; | |
| 345 | 删除: } | |
| 346 | 删除: | |
| 347 | 删除: string lastActiveProcess = activeProcess != null ? activeProcess.ToString() : ""; | |
| 348 | 删除: | |
| 349 | 删除: bool isCheck = IsCheckApp(args.ProcessName, args.Description, args.File); | |
| 350 | 删除: | |
| 351 | 删除: Logger.Info($"Active[{isCheck}]:" + args.ProcessName + ",Last:" + lastActiveProcess + ",Time:" + activeStartTime.ToString()); | |
| 352 | 删除: | |
| 353 | 删除: if (activeProcess != args.ProcessName) | |
| 354 | 删除: { | |
| 355 | 删除: UpdateTime(); | |
| 356 | 删除: } | |
| 357 | 删除: | |
| 358 | 删除: if (isCheck) | |
| 359 | 删除: { | |
| 360 | 删除: if (activeProcess == null) | |
| 361 | 删除: { | |
| 362 | 删除: activeStartTime = DateTime.Now; | |
| 363 | 删除: } | |
| 364 | 删除: activeProcess = args.ProcessName; | |
| 365 | 删除: } | |
| 366 | 删除: else | |
| 367 | 删除: { | |
| 368 | 删除: activeProcess = null; | |
| 369 | 删除: } | |
| 370 | 删除: | |
| 371 | 删除: } | |
| 372 | 删除: | |
| 373 | 311 | private void HandleLinks(string processName, int seconds, DateTime time) |
| 374 | 312 | { |
| 375 | 313 | Task.Run(() => |
| @@ -391,7 +329,7 @@ namespace Core.Servicers.Instances | ||
| 391 | 329 | if (IsProcessRuning(linkProcess)) |
| 392 | 330 | { |
| 393 | 331 | // 同步更新 |
| 394 | 删除: data.SaveAppDuration(linkProcess, seconds, time); | |
| 332 | 新增: data.UpdateAppDuration(linkProcess, seconds, time); | |
| 395 | 333 | } |
| 396 | 334 | |
| 397 | 335 | } |
| @@ -421,44 +359,6 @@ namespace Core.Servicers.Instances | ||
| 421 | 359 | } |
| 422 | 360 | #endregion |
| 423 | 361 | |
| 424 | 删除: private void UpdateTime() | |
| 425 | 删除: { | |
| 426 | 删除: string app = activeProcess != null ? activeProcess.ToString() : ""; | |
| 427 | 删除: | |
| 428 | 删除: if (!string.IsNullOrEmpty(app)) | |
| 429 | 删除: { | |
| 430 | 删除: var time = new DateTime(activeStartTime.Ticks); | |
| 431 | 删除: | |
| 432 | 删除: // 更新计时 | |
| 433 | 删除: TimeSpan timeSpan = DateTime.Now - time; | |
| 434 | 删除: int seconds = (int)timeSpan.TotalSeconds; | |
| 435 | 删除: | |
| 436 | 删除: if (seconds > 3600) | |
| 437 | 删除: { | |
| 438 | 删除: Logger.Warn($"计时异常。start:{time},process:{app},duration:{seconds},status:{sleepStatus}"); | |
| 439 | 删除: activeStartTime = DateTime.Now; | |
| 440 | 删除: return; | |
| 441 | 删除: } | |
| 442 | 删除: | |
| 443 | 删除: // 如果是休眠状态要减去5分钟 | |
| 444 | 删除: if (sleepStatus == SleepStatus.Sleep) | |
| 445 | 删除: { | |
| 446 | 删除: seconds -= 300; | |
| 447 | 删除: } | |
| 448 | 删除: | |
| 449 | 删除: if (seconds > 0) | |
| 450 | 删除: { | |
| 451 | 删除: data.SaveAppDuration(app, seconds, time); | |
| 452 | 删除: | |
| 453 | 删除: // 关联进程更新 | |
| 454 | 删除: HandleLinks(app, seconds, time); | |
| 455 | 删除: } | |
| 456 | 删除: | |
| 457 | 删除: activeStartTime = DateTime.Now; | |
| 458 | 删除: OnUpdateTime?.Invoke(this, null); | |
| 459 | 删除: } | |
| 460 | 删除: } | |
| 461 | 删除: | |
| 462 | 362 | #region 处理网站数据记录配置项开关 |
| 463 | 363 | /// <summary> |
| 464 | 364 | /// 处理网站数据记录配置项开关 |
| @@ -469,17 +369,36 @@ namespace Core.Servicers.Instances | ||
| 469 | 369 | { |
| 470 | 370 | return; |
| 471 | 371 | } |
| 372 | 新增: } | |
| 373 | 新增: #endregion | |
| 472 | 374 | |
| 473 | 删除: if (config.General.IsWebEnabled) | |
| 474 | 删除: { | |
| 475 | 删除: browserObserver.Start(); | |
| 476 | 删除: } | |
| 477 | 删除: else | |
| 375 | 新增: private void _appTimer_OnAppDurationUpdated(object sender, Event.AppDurationUpdatedEventArgs e) | |
| 376 | 新增: { | |
| 377 | 新增: UpdateAppDuration(e); | |
| 378 | 新增: } | |
| 379 | 新增: | |
| 380 | 新增: private void UpdateAppDuration() | |
| 381 | 新增: { | |
| 382 | 新增: UpdateAppDuration(_appTimer.GetAppDuration()); | |
| 383 | 新增: } | |
| 384 | 新增: private void UpdateAppDuration(AppDurationUpdatedEventArgs e) | |
| 385 | 新增: { | |
| 386 | 新增: if (e == null) return; | |
| 387 | 新增: | |
| 388 | 新增: var app = e.App; | |
| 389 | 新增: int duration = e.Duration; | |
| 390 | 新增: DateTime startTime = e.ActiveTime; | |
| 391 | 新增: | |
| 392 | 新增: bool isCheck = IsCheckApp(app.Process, app.Description, app.ExecutablePath); | |
| 393 | 新增: if (isCheck) | |
| 478 | 394 | { |
| 479 | 删除: browserObserver.Stop(); | |
| 395 | 新增: // 更新统计时长 | |
| 396 | 新增: data.UpdateAppDuration(app.Process, duration, startTime); | |
| 397 | 新增: // 关联进程更新 | |
| 398 | 新增: HandleLinks(app.Process, duration, startTime); | |
| 399 | 新增: OnUpdateTime?.Invoke(this, null); | |
| 480 | 400 | } |
| 481 | 401 | } |
| 482 | 删除: #endregion | |
| 483 | 402 | |
| 484 | 403 | } |
| 485 | 404 | } |
| @@ -0,0 +1,57 @@ | ||
| 1 | 新增:using Core.Librarys; | |
| 2 | 新增:using Core.Models.AppObserver; | |
| 3 | 新增:using Core.Servicers.Interfaces; | |
| 4 | 新增:using System; | |
| 5 | 新增:using System.Collections.Generic; | |
| 6 | 新增:using System.Linq; | |
| 7 | 新增:using System.Text; | |
| 8 | 新增:using System.Threading.Tasks; | |
| 9 | 新增: | |
| 10 | 新增:namespace Core.Servicers.Instances | |
| 11 | 新增:{ | |
| 12 | 新增: public class WindowManager : IWindowManager | |
| 13 | 新增: { | |
| 14 | 新增: | |
| 15 | 新增: public WindowInfo GetWindowInfo(IntPtr handle_) | |
| 16 | 新增: { | |
| 17 | 新增: try | |
| 18 | 新增: { | |
| 19 | 新增: string title = GetWindowTitle(handle_); | |
| 20 | 新增: var rect = Win32API.GetWindowRect(handle_); | |
| 21 | 新增: string className = Win32API.GetWindowClassName(handle_); | |
| 22 | 新增: int width = rect.Width; | |
| 23 | 新增: int height = rect.Height; | |
| 24 | 新增: int x = rect.Left; | |
| 25 | 新增: int y = rect.Top; | |
| 26 | 新增: | |
| 27 | 新增: return new WindowInfo(className, title, handle_, width, height, x, y); | |
| 28 | 新增: } | |
| 29 | 新增: catch (Exception e) | |
| 30 | 新增: { | |
| 31 | 新增: return WindowInfo.Empty; | |
| 32 | 新增: } | |
| 33 | 新增: | |
| 34 | 新增: } | |
| 35 | 新增: | |
| 36 | 新增: /// <summary> | |
| 37 | 新增: /// 获取窗口标题 | |
| 38 | 新增: /// </summary> | |
| 39 | 新增: /// <param name="handle_"></param> | |
| 40 | 新增: /// <returns></returns> | |
| 41 | 新增: private string GetWindowTitle(IntPtr handle_) | |
| 42 | 新增: { | |
| 43 | 新增: try | |
| 44 | 新增: { | |
| 45 | 新增: int titleCapacity = Win32API.GetWindowTextLength(handle_) * 2; | |
| 46 | 新增: StringBuilder stringBuilder = new StringBuilder(titleCapacity); | |
| 47 | 新增: Win32API.GetWindowText(handle_, stringBuilder, stringBuilder.Capacity); | |
| 48 | 新增: string title = stringBuilder.ToString(); | |
| 49 | 新增: return stringBuilder.ToString(); | |
| 50 | 新增: } | |
| 51 | 新增: catch (Exception e) | |
| 52 | 新增: { | |
| 53 | 新增: return string.Empty; | |
| 54 | 新增: } | |
| 55 | 新增: } | |
| 56 | 新增: } | |
| 57 | 新增:} | |
| @@ -0,0 +1,20 @@ | ||
| 1 | 新增:using Core.Models.AppObserver; | |
| 2 | 新增:using NPOI.XSSF.Model; | |
| 3 | 新增:using System; | |
| 4 | 新增:using System.Collections.Generic; | |
| 5 | 新增:using System.Linq; | |
| 6 | 新增:using System.Text; | |
| 7 | 新增:using System.Threading.Tasks; | |
| 8 | 新增: | |
| 9 | 新增:namespace Core.Servicers.Interfaces | |
| 10 | 新增:{ | |
| 11 | 新增: public interface IAppManager | |
| 12 | 新增: { | |
| 13 | 新增: /// <summary> | |
| 14 | 新增: /// 通过窗口句柄获取应用信息 | |
| 15 | 新增: /// </summary> | |
| 16 | 新增: /// <param name="hwnd_">窗口句柄</param> | |
| 17 | 新增: /// <returns></returns> | |
| 18 | 新增: AppInfo GetAppInfo(IntPtr hwnd_); | |
| 19 | 新增: } | |
| 20 | 新增:} | |
| @@ -24,6 +24,6 @@ namespace Core.Servicers.Interfaces | ||
| 24 | 24 | /// <summary> |
| 25 | 25 | /// 切换活跃APP时发生 |
| 26 | 26 | /// </summary> |
| 27 | 删除: event ObserverEventHandler OnAppActive; | |
| 27 | 新增: event AppObserverEventHandler OnAppActiveChanged; | |
| 28 | 28 | } |
| 29 | 29 | } |
| @@ -0,0 +1,31 @@ | ||
| 1 | 新增:using Core.Event; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增: | |
| 8 | 新增:namespace Core.Servicers.Interfaces | |
| 9 | 新增:{ | |
| 10 | 新增: public interface IAppTimerServicer | |
| 11 | 新增: { | |
| 12 | 新增: /// <summary> | |
| 13 | 新增: /// 当有应用的计时更新时发生 | |
| 14 | 新增: /// </summary> | |
| 15 | 新增: event AppTimerEventHandler OnAppDurationUpdated; | |
| 16 | 新增: | |
| 17 | 新增: /// <summary> | |
| 18 | 新增: /// 启动计时服务 | |
| 19 | 新增: /// </summary> | |
| 20 | 新增: void Start(); | |
| 21 | 新增: /// <summary> | |
| 22 | 新增: /// 停止计时服务 | |
| 23 | 新增: /// </summary> | |
| 24 | 新增: void Stop(); | |
| 25 | 新增: /// <summary> | |
| 26 | 新增: /// 获取当前应用的计时信息 | |
| 27 | 新增: /// </summary> | |
| 28 | 新增: /// <returns></returns> | |
| 29 | 新增: AppDurationUpdatedEventArgs GetAppDuration(); | |
| 30 | 新增: } | |
| 31 | 新增:} | |
| @@ -17,7 +17,7 @@ namespace Core.Servicers.Interfaces | ||
| 17 | 17 | /// <param name="processName_">进程名称</param> |
| 18 | 18 | /// <param name="duration_">时长(秒)</param> |
| 19 | 19 | /// <param name="startDateTime_">记录开始时间</param> |
| 20 | 删除: void SaveAppDuration(string processName_, int duration_, DateTime startDateTime_); | |
| 20 | 新增: void UpdateAppDuration(string processName_, int duration_, DateTime startDateTime_); | |
| 21 | 21 | |
| 22 | 22 | /// <summary> |
| 23 | 23 | /// 获取今天的数据 |
| @@ -0,0 +1,20 @@ | ||
| 1 | 新增:using Core.Models.AppObserver; | |
| 2 | 新增:using System; | |
| 3 | 新增:using System.Collections.Generic; | |
| 4 | 新增:using System.Linq; | |
| 5 | 新增:using System.Text; | |
| 6 | 新增:using System.Threading.Tasks; | |
| 7 | 新增:using static Core.Librarys.Win32API; | |
| 8 | 新增: | |
| 9 | 新增:namespace Core.Servicers.Interfaces | |
| 10 | 新增:{ | |
| 11 | 新增: public interface IWindowManager | |
| 12 | 新增: { | |
| 13 | 新增: /// <summary> | |
| 14 | 新增: /// 获取窗口信息 | |
| 15 | 新增: /// </summary> | |
| 16 | 新增: /// <param name="handle_">窗口句柄</param> | |
| 17 | 新增: /// <returns></returns> | |
| 18 | 新增: WindowInfo GetWindowInfo(IntPtr handle_); | |
| 19 | 新增: } | |
| 20 | 新增:} | |
| @@ -92,8 +92,11 @@ namespace UI | ||
| 92 | 92 | { |
| 93 | 93 | // 核心服务 |
| 94 | 94 | services.AddSingleton<IDatabase, Database>(); |
| 95 | 新增: services.AddSingleton<IAppManager, AppManager>(); | |
| 96 | 新增: services.AddSingleton<IWindowManager, WindowManager>(); | |
| 97 | 新增: services.AddSingleton<IAppTimerServicer, AppTimerServicer>(); | |
| 95 | 98 | services.AddSingleton<IAppObserver, AppObserver>(); |
| 96 | 删除: services.AddSingleton<IBrowserObserver, BrowserObserver>(); | |
| 99 | 新增: services.AddSingleton<IWebServer, WebServer>(); | |
| 97 | 100 | services.AddSingleton<IMain, Main>(); |
| 98 | 101 | services.AddSingleton<IData, Data>(); |
| 99 | 102 | services.AddSingleton<IWebData, WebData>(); |
| @@ -167,7 +170,7 @@ namespace UI | ||
| 167 | 170 | isSelfStart = true; |
| 168 | 171 | } |
| 169 | 172 | } |
| 170 | 删除: main.Start(isSelfStart); | |
| 173 | 新增: main.Start(isSelfStart); | |
| 171 | 174 | |
| 172 | 175 | // 创建保活窗口 |
| 173 | 176 | keepaliveWindow = new HideWindow(); |
| @@ -67,11 +67,12 @@ namespace UI.Servicers | ||
| 67 | 67 | |
| 68 | 68 | WatchStateAsync(); |
| 69 | 69 | |
| 70 | 删除: _appObserver.OnAppActive += _appObserver_OnAppActive; | |
| 70 | 新增: _appObserver.OnAppActiveChanged += _appObserver_OnAppActiveChanged; ; | |
| 71 | 71 | _themeServicer.OnThemeChanged += _themeServicer_OnThemeChanged; |
| 72 | 72 | Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException; |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 新增: | |
| 75 | 76 | private void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) |
| 76 | 77 | { |
| 77 | 78 | _statusBarIcon.Visible = false; |
| @@ -83,7 +84,7 @@ namespace UI.Servicers | ||
| 83 | 84 | _contextMenu.UpdateDefaultStyle(); |
| 84 | 85 | } |
| 85 | 86 | |
| 86 | 删除: private void _appObserver_OnAppActive(Core.Models.AppObserver.AppObserverEventArgs args) | |
| 87 | 新增: private void _appObserver_OnAppActiveChanged(object sender, Core.Event.AppActiveChangedEventArgs e) | |
| 87 | 88 | { |
| 88 | 89 | Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => |
| 89 | 90 | { |

