"I use FindChild quite a bit to patch up a broken automation until I can get around to fixing the name map"
Exactly the problem! "Broken Automation due to namemapping". This is the problem we are avoiding.
On Paper it sounds good.. and if your app is like Calculator where it all names itself nicely.
Here's an example of a dev express control's Fullname:
Sys.Process("MyApp").WPFObject("HwndSource: root").WPFObject("root").WPFObject("Grid", "", 1).WPFObject("FloatingContainerBorder").WPFObject("Grid", "", 1).WPFObject("FloatingContainerBody").WPFObject("border").WPFObject("Grid", "", 1).WPFObject("PART_ContainerContent").WPFObject("Grid", "", 1).WPFObject("DockPanel", "", 1).WPFObject("dockLayoutManager").WPFObject("spreadUserControlLayoutGroup").WPFObject("spreadUserControlLayoutPanel").WPFObject("DockPanel", "", 1).WPFObject("spreadLadder").WPFObject("gridControl").WPFObject("gridView").WPFObject("HierarchyPanel", "", 1).WPFObject("RowControl", "", 22).WPFObject("CellsControl", "", 1).WPFObject("LightweightCellEditor")
Here's how it namemapped itself:
Aliases.MyApp.Spread.root.Grid.FloatingContainerBorder.Grid.FloatingContainerBody.border.Grid.PART_ContainerContent.Grid.DockPanel.dockLayoutManager.spreadUserControlLayoutGroup.spreadUserControlLayoutPanel.DockPanel.PriceLadder.spreadLadder.gridView.HierarchyPanel.RowControl.CellsControl.LightWeightCellEditor
Here's how it looks with FindChild:
Sys.Process("MyApp").FindChild("Name", "WPFObject(""LightweightCellEditor"")", 99999)
I'd take FindChild ANY DAY OF THE WEEK over the other two methods for multiple reasons...
1. It is much more readable and concise when sifting through code. It's insane to try to manage all those in-between objects.
2. When (not if) the grid object system (DevExpress in this case) gets updated, it ALWAYS changes the fullname somewhere in the middle. This in turn breaks the name mapping. Imagine now I have about 50 mapped items, and while some might figure themselves out when parents are fixed, most do not because the changes are later in the object string. With FindChild, I rarely need to change anything because it only care about the beginning and the end, the rest is dynamic.
3. It always gets the "latest" refresh on demand so if the properties have changed within the app, like color or data, it will automatically grap the latest data when I do the lookup.
4. There is surprisingly little to no performance difference between namemapping and doing live lookups. This shocked me the most and when I saw how fast it was I've never looked back.
Namemapping is a no-go for our testing because of the extreme length of object names and volatility of the changes. One slight change anywhere in the fullname will break far too much. I am surprised this doesn't affect more people.
Using my Accessor function above, I can simplify it more by giving a nickname to that FindChild call. In this case the obvious name could be "LightweightCellEditor". Granted that may be too generic as there will be other grids that will also have this name, but this was just an example. Usually for similar objects there is one identifying factor that makes it unique. For example, 2 buttons that are side by side:
Set BuyButton = standaloneWindow.FindChild("NativeClrObject.Name", "buyButton", 999999)
Set SellButton = standaloneWindow.FindChild("NativeClrObject.Name", "sellButton", 999999)
Sometimes you even need multiple FindChild calls in one line as there may be 2 grids that use "gridControl" but somewhere in the middle, their parent wrapper is unique:
Sys.Process("MyApp").FindChild("Name", "ordersUserControl", 9999).FindChild("Name", "WPFObject(""gridControl"")", 99999)
Sys.Process("MyApp").FindChild("Name", "filledOrdersUserControl", 9999).FindChild("Name", "WPFObject(""gridControl"")", 99999)
That is still much more plausible than the original fullname or name map.