2

I am trying to read data grid items in SysListView32 of another process using C# .net ui-automation and winapi

C# code using ui-automation
http://pastebin.com/6x7rXMiW

C# code using winapi http://pastebin.com/61RjXZuK

using this code you just have to place your Mouse pointer on SysListView32 on screen and press Enter.

now both code returns empty on the cell item which have following properties

pastebin.com/Rw9FGkYC

but both code works on following properties

pastebin.com/L51T4PLu

the only difference i noted that the name property contains the same data as in cell but problem occurs when name property is empty.

Is there any other way to read the cell ? or any changes I can make, Please elaborate.

Nate
  • 30,286
  • 23
  • 113
  • 184
Bravo
  • 21
  • 1
  • 2
  • You might want to use the [inspect tool](http://msdn.microsoft.com/en-us/library/windows/desktop/dd318521(v=vs.85).aspx) to check that the UIAutomation tree is as you expect, and has the right structure with each node having the names and values you expect. In details view, there's multiple levels, with sub-items for the cells that are children of the parent row. (Also, you might need to use child.Current.Name to get the name, I don't know if ToString() is reliable on an AutomationElement.) – BrendanMcK Jun 01 '12 at 06:47

1 Answers1

4

I would also suggest the Inspect tool. If you see this:

IsLegacyIAccessiblePatternAvailable:    true

you can use the LegacyIAccessiblePattern. Other posts seem to indicate that it is not yet in the Client UI Automation Api, but it is in the core. You can use the core in .NET by wrapping it. I added this into my build to begin using it:

"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\tlbimp.exe" %windir%\system32\UIAutomationCore.dll /out:..\interop.UIAutomationCore.dll"

I can add more details if this pattern is indeed supported.


Well, then you are probably good.

Here is some sample code:

    // C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\UIAutomationClient.h
    public const int UIA_LegacyIAccessibleNamePropertyId = 30092;
    public const int UIA_LegacyIAccessibleValuePropertyId = 30093;
    public const int UIA_IsTextPatternAvailablePropertyId = 30040;
    public const int UIA_IsItemContainerPatternAvailablePropertyId = 30108;
    public const int UIA_AutomationIdPropertyId = 30011;
    public const int UIA_NamePropertyId = 30005;
    public const int UIA_IsInvokePatternAvailablePropertyId = 30031;

    public const int UIA_ItemContainerPatternId = 10019;
    public const int UIA_TextPatternId = 10014;
    public const int UIA_LegacyIAccessiblePatternId = 10018;
    public const int UIA_ValuePatternId = 10002;
    public const int UIA_InvokePatternId = 10000;

    public const int UIA_ButtonControlTypeId = 50000;

        uiAutomationCore = new UiAutomationCore();
        cacheRequest = UiAuto.CreateCacheRequest();
        cacheRequest.AddPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
        cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleNamePropertyId);

       cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleValuePropertyId);
        cacheRequest.TreeFilter = UiAuto.ContentViewCondition;
        trueCondition = UiAuto.CreateTrueCondition();

// A Pinvoke GetChildWindows call because it is 
// the fastest way to traverse down to a handle
foreach (var child in GetChildWindows(someIUIAutomationElement.GetMainWindowHandle()))
        {
            var sb = new StringBuilder(100);
            // get the name of each window & see if it is an ultragrid
            // (get the name because the getchildwindows call only gets the handles
            User32.GetClassName(child, sb, sb.Capacity);
            var foundProperGrid = false;
            if (Win32Utils.GetText(child) != "UltraGrid1")
                continue;
            // if this is an ultragrid, create a core automation object
            var iuiae = UiCore.AutoElementFromHandle(child);

            // get the children of the grid
            var outerArayOfStuff =
                iuiae.FindAllBuildCache(interop.UIAutomationCore.TreeScope.TreeScope_Children,
                                        trueCondition,
                                        cacheRequest.Clone());

            var countOuter = outerArayOfStuff.Length;
            // loop through the grid children 
            for (var counterOuter = 0; counterOuter < countOuter; counterOuter++)
            {
                // make a core automation object from each
                var uiAutomationElement = outerArayOfStuff.GetElement(counterOuter);

                // hacky - see if this grid has a GroupBy Box as first 'row'
                //       - if so, this is the proper grid
                //       - ignore other grids
                if (!foundProperGrid && uiAutomationElement.CurrentName.Equals("GroupBy Box"))
                {
                    foundProperGrid = true;
                }
                else if (foundProperGrid)
                {
                    // 'cast' the object to a core 'legacy msaa' object
                    IUIAutomationLegacyIAccessiblePattern outerLegacyPattern =
                        uiAutomationElement.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
                    Log.Info("OUTER, CachedName = " + outerLegacyPattern.CachedName);

                    try
                    {
                        // select the 'row' to give visual feedback
                        outerLegacyPattern.Select(3);
                    }
                    catch (Exception exc)
                    {
                        Log.Info(exc.Message);
                    }

                    // get the cells in a row
                    var arrayOfStuff =
                        uiAutomationElement.FindAllBuildCache(TreeScope.TreeScope_Children,
                                                                trueCondition,
                                                                cacheRequest.Clone());
                    // loop over the cells in a row
                    var count = arrayOfStuff.Length;
                    for (var counter = 0; counter < count; counter++)
                    {
                        // get a cell
                        var currIUIA = arrayOfStuff.GetElement(counter);

                        // 'cast' cell to a core 'legacy msaa' object
                        IUIAutomationLegacyIAccessiblePattern legacyPattern =
                            currIUIA.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);

                        // dump cell name & value for reference
                        var name = legacyPattern.CachedName;
                        Log.Info(counter + ") CachedName = " + name);
                        var value = legacyPattern.CachedValue;
                        Log.Info("CachedValue = " + value);
                        // check if cell name corresponds to what is being checked
                        if (name.Equals("Date"))
                        {
                            //if (!value.StartsWith("5/23/2012"))
                            if (!value.StartsWith("5/25/2012"))
                                errorList.AppendLine("Bad Date = " + value);
                        }
                        if (name.Equals("XXX"))
                        {
                            if (!(value.Equals("1") || value.Equals("2")))
                                errorList.AppendLine("Bad XXX= " + value);
                        }
                        if (name.Equals("YYY"))
                        {
                            if (!value.Equals("ZZZ"))
                                errorList.AppendLine("Bad YYY = " + value);
                        }
                    }
                }
            }
            foundProperGrid = false;
        }
        var stopTime = DateTime.Now;
        var duration = stopTime - startTime;
        Log.Info("duration = " + duration);

        if (!"".Equals(errorList.ToString()))
        {
            Log.Info("errorList = " + errorList);
            Assert.Fail("Test errors");
        }
    }
chrismead
  • 2,163
  • 3
  • 24
  • 36
  • i don't have Inspect tool :(, but other tools doesn't seem to show that LegacyIAccessiblePattern true. – Bravo Jun 02 '12 at 07:17
  • I cut pasted code from a couple different places some some things (like the classname WindowsConstants) might seem a bit out of place. – chrismead Jun 02 '12 at 23:49
  • i don't know how to use it properly, but i found another way around for my problem, now i am sending message to list handle to copy the grid then grab the data from clipboard. – Bravo Jun 03 '12 at 09:38
  • glad you got it. you might want to post your solution for future searchers.. cheers. – chrismead Jun 03 '12 at 19:42
  • @Bravo: I have the same problem you described. Can you please post more details about the solution. Thank you. – Roi Shabtai Jul 10 '12 at 14:05
  • hey, There was Copy option in context menu of that particular grid, so i invoked that and get clipboard data from memory, but it may create serious problems. – Bravo Aug 22 '12 at 06:33