跳到主要内容

github/tai

公开

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

浏览文件

AppTimerServicer.cs

170 行 · 4.8 KB历史下载
1using Core.Enums;
2using Core.Event;
3using Core.Models.AppObserver;
4using Core.Servicers.Interfaces;
5using System;
6using System.Collections.Generic;
7using System.Diagnostics;
8using System.Linq;
9using System.Text;
10using System.Threading.Tasks;
11using System.Timers;
12
13namespace 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}