I have a rough idea, we can use a service.
Tutorial: Create a Windows service app
Use Timer to detect whether the browser is open, record the currently active page, add it to a List<HistoryItem>
, and then use another Timer to detect whether the currently active page has changed. If it changes, record the current time, which is the start time of the current page and the end time of the previous page.
At the same time, query whether the current page already exists in the list, if it already exists, modify the VisitedTime of that item.
Because the user may switch pages during the two polls of the Timer, the time obtained by this method is not completely accurate, just relatively close.
Moreover, as cooldadtx said, if a user opens a page for a long time without any action, we cannot tell whether the user is active or not, maybe he is reading a difficult paper. So in this way, as long as the page does not switch, we will treat it as active.
HistoryItem Class:
public class HistoryItem
{
public string Title { get; set; }
public DateTime VisitedTime { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}
Check if the browser is running:
static bool CheckIfBrowserIsRunning()
{
Process[] Processes = Process.GetProcessesByName("chrome");
if (Processes.Length <= 0)
return false;
if (!Processes.Any(d => d.MainWindowHandle != IntPtr.Zero))
return false;
return true;
}
Get the title of the currently active window:
class Program
{
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(Win32Callback enumProc, IntPtr lParam);
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
List<IntPtr> pointers = GCHandle.FromIntPtr(pointer).Target as List<IntPtr>;
pointers.Add(handle);
return true;
}
[DllImport("User32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr windowHandle, StringBuilder stringBuilder, int nMaxCount);
[DllImport("user32.dll", EntryPoint = "GetWindowTextLength", SetLastError = true)]
internal static extern int GetWindowTextLength(IntPtr hwnd);
private static string GetTitle(IntPtr handle)
{
int length = GetWindowTextLength(handle);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(handle, sb, sb.Capacity);
return sb.ToString();
}
private static List<IntPtr> GetAllWindows()
{
Win32Callback enumCallback = new Win32Callback(EnumWindow);
List<IntPtr> pointers = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(pointers);
try
{
EnumWindows(enumCallback, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated) listHandle.Free();
}
return pointers;
}
static void Main(string[] args)
{
foreach (var item in GetAllWindows())
{
string title = GetTitle(item);
Console.WriteLine(title);
if (title.Contains("Google Chrome"))
{
Console.WriteLine(title);
}
}
Console.WriteLine("Press any key to continue......");
Console.ReadLine();
}
}
The link I refer to:
Getting the current tab's URL from Google Chrome using C#
Update(6/25):
Method to get the URL of the active window:
private static string GetUrlInternal()
{
string sURL = null;
Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
if (chrome.MainWindowHandle == IntPtr.Zero)
{
continue;
}
AutomationElement element = AutomationElement.FromHandle(chrome.MainWindowHandle);
AutomationElement elm1 = element.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
AutomationElement elm2 = TreeWalker.RawViewWalker.GetLastChild(elm1);
AutomationElement elm3 = elm2.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""));
AutomationElement elm4 = elm3.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar));
AutomationElement elementx = elm1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
if (!(bool)elementx.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty))
{
sURL = ((ValuePattern)elementx.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
}
return sURL;
}
If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.