Ranorex C# automation for MFC Windows GUI
The following code supposes you have Ranorex linked to your C# solution.
Main.script
rem call main
kill
start
type @login.password schilling
click @login.ok
click title=Schilling;text=Firmavalg
click title=Schilling;innertext=SPS.UK$,href=4$
doubleClick title=Schilling;text=Main.menu
doubleClick title=Schilling;text=Publisher
doubleClick title=Schilling;text=Product.management
REM Step 1
click title=Schilling;*=Product.management.project
rem ocr_click Project 3 0.5
type /form[@title~'^Product\smanagement\s-\sedit']/?/?/container[@caption~'^Product\smanagement\s-\sedit']/element/element[6]/text[@class='Edit'] 21321131231
REM Step 3
click *=Product.management;text=Create.project$
REM Step 4
click *=Product.management;*=Create.project;*=Other.projects..F7.
REM 5
click *=Product.management;text=Get.serial.number
REM 6
click *=Product.management;text=Accept$
rem ocr_click @Name: 0.5 0.5
REM 10
rem type *=Product.management;*=Save.project.as CrashCourseCardiology\t\t\t\t\t\t\t\tCrash
type @pm.edit.saveas.new-project-number {ts}
type @pm.edit.saveas.name "Crash Course Cardiology"
type @pm.edit.saveas.title "Crash Course Cardiology"
rem click on title
type @pm.edit.saveas.main-group 07
type @pm.edit.saveas.sub-group 021
type @pm.edit.saveas.dimension-1 002
click @pm.edit.saveas.new-project-number
click @pm.edit.saveas.name
click @pm.edit.saveas.new-project-number
click @pm.edit.saveas.name
click "*=Product.management;text=Create project$"
rem click "/form[@title='Error']/button[@text='OK']"
rem click "*=Product.management;text=Create project$"
click "/form[@title='Question']/button[@text='&Yes']"
click @pm.edit.details.tab
wait 1000
clickAt @pm.edit.details.stackholders 100 20
clickAt @pm.edit.details.stackholders 10 20
clickAt @pm.edit.details.stackholders 100 20
wait 1000
type "/form[@title~'^Product\ management\ -\ edit']/?/?/container[@caption~'^Product\ management\ -\ edit']/?/?/container[@caption='Details']/?/?/container[@caption='Stakeholders']/?/?/element[@class='OaseGrid']/element/element[4]/text[@class='Edit']" "R"
wait 1000
clickAt @pm.edit.details.stackholders 200 20
wait 200
clickAt @pm.edit.details.stackholders 200 20
type "/form[@title~'^Product\ management\ -\ edit']/?/?/container[@caption~'^Product\ management\ -\ edit']/?/?/container[@caption='Details']/?/?/container[@caption='Stakeholders']/?/?/element[@class='OaseGrid']/element/element[31]/text[@class='Edit']" "Aut"
rem wait 1000
rem clickAt @pm.edit.details.stackholders 300 20
rem clickAt @pm.edit.details.stackholders 10 20
rem clickAt @pm.edit.details.stackholders 300 20
rem type "/form[@title~'^Product\ management\ -\ edit']/?/?/container[@caption~'^Product\ management\ -\ edit']/?/?/container[@caption='Details']/?/?/container[@caption='Stakeholders']/?/?/element[@class='OaseGrid']/element/element[4]/text[@class='Edit']" "Author "
wait 1000
clickAt @pm.edit.details.stackholders 700 20
wait 200
clickAt @pm.edit.details.stackholders 700 20
type "/form[@title~'^Product\ management\ -\ edit']/?/?/container[@caption~'^Product\ management\ -\ edit']/?/?/container[@caption='Details']/?/?/container[@caption='Stakeholders']/?/?/element[@class='OaseGrid']/element/element[22]/text[@class='Edit']" "p2012-009"
rem Aut Author p2012-009
click @pm.edit.texts.tab
click @pm.edit.calculation.tab
type @pm.edit.calculation.version 3
type @pm.edit.calculation.price 9
click @pm.edit.calculation.version
click @pm.edit.calculation.price
click *=Product.management;text=Accept$
Repository.properties
login.password=title=Schilling;class=Edit
login.ok=title=Schilling;*=OK
pm.edit=/form[@title~'^Product\ management\ -\ edit']/?/?/container[@caption~'^Product\ management\ -\ edit']/
pm.edit.saveas=?/?/container[@caption='Save project as']/?/?/container[@caption='Master data']/
pm.edit.saveas.new-project-number=?/?/element[@instance='1']
pm.edit.saveas.name=?/?/element[@instance='2']/text[@class='Edit']
pm.edit.saveas.title=?/?/container[@caption='More information']/element/element[2]/text[@class='Edit']
pm.edit.saveas.main-group=?/?/container[@caption='More information']/?/?/element[@instance='5']/text[@class='Edit']
pm.edit.saveas.sub-group=?/?/container[@caption='More information']/?/?/element[@instance='6']/text[@class='Edit']
pm.edit.saveas.dimension-1=?/?/container[@caption='More information']/?/?/element[@instance='19']/text[@class='Edit']
pm.edit.details.tab=?/?/tabpagelist[@class='SysTabControl32']/tabpage[@title='Details']
pm.edit.details.stackholders=?/?/container[@caption='Details']/?/?/container[@caption='Stakeholders']/?/?/element[@class='OaseGrid']/element[@class='SchGridView']
pm.edit.texts.tab=?/?/tabpagelist[@class='SysTabControl32']/tabpage[@title='Texts']
pm.edit.calculation=
pm.edit.calculation.tab=?/?/tabpagelist[@class='SysTabControl32']/tabpage[@title='Calculation']
pm.edit.calculation.version=?/?/container[@caption='Calculation']/?/?/container[@caption='Calculation overview']/?/?/element[@instance='3']/text[@class='Edit']
pm.edit.calculation.price=?/?/container[@caption='Calculation']/?/?/container[@caption='Editorial']/?/?/container[@caption='Sales']/element/element[6]/text[@class='Edit']
Program.cs
using System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ranorex.Core;
using System.Drawing;
using Ranorex;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
[STAThread]
static void Main(string[] args)
{
for (; ; )
{
Console.ForegroundColor = ConsoleColor.White;
Console.Write(">>");
Console.ForegroundColor = ConsoleColor.Gray;
string line = Console.ReadLine();
line = line.Split('#')[0];
Console.ForegroundColor = ConsoleColor.Yellow;
if (line == null) continue;
if (line.Length == 0) continue;
if (line == "quit") return;
try
{
eval(line);
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("ERROR: " + e);
}
}
}
public static void HELP()
{
foreach (var method in typeof(Program).GetMethods())
{
if (!method.IsStatic) continue;
if (method.Name != method.Name.ToUpper())
continue;
Console.WriteLine(method);
}
}
public static void START()
{
System.Diagnostics.Process.Start(@"Client.exe");
}
public static void KILL()
{
System.Diagnostics.Process.Start("taskkill.exe", "/im Client.exe /t /f").WaitForExit();
}
public static void SHOW(string path)
{
var result = findAll(path);
Console.WriteLine("COUNT: " + result.Count());
foreach (var item in result)
{
Element element = item;
Console.WriteLine("------------------");
foreach (var k in element.Attributes)
Console.WriteLine("\t" + k.Name + ": " + element.GetAttributeValueText(k.Name));
}
Console.WriteLine("=========================");
}
public static void RUN(string script)
{
ts = System.DateTime.Now;
CALL(script);
}
public static void CALL(string script)
{
var line = 1;
foreach (var callLine in System.IO.File.ReadAllLines(@"c:\users\Administrator\Desktop\schilling\\" + script + ".script"))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(script + ":" + line + " ");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(callLine);
Console.ForegroundColor = ConsoleColor.Yellow;
eval(callLine);
line++;
}
}
public static void CLICKAT(string selector, string x, string y)
{
Location location = new Location(new Point(int.Parse(x),int.Parse(y)));
findUnique(selector).Click(location,Duration.Zero);
}
public static void CLICK(string selector)
{
findUnique(selector).Click(Duration.Zero);
}
public static void DOUBLECLICK(string selector)
{
findUnique(selector).DoubleClick(Duration.Zero);
}
public static void TYPE(string selector, string text)
{
text = text.Replace("\\t", "\t");
text = text.Replace("\\n", "\n");
text = text.Replace("\\r", "\r");
findUnique(selector).PressKeys(text);
}
public static void WAIT(string selector)
{
if (new Regex("\\d+").IsMatch(selector))
System.Threading.Thread.Sleep(Int32.Parse(selector));
else
findUnique(selector);
}
static System.DateTime ts = System.DateTime.Now;
public static void eval(string line)
{
if (line.Trim().Length == 0) return;
if (line.ToUpper().StartsWith("REM")) return;
line = line.Replace("{now}", string.Format("{0:yyMMddHHmmss}", System.DateTime.Now));
line = line.Replace("{ts}", string.Format("{0:yyMMddHHmmss}", ts));
var tokens = new List<string>();
foreach (var token in new Regex("(?<match>[^\\s\"]+)|(?<match>\"[^\"]*\")").Split(line))
if (token.Trim().Length > 0)
{
if (token.StartsWith("\""))
tokens.Add(token.Substring(1, token.Length - 2));
else tokens.Add(token);
}
Type myType = typeof(Program);
var method = myType.GetMethod(tokens[0].ToUpper());
if (method != null)
{
var parameters = new List<String>(tokens);
parameters.RemoveAt(0);
method.Invoke(null, parameters.ToArray<String>());
return;
}
throw new Exception("Command " + tokens[0] + " not defined.");
}
public static Unknown findUnique(string path)
{
var started = System.DateTime.Now;
for (; ; )
{
var result = findAll(path);
if (result.Count() == 1)
{
Console.WriteLine();
return result[0];
}
System.Threading.Thread.Sleep(250);
Console.Write("*");
if ((System.DateTime.Now - started).TotalSeconds > 15)
{
Console.WriteLine();
if (result.Count() == 0)
throw new Exception("Cannot find " + path);
if (result.Count() > 1)
throw new Exception("Found " + result.Count() + " for " + path);
}
}
}
public static List<Unknown> findAll(string path)
{
if(path[0]=='@')
return findAll(Repository.get(path.Substring(1)));
if (path[0] == '/')
{
List<Unknown> result = new List<Unknown>();
foreach (Element element in Host.Local.Element.Find(new RxPath(path)))
result.Add(element);
return result;
}
List<Unknown> currentNodes = new List<Unknown>() { Host.Local.Element };
foreach (string kv in path.Split(';'))
{
var nextLevel = new List<Unknown>();
if (kv == "..")
{
foreach (var currentNode in currentNodes)
nextLevel.Add(currentNode.Element.Parent);
}
else
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (string kvs in kv.Split(','))
{
var kvsp = kvs.Split('=');
var key = kvsp[0];
if (key == "") key = "*";
var value = kvsp[kvsp.Length - 1];
dictionary[key] = value;
}
foreach (var currentNode in currentNodes)
foreach (var nextLevelNode in findAll(currentNode, dictionary))
nextLevel.Add(nextLevelNode);
}
currentNodes = nextLevel;
}
return currentNodes;
}
public static List<Unknown> selectAll(List<Unknown> from, Dictionary<string, string> criterion)
{
var result = new List<Unknown>();
foreach (Unknown item in from)
if (matches(item, criterion))
result.Add(item);
return result;
}
public static List<Unknown> findAll(Element root, Dictionary<string, string> like)
{
var started = System.DateTime.Now;
List<Unknown> queue = new List<Unknown>();
foreach (var child in root.Children)
queue.Add(child);
for (; ; )
{
if (queue.Count() == 0) return queue;
if (selectAll(queue, like).Count() > 0) return selectAll(queue, like);
var newList = new List<Unknown>();
foreach (var item in queue)
{
foreach (var child in item.Children)
newList.Add(child);
if ((System.DateTime.Now - started).TotalSeconds > 5) return new List<Unknown>();
}
queue = newList;
}
}
public static bool matches(Unknown Elem, Dictionary<string, string> Like)
{
var description = new Dictionary<string, string>() { { "*", "" } };
foreach (var attribute in Elem.Element.Attributes)
{
var Value = Elem.Element.GetAttributeValueText(attribute.Name);
description[attribute.Name] = Value;
description["*"] += Value + " ";
}
foreach (var Entry in Like)
{
if (!description.ContainsKey(Entry.Key)) return false;
var Value = description[Entry.Key];
if (Value == null) return false;
if (!new Regex(Entry.Value).IsMatch(Value))
return false;
}
return true;
}
}
}