跳到主要内容

github/tai

公开

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

提交记录

Merge pull request #163 from l1nxy/add-support-for-vivaldi

Add browser support for Vivaldi.

作者
Berumotto
时间
2023/04/19 17:40
提交
5d84313
这个版本的全部文件

这是一个合并提交,下面是和第一个上一提交相比的改动。

修改Core/Core.csproj+1 −0看文件
@@ -208,6 +208,7 @@
208208 <Compile Include="Servicers\Interfaces\ISleepdiscover.cs" />
209209 <Compile Include="Servicers\Interfaces\IWebData.cs" />
210210 <Compile Include="Servicers\Interfaces\IWebFilter.cs" />
211新增: <Compile Include="Servicers\Instances\VivaldiBrowserWatch.cs" />
211212 </ItemGroup>
212213 <ItemGroup>
213214 <None Include="App.config" />
修改Core/Enums/BrowserType.cs+7 −1看文件
@@ -22,6 +22,12 @@ namespace Core.Enums
2222 /// <summary>
2323 /// Microsoft Edge
2424 /// </summary>
25删除: MSEdge
25新增: MSEdge,
26新增: /// <summary>
27新增: /// Vivaldi
28新增: /// </summary>
29新增: Vivaldi
30新增:
31新增:
2632 }
2733}
修改Core/Servicers/Instances/BrowserObserver.cs+6 −0看文件
@@ -109,6 +109,9 @@ namespace Core.Servicers.Instances
109109 case "msedge":
110110 StartWatch(BrowserType.MSEdge, args.Handle);
111111 break;
112新增: case "vivaldi":
113新增: StartWatch(BrowserType.Vivaldi, args.Handle);
114新增: break;
112115 default:
113116 StopWatch();
114117 break;
@@ -124,6 +127,9 @@ namespace Core.Servicers.Instances
124127 {
125128 case BrowserType.Chrome:
126129 _browserWatcher = new ChromeBrowserWatch();
130新增: break;
131新增: case BrowserType.Vivaldi:
132新增: _browserWatcher = new VivaldiBrowserWatch();
127133 break;
128134 case BrowserType.MSEdge:
129135 _browserWatcher = new MSEdgeBrowserWatch();
新增Core/Servicers/Instances/VivaldiBrowserWatch.cs+220 −0看文件
@@ -0,0 +1,220 @@
1新增:using Core.Enums;
2新增:using Core.Event;
3新增:using Core.Librarys;
4新增:using Core.Librarys.Browser.Favicon;
5新增:using Core.Models.WebPage;
6新增:using Core.Servicers.Interfaces;
7新增:using NPOI.SS.Formula.Functions;
8新增:using System;
9新增:using System.Collections.Generic;
10新增:using System.Data.SQLite;
11新增:using System.Diagnostics;
12新增:using System.IO;
13新增:using System.Linq;
14新增:using System.Security.Cryptography;
15新增:using System.Text;
16新增:using System.Threading.Tasks;
17新增:using System.Windows.Automation;
18新增:using System.Windows.Interop;
19新增:using UIAutomationClient;
20新增:
21新增:namespace Core.Servicers.Instances
22新增:{
23新增: public class VivaldiBrowserWatch : IBrowserWatcher
24新增: {
25新增: public event BrowserObserverEventHandler OnSiteChanged;
26新增: private string url, title;
27新增: CUIAutomation automation;
28新增: // 根元素(监听站点切换使用)
29新增: IUIAutomationElement rootElement;
30新增: // 主元素(寻找URL使用)
31新增: IUIAutomationElement mainElement;
32新增: // 站点切换事件
33新增: AutomationPropertyChangedEventHandler siteChangedEventHandler;
34新增:
35新增: public VivaldiBrowserWatch()
36新增: {
37新增: automation = new CUIAutomation();
38新增: siteChangedEventHandler = new AutomationPropertyChangedEventHandler(OnNameChanged);
39新增: }
40新增:
41新增: public void StartWatch(IntPtr handle)
42新增: {
43新增: try
44新增: {
45新增: if (handle == IntPtr.Zero)
46新增: {
47新增: throw new Exception("未传入浏览器句柄");
48新增: }
49新增:
50新增: Win32API.GetWindowThreadProcessId(handle, out int processID);
51新增: Process process = Process.GetProcessById(processID);
52新增: if (process == null)
53新增: {
54新增: return;
55新增: }
56新增:
57新增: Debug.WriteLine("启动浏览器监听,目标:" + process.ProcessName);
58新增: // 搜索根元素
59新增: rootElement = automation.ElementFromHandle(handle);
60新增: if (rootElement == null)
61新增: {
62新增: throw new Exception("找不到根元素!");
63新增: }
64新增: // 找到窗口
65新增: var condtionPanel = automation.CreatePropertyCondition(30003, 50033);
66新增: var condtionName = automation.CreatePropertyCondition(30005, "Chrome_WidgetWin_1");
67新增: var condtionFindWindow = automation.CreateAndCondition(condtionPanel, condtionName);
68新增: var window = rootElement.FindFirst(TreeScope.TreeScope_Children, condtionFindWindow);
69新增: if (window != null)
70新增: {
71新增: // 第二个窗口
72新增: mainElement = window.FindFirst(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
73新增: }
74新增: else
75新增: {
76新增: mainElement = rootElement;
77新增: Debug.WriteLine("没有找到主窗口,使用根元素作为主元素");
78新增: }
79新增:
80新增:
81新增: if (mainElement == null)
82新增: {
83新增: throw new Exception("找不到主元素!");
84新增: }
85新增:
86新增: // 注册事件
87新增: IUIAutomationCacheRequest cacheRequest = automation.CreateCacheRequest();
88新增: cacheRequest.AddProperty(30005);
89新增: int[] props = { 30005 };
90新增:
91新增: automation.AddPropertyChangedEventHandler(rootElement, TreeScope.TreeScope_Element, cacheRequest, siteChangedEventHandler, props);
92新增: Debug.WriteLine("启动浏览器监听成功");
93新增:
94新增: Handle(process.MainWindowTitle);
95新增: }
96新增: catch (Exception e)
97新增: {
98新增: Logger.Error(e.ToString());
99新增: }
100新增: }
101新增:
102新增: private void OnNameChanged(IUIAutomationElement s, int p, object v)
103新增: {
104新增: Handle(v.ToString());
105新增: }
106新增:
107新增: #region AutomationPropertyChangedEventHandler
108新增: private class AutomationPropertyChangedEventHandler : IUIAutomationPropertyChangedEventHandler
109新增: {
110新增: public AutomationPropertyChangedEventHandler(Action<IUIAutomationElement, int, object> action)
111新增: {
112新增: if (action == null)
113新增: throw new ArgumentNullException(nameof(action));
114新增:
115新增: Action = action;
116新增: }
117新增:
118新增: public Action<IUIAutomationElement, int, object> Action { get; }
119新增: public void HandlePropertyChangedEvent(IUIAutomationElement sender, int propertyId, object newValue) => Action(sender, propertyId, newValue);
120新增: }
121新增: #endregion
122新增:
123新增: public void StopWatch()
124新增: {
125新增: try
126新增: {
127新增: Debug.WriteLine("已停止浏览器监听");
128新增: automation.RemovePropertyChangedEventHandler(rootElement, siteChangedEventHandler);
129新增: }
130新增: catch (Exception e)
131新增: {
132新增: Logger.Error(e.ToString());
133新增: }
134新增: }
135新增:
136新增: private string FormatTitle(string title)
137新增: {
138新增: if (string.IsNullOrEmpty(title))
139新增: {
140新增: return title;
141新增: }
142新增: int length = title.LastIndexOf('-') - 1;
143新增: if (length < 1)
144新增: {
145新增: length = 1;
146新增: }
147新增:
148新增: return title.Substring(0, length);
149新增: }
150新增:
151新增: private async void Handle(string title)
152新增: {
153新增: title = FormatTitle(title);
154新增: //Debug.WriteLine($"切换标题 {title}");
155新增: Site site = null;
156新增: if (!string.IsNullOrEmpty(title))
157新增: {
158新增: site = SiteCache.Get(title);
159新增: }
160新增:
161新增: if (site == null)
162新增: {
163新增: string url = await GetURLSync();
164新增: site = new Site()
165新增: {
166新增: Url = url,
167新增: Title = title
168新增: };
169新增: SiteCache.Set(title, url);
170新增: }
171新增:
172新增: ResponseEvent(site.Url, site.Title);
173新增: }
174新增:
175新增: #region 获取浏览器当前URL
176新增: /// <summary>
177新增: /// 获取浏览器当前URL
178新增: /// </summary>
179新增: /// <returns></returns>
180新增: private async Task<string> GetURLSync()
181新增: {
182新增: return await Task.Run(() =>
183新增: {
184新增: string result = string.Empty;
185新增: try
186新增: {
187新增: var condtionEdit = automation.CreatePropertyCondition(30003, 50004);
188新增: var condtionName = automation.CreatePropertyCondition(30011, "urlFieldInput");
189新增: var condtion = automation.CreateAndCondition(condtionEdit, condtionAccessKey);
190新增: var addressElement = rootElement.FindFirst(TreeScope.TreeScope_Subtree, condtionName);
191新增: if (addressElement != null)
192新增: {
193新增: result = ((IUIAutomationValuePattern)addressElement.GetCurrentPattern(10002)).CurrentValue;
194新增: }
195新增: }
196新增: catch (Exception e)
197新增: {
198新增: Logger.Error(e.ToString());
199新增: }
200新增: return result;
201新增: });
202新增:
203新增: }
204新增: #endregion
205新增:
206新增: private void ResponseEvent(string url, string title)
207新增: {
208新增: if (url != this.url)
209新增: {
210新增: this.url = url;
211新增: this.title = title;
212新增: OnSiteChanged?.Invoke(BrowserType.Chrome, new Models.WebPage.Site()
213新增: {
214新增: Url = url,
215新增: Title = title
216新增: });
217新增: }
218新增: }
219新增: }
220新增:}