Automationelement to detect chrome url is not consistence

Ravi Sharma 11 Reputation points
2021-07-29T09:51:00.243+00:00

I am using below code to detect active tab url in chrome browser but this gives result sometimes but not always. This take while for some urls. Chrom version : 86 and above

Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
if (chrome.MainWindowHandle == IntPtr.Zero)
continue;
AutomationElement element = AutomationElement.FromHandle(chrome.MainWindowHandle);
if (element == null)
return "element null";
Condition conditions = new AndCondition(
new PropertyCondition(AutomationElement.ProcessIdProperty, chrome.Id),
new PropertyCondition(AutomationElement.IsControlElementProperty, true),
new PropertyCondition(AutomationElement.IsContentElementProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));

            AutomationElement elementx = element.FindFirst(TreeScope.Descendants, conditions);
            if (elementx == null)
                return "blank";
            return ((ValuePattern)elementx.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
        }
Developer technologies | C#
{count} vote

1 answer

Sort by: Most helpful
  1. Castorix31 90,681 Reputation points
    2021-07-29T20:06:17.227+00:00

    For Chrome, I must enumerate the windows instead of using Process.GetProcessesByName which don't find them all (works with Edge)

    // Add reference to : "C:\Windows\system32\UIAutomationCore.dll"
    // Add : using UIAutomationClient;
    

    //

    EnumWindowsProc Callback = new EnumWindowsProc(ListWindows);
    IntPtr plParam = IntPtr.Zero;
    EnumDesktopWindows(IntPtr.Zero, Callback, ref plParam);
    

    //

    public bool ListWindows(IntPtr hWnd, ref IntPtr lParam)
    {
        StringBuilder sbClassName = new StringBuilder(260);
        string sClassName = null;
        GetClassName(hWnd, sbClassName, (int)(sbClassName.Capacity));
        sClassName = sbClassName.ToString();
        if (sClassName == "Chrome_WidgetWin_1" && IsWindowVisible(hWnd))
        {
            int nPID = 0;
            uint nSize = 260;
            StringBuilder sbProcessImageName = new StringBuilder((int)nSize);
            uint nThreadId = GetWindowThreadProcessId(hWnd, out nPID);
            IntPtr hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, nPID);               
            if (hProcess != IntPtr.Zero)
            {  
                QueryFullProcessImageName(hProcess, 0, sbProcessImageName, ref nSize);
                if (sbProcessImageName.ToString().Contains("chrome"))
                {
                    Console.WriteLine("hWnd = 0x{0}, Class = {1}, PID = {2} Exe = {3}", hWnd.ToString("x"), sClassName, nPID.ToString(), sbProcessImageName.ToString());
                    {
                        IUIAutomation pUIAutomation = new CUIAutomation();
                        IUIAutomationElement windowElement = pUIAutomation.ElementFromHandle(hWnd);
                        if (windowElement != null)
                        {
                            IUIAutomationElementArray elementArray = null;
                            IUIAutomationCondition condition = null;
                            condition = pUIAutomation.CreateTrueCondition();
                            elementArray = windowElement.FindAll(TreeScope.TreeScope_Descendants, condition);
                            IUIAutomationElement elementAddressBar = null;
                            if (elementArray != null)
                            {
                                int nNbItems = elementArray.Length;
                                for (int nItem = 0; nItem <= nNbItems - 1; nItem++)
                                {
                                    IUIAutomationElement element = elementArray.GetElement(nItem);
                                    string sName = element.CurrentName;
                                    string sAutomationId = element.CurrentAutomationId;
                                    string sAccessKey = element.CurrentAccessKey; // Ctrl+L
                                    Console.WriteLine("Name : {0} - AutomationId : {1}", sName, sAutomationId);
                                    int nType = element.CurrentControlType;
                                    if (nType == 50004 && sAccessKey == "Ctrl+L") // 50004 = UIA_EditControlTypeId
                                    {
                                        elementAddressBar = element;
                                        break;
                                    }                                       
                                }
                                if (elementAddressBar != null)
                                {
                                    Object pPattern = null;
                                    pPattern = elementAddressBar.GetCurrentPattern(10018); // UIA_PatternIds.UIA_LegacyIAccessiblePatternId
                                    if (pPattern != null)
                                    {
                                        IUIAutomationLegacyIAccessiblePattern pLegacyIAccessiblePattern = (IUIAutomationLegacyIAccessiblePattern)pPattern;
                                        String sValue = pLegacyIAccessiblePattern.CurrentValue;
                                        MessageBox.Show(String.Format("Current URL = {0}", sValue), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    }
                                }
                            }
                        }
                    }
                }                 
                CloseHandle(hProcess);
            }
        }
        return true;
    }
    

    Declarations :

    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProc lpEnumFunc, ref IntPtr lParam);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool QueryFullProcessImageName(IntPtr hProcess, int dwFlags, StringBuilder lpExeName, ref uint lpdwSize);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool CloseHandle(IntPtr hObject);
    
    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
    
    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool IsWindowVisible(IntPtr hWnd);
    
    public const long SYNCHRONIZE = (0x00100000L);
    public const int STANDARD_RIGHTS_REQUIRED = (0x000F0000);
    
    public const int PROCESS_VM_READ = (0x0010);
    public const int PROCESS_VM_WRITE = (0x0020);
    public const int PROCESS_DUP_HANDLE = (0x0040);
    public const int PROCESS_CREATE_PROCESS = (0x0080);
    public const int PROCESS_SET_QUOTA = (0x0100);
    public const int PROCESS_SET_INFORMATION = (0x0200);
    public const int PROCESS_QUERY_INFORMATION = (0x0400);
    public const int PROCESS_SUSPEND_RESUME = (0x0800);
    public const int PROCESS_QUERY_LIMITED_INFORMATION = (0x1000);
    public const int PROCESS_SET_LIMITED_INFORMATION = (0x2000);
    public const long PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF);
    
    public delegate bool EnumWindowsProc(IntPtr hWnd, ref IntPtr lParam);
    
    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.