| 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></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 | } |