Automation of Legacy Applications with the GDI Capture Plug-In

Posted by pgradnitzer on Thursday, September 16th, 2010 at 8:48 am to Best Practices,Improve Object Recognition

To set up test automation scripts, recognition of the UI objects under test is necessary. In some cases, Ranorex cannot access all the UI objects of the application under test (e.g. VB6, MFC, older Delphi versions). That’s why we developed the GDI Capture Plug-In (beta), which enables capturing and recognition of text elements drawn using GDI functions within the application under test.

These elements can then be used within the RanoreXPath as “RawText” and “RawTextBlock” capability. Both are added as children to existing Win32 windows or controls (NativeWindow capability). The RawText capability represents a single text line or string. The RawTextBlock combines the contents of all RawText strings into a single text block.

gdi-capture-plugin

Please note that the below procedure on how to set up the plugin only applies to Ranorex 2.X versions. For an explanation on how to set up the plugin for Ranorex 3.X, please read this section in the Ranorex User Guide.

Set up the GDI Capture Plug-In

  1. Please close all Ranorex tools
  2. Download and extract the GDI Capture Plug-in (zip) (works with Ranorex 2.3.4 and all higher 2.3.X versions; there is no need to install the plugin with Ranorex 3.X versions as 3.X already includes that plugin natively) to following location“C:\Documents and Settings\All Users\Application Data\Ranorex2\Plugins” (for Windows XP) or “C:\ProgramData\Ranorex2\Plugins” (for Vista, 7)”
  3. Now you have to configure the plug-in to enable capturing of the text for your application. Therefore, please open the “Ranorex.Plugin.RawTextPlugin.config” file and change following line in XML File
    <include type="process" name="notepad"/>

    to following (to check the process name of your application please use Spy or the Task Manager)

    <include type="process" name="YourApplicationProcessName"/>
  4. You can also use the process name of your application in the config file. Please use the
    <include type="class" name="MyCustomWndClass"/>

    statement in your XML-Config file. To get the class name of your element please use Spy and track your element. At the overview tab you will find the class name.

    You can also use RegEx in your config file to automate more than one classes. For example all classes which starts with “Afx”

    <include type="class" name="Afx.*"/>

    Whole XML-Config File:

    <!--
    Configuration for GDI Capture Plug-In
    -->
    <rawtextconfig>
    <!--
    Example for by process filtering <include type="process" name="calc"/>
    -->
    <!--
    Example for by class name filtering <include type="class" name="MyCustomWndClass"/>
    -->
    <include type="process" name="YourApplicationProcessName"/>
    </rawtextconfig>
  5. Start Ranorex Spy and check if the GDI Capture Plug-In was successfully loaded. Therefore, please open the About Dialog by clicking the Ranorex Logo and check if the RawText is loaded.
  6. gdiplugin_loaded

    GDI Capture Plug-In successfully loaded

  7. Start your application and Spy. Now you should be able to track the RawText/RawTextBlock of your elements. You also should recognize a short flicker of your application when you track an element. That’s the new GDI Capture Plug-In which forces your software to redraw.

On the screenshot below you can see the text elements of the menu bar of the application under test:
Spy with Plug-In

GDI Capture Plug-In Example Project

Create a new Project in Ranorex Studio and use the new GDI Capture Plug-In in code. After the project is created, please add a new reference to be able to access the Plug-In. Therefore right-click references and select the Ranorex.Plugin.RawText.dll from the Plug-In folder (the same folder as used above to install the Plug-In). If the DLL is successfully added, create two new methods called CreateNewDocument and CheckIfTextExists.
These two methods should look like following:

CreateNewDocument

private static void CreateNewDocument(Ranorex.Form form)
{
	//Searching for the menu "File" using the RawText capability
	RawText MenuFile = form.FindSingle(".//rawtext[@caption='File']");
	//Click the menu "File"
	MenuFile.Click();
	Report.Log(ReportLevel.Info, "Info", "File menu clicked");
	Delay.Ms(500);

	//Popup form for the menu items
	Ranorex.Form IdleForm = "/form[@title='']";
	//Now searching for the new Button to create a new document
	RawText MenuItemNew = IdleForm.FindSingle(".//rawtext[@caption='New']");
	//Click the menu entry to create a new document
	MenuItemNew.Click();
	Report.Log(ReportLevel.Info, "Info", "New menu item clicked");

	//Check if the new document was created succesfully
	Validate.Exists(form.FindSingle(".//rawtext[@caption='MFC_Test2']"));
}

CheckIfTextExists

private static void CheckIfTextExists(RawTextBlock TextBlock, string CheckString)
{
	Report.Log(ReportLevel.Info,"Text", "Check if the string exists in RawTextBlock");

	//If the CheckString value is available in TextBlock. Report will report succes.
	//If not available Report will report Error
	if(TextBlock.RawText.Contains(CheckString))
	{
		Report.Log(ReportLevel.Success,"Text", "Is available in RawTextBlock '" + TextBlock.RawText + "'");
	}
	else
	{
		Report.Log(ReportLevel.Error,"Text", "Is not available in RawTextBlock '" + TextBlock.RawText + "'");
	}
}

Please download the following MFC sample application SampleApplication.zip and place it in your project folder on your hard drive.

Add following code to your main method:
Main

STAThread]
public static int Main(string[] args)
{
    Keyboard.AbortKey = System.Windows.Forms.Keys.Pause;
    int error = 0;

    string logFileName = "Test.rxlog";

    Report.Setup(ReportLevel.Info, logFileName, true);

    try
    {
        //Start the MFC Application
        System.Diagnostics.Process.Start("..\\..\\MFC_Test.exe");

        //Wait for process
        Delay.Seconds(5);

        //Form of MFC Application
        Ranorex.Form form = "/form[@processname='MFC_Test']";

        //Bring form to foreground and activate it
        form.EnsureVisible();
        form.Activate();

        //Call the method to create a new document
        CreateNewDocument(form);

        //Call method to check if string exists in element
        CheckIfTextExists(form.FindSingle(@".//rawtextblock[@caption~'^This\ is\ a\ caption\ bar\ whe']"),
                          "presented");

        //Close the Application
        Ranorex.Button CloseButton = "/form[@processname='MFC_Test']/titlebar/button[@accessiblename='Close']";
        CloseButton.Click();
    }
    catch (Exception e)
    {
        Report.Error("Unexpected exception occured: " + e.ToString());
        error = -1;
    }

    Report.End();
    return error;
}

Last but not least you have to configure the GDI Capture Plug-In, to be able to access drawn text elements within the application under test. Therefore please take a look at “Step 3″ of “Set up the GDI Capture Plug-In” and add following line to your configuration file

<include type="process" name="MFC_Test"/>

If the above steps are finished, please compile your project and execute it. Ranorex should be able to automate the “Menu Bar” of the MFC Feature Pack Application.

Download the GDI Plug-In Example Solution (GDIPluginExample.zip)

Share

Tags: , , ,

11 comments

  1. Anfal

    This is really a wonderfull implementation
    Peter has done a great job in implementing this feature
    I am glad to be a customer of Ranorex

  2. Slavik

    Using Ranorex 2.3.5 Trial.
    I noticed warning “Found conflicts between different versions of the same dependent assembly. (MSB3247)” every time i compile project.
    Do you know what’s the meaning of it?

  3. Slavik

    Also, attached GDIPluginExample doesn’t work.

    Getting error:
    Unexpected exception occured: Ranorex.ElementNotFoundException: No element found for path ‘.//rawtext[@caption='File']‘ within 0ms.
    at Ranorex.Core.Element.FindSingle(RxPath path)
    at Ranorex.Adapter.FindSingle[T](RxPath path)
    at GDIPlugInExample.Program.CreateNewDocument(Form form) in c:\Users\capture1\Desktop\ExMFC\GDIPlugInExample\Program.cs:line 74
    at GDIPlugInExample.Program.Main(String[] args) in c:\Users\capture1\Desktop\ExMFC\GDIPlugInExample\Program.cs:line 49

    Tested on my Win7/32 with 2.3.4 and 2.3.5

    Ranorex Spy can’t see children of “Element 59358″ – only ToolBar ‘Menu Bar’, but not menu entris. Just like on top picture on the left. I verified, GDI Plugin is in the list of Plugins (in About dialog)

    However, this plugin partially work for my application.

  4. ahoisl

    Did you edit the config file (“Ranorex.Plugin.RawTextPlugin.config”) as described in this blog and add the process name of your application to the config?

    Regarding the Studio warning MSB3247: Did you add any references to your project? This should only happen if the added references themselves depend on different versions of the same DLL.

    Regards,
    Alex

  5. Slavik

    You are correct, example was not running because i did not edit config file. After i done it – it runs just fine.

    However, i still getting warning MSB3247 in my app and your example, as well. But since it’s just warning, i guess i can ignore it…

  6. Fursov

    Can you explain, how columns and rows works?
    How Plug-In decide if some text is new column or just space between words in one column?
    I tried to use …rawtext[@column='5' and @row='3'], but it doesn’t work reliable for me. I think i not really understand how it splits columns? (I never had problems with rows).

  7. twalter

    The plugin tries to find patterns in your text. So in a table the plugin tries to find elements with same x values to build columns and tries to find elements with the same y calue to build rows. This is a approximation to rebuild the table structure. It may not be 100% reliable but it’s the best approach of doing in our opinion.

    Regards,
    Tobias

  8. rrgrfrfrf

    thanks for posting this, I was looking for this info

  9. SanMan

    ranorex Spy error when adding elemts torepository (inc children)

    Problem signature:
    Problem Event Name: APPCRASH
    Application Name: Ranorex.Spy.exe
    Application Version: 2.3.5.10317
    Application Timestamp: 4ce28c51
    Fault Module Name: KERNELBASE.dll
    Fault Module Version: 6.1.7600.16385
    Fault Module Timestamp: 4a5bdaae
    Exception Code: e053534f
    Exception Offset: 00009617
    OS Version: 6.1.7600.2.0.0.256.1
    Locale ID: 1035

  10. pgradnitzer

    Hi,

    Please update to the latest version of Ranorex. We fixed some bugs with 2.3.9 which affect the GDI Plug-In.

    Regards,
    Peter
    Ranorex Team

  11. SanMan

    Same result with latest version:

    Description:
    Stopped working

    Problem signature:
    Problem Event Name: APPCRASH
    Application Name: Ranorex.Spy.exe
    Application Version: 2.3.9.11654
    Application Timestamp: 4d6e0367
    Fault Module Name: KERNELBASE.dll
    Fault Module Version: 6.1.7600.16385
    Fault Module Timestamp: 4a5bdaae
    Exception Code: e053534f
    Exception Offset: 00009617
    OS Version: 6.1.7600.2.0.0.256.1
    Locale ID: 1035

    Read our privacy statement online:
    http://go.microsoft.com/fwlink/?linkid=104288&clcid=0×0409

    If the online privacy statement is not available, please read our privacy statement offline:
    C:\Windows\system32\en-US\erofflps.txt

    When this element in Spy is right clicked, this error occures:
    Class AfxFrameOrView42su

Leave a Reply