Get actual time spent browsing websites by user C#.NET

TkTech 56 Reputation points
2021-06-23T11:42:00.4+00:00

I have written a C#.NET app to fetch browser's history of websites visited by a user on his machine. But, want his actual time while visiting sites. For example,

  1. If user just visits a website for 3 minutes.
  2. Next, he lets the website remain open in a tab for 2 hours
  3. Goes on to do some other task on his machine

So, the total time visiting the site should be 3 minutes only.

But, this is giving total time, i.e. 2 hours , which is incorrect. Please suggest

Developer technologies | C#
{count} votes

2 answers

Sort by: Most helpful
  1. Michael Taylor 60,326 Reputation points
    2021-06-23T13:24:03.867+00:00

    There is no such information available that I'm aware of. How exactly do you know that a user is interacting with a site vs just leaving it open? The most you might have is when the site was opened (from history).

    You said you used the given link to get the time but the original link was just getting browser history. How do you know that the user even sat on a site for 2 hours? Hopefully you're not relying on time differencing between history links as that won't work at all. Please provide some sample code.

    Also please provide what problem you're actually trying to solve because honestly it sounds like you're trying to create a "big brother" app to monitor people and it probably isn't going to work.

    1 person found this answer helpful.

  2. Timon Yang-MSFT 9,606 Reputation points
    2021-06-24T03:08:28.347+00:00

    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.

    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.