I have started to automate my windows application using coded UI tests recently and facing issue while accessing some of the MSAA control.
I am hand coding my automation and do not want to add controls to UI Map and then use it.
The control on which I got stuck is a treeItem on a left pane which selects machine and details are displayed in left over client area at the center.
I have tried to search control using properties as shown by crosshair onto the UI control but in vain.
Below is the code I have tried -
UITestControl machine = new UITestControl(App);
machine.TechnologyName = "MSAA";
machine.SearchProperties.Add(WinTreeItem.PropertyNames.ControlType, "TreeItem");
machine.SearchProperties.Add(WinTreeItem.PropertyNames.Name, "Machine1");
machine.SearchProperties.Add(WinTreeItem.PropertyNames.ControlName, "m_tvPlantStructureView");
Mouse.Click(machine); // This code gives an error
ERROR-
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException:
The playback failed to find the control with the given search
properties. Additional Details: TechnologyName: 'MSAA' ControlType:
'TreeItem' Name: 'Machine1' ControlName: 'm_tvPlantStructureView'
---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.
Refer to attachments.
Let me know, what is the problem and what process to follow to completely get away of such kind of errors of controls not recognized in future.
Currently, I follow the method of doing a crosshair and getting properties and then coding on that property of control to automate user actions and assertions. But this way does not always work.
Let me know if there is any better way of doing it.
You need to do a hierarchy search. Create 2 controls: first the Treeview as Window. With control name m_tvPlantStructureView, then create a new TreeItem with name Machine1.
var treeView = new WinWindow(App);
treeView.SearchProperties.Add(WinWindow.PropertyNames.ControlName, "m_tvPlantStructureView");
var machine= new WinTreeItem(treeView);
machine.SearchProperties.Add(WinTreeItem.PropertyNames.Name, "Machine1");
Mouse.Click(machine); // This code gives an error
Another thing if this fails is to remove App from treeview and add window title.
Let me know if you have any questions.
var treeView = new WinWindow();
treeView.WindowTitles.Add("mywindowname");
treeView.SearchProperties.Add(WinWindow.PropertyNames.ControlName, "m_tvPlantStructureView");
var machine= new WinTreeItem(treeView);
machine.SearchProperties.Add(WinTreeItem.PropertyNames.Name, "Machine1");
Mouse.Click(machine); // This code gives an error
Before doing the mouse clik, I perform a search of the control using
machine.Find();
After that, I check if machine has a value distinct of null, and if is it not null, i perform the click.
Related
I'm wondering how to add several UI panels to a scripting palette in GMS 2.x. I found some commands in Gatan's outdated documentation (http://digitalmicrograph-scripting.tavernmaker.de/other%20resources/Old-DMHelp/FloatingPalettes.htm) but most of them are not found in GMS 2.32.
Given a UI class "UI_class" (including an init() function that creates the interface) I've already successfully registered the script palette and opened the corresponding gadget using:
object UI=Alloc(UI_class).init()
RegisterScriptPalette(UI,"Type","Display")
OpenGadgetPanel("Display")
Unfortunately, the command GadgetWindowAddGadgetPanel() which seemed to be the most promising to me in the first instance in order to add a second UI to the same palette cannot be found.
Does anybody know a working equivalent?
Thank you in advance for sharing your experience, I'm looking forward to see some nicely designed floating palettes!
I'm not 100% sure I understood the question correctly. Each UI derived object forms it's own "dialog", which can be displayed either as
Modal Dialog - using Pose( DlgObj )
Modeless Dialog - using Display( DlgObj, "name" )
Gadget panel - by first 'registering' it and then displaying a registed dialog
If you have multiple gadget of same width, you can add them together by drag-and drop. This is not part of the dialog - just part of how the UI interaction with dialogs. ( You drag a palette to the side of the screen to attach it, and then you can dragg other palettes on top of it. )
|
|
Example script to produce some dialogs:
Object CreateDlgObj()
{
TagGroup DialogTG = DLGCreateDialog("My Dialog")
TagGroup StrFieldTG = DLGCreateStringField("Some string",20)
DialogTG.DLGAddElement(StrFieldTG)
Object DialogObj = Alloc(UIFrame)
DialogOBJ.Init(DialogTG)
return DialogObj
}
// MAIN
// Show dialog as modal dialog
// CreateDLGObj().Pose()
// Show dialog as modeless dialog
// CreateDLGObj().Display( "NewName" )
// Register dialog as gadget and then display
// RegisterScriptPalette( CreateDLGObj(),"", "RegDlg" )
// OpenGadgetPanel( "RegDlg" )
// Create, register and display multiple dialogs as palettes
number nMax = 2
For( number i =0; i<nMax; i++)
{
string name = "MyDlg_" + i
RegisterScriptPalette( CreateDLGObj(),"", name )
OpenGadgetPanel( name )
}
Note that "Gadget panels" or "tool palettes" or whatever you call them are different in GMS 1.x, GMS 2.x and GMS 3.x as it is always the "main program" which decides how to handle the dialogs. GMS 2.x is the only version, where the program "remembers" the layout of multiple such palettes. These layouts can be saved and loaded. GMS 3 no longer has this, as all UI palettes are fixed in position. (Old custom dialogs still appear, but in a somewhat 'out-of-style' way.
GMS 2.x's "Floating Window Layout" tool:
The "layout" information stored with this tool is actually stored in the Windows registry.
But I have never used that so far. (And it also only applies to GMS 2.x.)
It is also worth mentioning, that RegisterScriptPalette does exactly what is says: It adds the UI permanently to the list of palettes the appliction knows of.
So running the script twice, you get two identical palettes. You usually don't want that! Just use OpenGadgetPanel to show any already registered palette.
However, 'registered' palettes will only remain 'registered' as long as the application is running, so they are gone at restart of DM.
If you want somethng more persistent, you need to install the code as a Library via the File menu. Note, that any executeable part of the code will be automatically run on startup. So you want to have the RegisterScriptPalette be part of that code, but not the OpenGadgetPanel.
For the last few days i have been trying to figure out the best way to get AutomationElement for a specific control in a vb6 application.
My initial way of doing so was by doing a search with the following condition:
new PropertyCondition(AutomationElement.NameProperty, controlName)
I was under the assumption that this was working correctly for about a week in a little test VB6 application.
but i few days ago i realized something... when i dragged a vb6 textbox into the form, the 'Name' property and 'Text' property were both set to 'Text1'
So when i searched with:
new PropertyCondition(AutomationElement.NameProperty, 'Text1')
it return the correct element, but if i then went and set the 'Text' property to '' the same search would bring nothing back.
Question: Has anyone found a way to get a AutomationElement based on a the VB6 control name
What i have tried:
getting the MSAA equivalent interface and looking at the 'Name' property - Result: ''
http://msdn.microsoft.com/en-us/library/windows/desktop/dd318490%28v=vs.85%29.aspx
getting the control based on other properties (AutomationId, RuntimeId) - Result: AutomationId - not all controls seem to have this property available - RuntimeId - changes each time the app runs
I have looked at alot of different sites the main one is listed below - while some say they have manage to get it working - i don't believe i can see how they do it.. or i just dont understand it :$
http://blogs.msdn.com/b/brianmcm/archive/2006/01/17/getting-the-winforms-id-of-a-control.aspx
While i have access to the demo app, i will not access to the production app as that has been created by a third party.
What i plan on doing from here is to get the Automation element based on their position on the form..
Thank you
Can't comment due to low rep. Do you absolutely HAVE to have an AutomationElement?
You may want to look at invoking [user32.dll] (http://pinvoke.net/default.aspx/user32.EnumChildWindows). Look at FindWindowEx, GetWindow, EnumWindows, EnumChildWindows, GetWindowText, etc.
You need the handle of the parent window, so you can use this loop to get it. From there you can use the other functions to get the information you need about the control.
IntPtr hWnd = IntPtr.Zero;
foreach(var process in System.Diagnostics.Process.GetProcesses())
if(condition)
hWnd = process.Handle;
Comment with the exact information you need out of the VB6 window, and I'll give you better code.
You can use the relational position of the AutomationElement in a specific Window (or any other container for that matter), in order to detect it. For example, if you have 5 TextBox AutomationElements in your main window, and you're certain that the order will not be changing, you could create a PropertyCondition on the TextBox class name, and then use the FindAll method to return a collection of AutomationElements and iterate through it, querying the BoundingRectangle property to find out which is the lowest one (or middle, or any other position, for that matter).
I would create a helper method that would return a Dictionary<int,AutomationElement> with the key being the visual position of the AutomationElement, and the value being the AutomationElement itself.
This way you can avoid using a specific Point on your screen (any window size change or element positioning will easily break your code) while not being bound to the AutomationId property.
After moving and rearranging controls on a Winform when invoking a Build and/or Rebuild All command the following error message appears :
"An error occurred while processing this command. Could not load file
or assembly 'LoLock, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null' or one of its dependencies. The system cannot
find the file specified."
At that point all the controls disappear from the Designer and form the executing form as well. I've scoured the designer cs file and run diffs against a previous working version and cannot find anything amiss.
This has happened to me on several occasions and appears to be random.
Any clues ??
I've had the same problem...exactly...same error followed by the disappearance of most of the controls. The controls that are missing in the designer are my custom controls. The change I made before the error and the disappearance was to add a constructor to each of the controls derived class (i.e. my part of the control). So far, I've noted that the Control.Add(...) is missing for each of the hundred or so controls that have disappeared (from the automatically generated Form.designer.cs file). This is the one point that seems to differ from your situation if you are running a diff on the designer.cs file between pre and post failure. Mine definitely has missing Add()s.
So far, my solution is to manually add back the Add() methods to the generated file. However, it would obviously help if there was some way to get visual studio to see this problem and add the controls back automatically. However, I can't think of any way that VS could know, at this point, which controls to add to which parent control.
For example, before the error I had the following group box defined in my designer.cs file:
//
// groupBox10
//
this.groupBox10.Controls.Add(this.checkBox_FincaDescription_ForRent);
this.groupBox10.Controls.Add(this.checkBox_FincaDescription_ForSale);
this.groupBox10.Location = new System.Drawing.Point(883, 67);
this.groupBox10.Name = "groupBox10";
this.groupBox10.Size = new System.Drawing.Size(310, 76);
this.groupBox10.TabIndex = 9;
this.groupBox10.TabStop = false;
this.groupBox10.Text = "Property Type";
After the FAIL I have the following code which was generated as a result of either the error or simply the designers failure to manage my custom controls:
//
// groupBox10
//
this.groupBox10.Location = new System.Drawing.Point(883, 67);
this.groupBox10.Name = "groupBox10";
this.groupBox10.Size = new System.Drawing.Size(310, 76);
this.groupBox10.TabIndex = 9;
this.groupBox10.TabStop = false;
this.groupBox10.Text = "Property Type";
This is a massive FAIL for me as I have so many fields to manually correct (although luckily only a few group boxes and a good backup). I have read of so many people having this same problem from 2005 on, I can't believe it hasn't been addressed.
I also experienced this with a user control.
I received an exception for each control that had the Add method removed from the designer.
Surprisingly, I had a couple of panels, and the Add code for the children of those panels remained in tact.
I only had to implement Add for those panels and a few controls that were not in containers, which is fortunate because there were over 100 controls.
An error was introduced in the constructor of the user control, and I believe that this contributed to the chain of events resulting in the corrupt designer file.
I am exploring the newly exposed framework UI Automation in iphoneOS 4.0. Has anybody tested their application using this framework. I will appreciate any help.
I am trying to test a sample application that just contains a textfield and a button. I have written a script as
UIALogger.logStart("Starting Test");
var view = UIATarget.localTarget().frontMostApp().mainWindow().elements()[0];
var textfields = view.textFields();
if (textfields.length != 1) {
UIALogger.logFail("Wrong number of text fields");
} else {
UIALogger.logPass("Right number of text fields");
}
textfields[0].setValue("anurag");
view.buttons()[0].tap();
The problem is that the value of textfield is not getting set and no button is tapped. When I run the instruments only the view(with textfield and button) appears and then notting is happening.
There is a message in instruments "Something else has happened".
If your main window contains a button and a text field (in this order in the hierarchy) then your first line of code will return you the UIAButton element, so the next line is incorrect, because you're trying to call textFields() on a button.
The first part should look like this:
var view = UIATarget.localTarget().frontMostApp().mainWindow();
var textfields = view.textFields();
if (textfields.length != 1) {
UIALogger.logFail("Wrong number of text fields");
} else {
UIALogger.logPass("Right number of text fields");
}
And in that case I think there are two ways of testing the tap and text field. Like this:
textfields[0].setValue("anurag");
view.buttons()[0].tap();
or like this:
view.elements()[1].setValue("anurag");
view.elements()[0].tap();
And personally I prefer getting objects by using Accessibility Label instead of index. For more information look for a UIAElement Class Reference and take a look here:
UI Automation Reference Collection
All this stuff is gonna work only if the application is made with that accessibility thing (its own accessibility protocol: by tagging all its UI controls in Interface Builder with names, by setting the Accessability label to a unique value for the view). Or if you work with iPhone standard controls.
If the application doesn't contain anything like that, you won't be able to do much with UI Automation and will see only a 320x480 empty canvas.
You can check this link for some more details.
For example, I work on a OpenGL application that was not built with any accessibility tag and I cannot see anything through UI Automation besides a 320x480 empty form.
I am trying to use ultimate grid from Code Project in a dialog box but the grid is invisible.
m_Plist.AttachGrid(this, IDC_CREDENTIALS) returns true but the static text place holder where the grid should be shown cant be seen and the grid is never displayed.
I am using sample the code from here http://www.codeproject.com/KB/MFC/UltimateGrid_Start.aspx?display=PrintAll&fid=452565&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2629959&fr=51#Using_the_Grid_in_a_CDialog
I have installed the latest update UltimateGrid72_Src_Update03.zip and Im using VS2008 SP1.
Thanks...
BOOL CCredentials::OnInitDialog()
{
CDialog::OnInitDialog();
MyCug m_PList;
m_Plist.AttachGrid(this, IDC_CREDENTIALS);
}
I've not used Ultimate Grid myself. However, looking at the code you posted, I can see that there is likely to be a problem: you declare an instance of "MyCug" on the stack, then attach it, but that stack-based instance will be destroyed as soon as the OnInitDialog() method exists. What you must do is put the declaration of "MyCug m_PList;" as a member of the dialog class, so that the lifetime of the grid object is the same as the lifetime of the dialog.
I don't know why your grid is not displaying, things to look for are is it correctly loading from the dialog template, and is it visible? You can use spy++ (a tool distributed with visual studio) to see what windows are actually created in your dialog, where they are and the flags and styles set on them.
After you create and attach the grid, are you adding rows and columns as defined by the examples?
Otherwise, there isn't going to be anything to see.
You'll need the following code in MyCug::OnSetup():
void MyCug::OnSetup(){
//*******Set the Rows and Columns
SetNumberCols(10);
SetNumberRows(10);
}
That's from the tutorial in the 7.2 version. I used UG extensively, and have no problems with VS2008. But I create all my grid myself, I don't use dialog templates.