|
Advanced Search |
|
|
|
||||||||||||||||

The automator tool may be used to automate a set of repetitive tasks based on key presses. The tasks themselves are configurable (in ksq files). The tool can also reference XML files for data to use with the key sequences.
I wrote this tool to enter bugs into a bug tracking tool. People would send me bug files to enter them into a tool that they could not access and I would use this to automatically enter the xml bug files into the tool. So if you see some code/variables specific to a bug entry tool, you know where it came from. :-)
Along with the demo are samples that u can try out. Open the .ksq file in some text editor and it has instructions at the top on how to run the sample.
For writing your own key sequences check the site: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformssendkeysclasstopic.asp
Additionally the following custom key sequences can be used
a) WAIT:n
Where n is the number of seconds that the application must pause before sending next keys.
Eg. WAIT:3 //to wait for 3 seconds
b) REPEAT: and REPEATEND:
To repeat the key sequences in between the specified number of times.
Eg. REPEAT:3
{ENTER}
REPEATEND: //to repeat the enter key 3 times
c)XML:
To access the specified element value in the current xml file.
Eg. XML:ELEMENT1 //will return the value "abcd" if the current xml contained <ROOT><ELEMENT1>abcd</ELEMENT1></ROOT>
d)//
Specifies a comment. Everything after a // anywhere is a comment.
See the sample files sample1.ksq and sample2.ksq to clarify the above commands.
I'll attempt to explain some relevant parts of the code here.
this.processWindowHandle = IntPtr.Zero;
Process[] plist = Process.GetProcesses();
foreach (Process p in plist)
{
if (!this.processWindowHandle.Equals(IntPtr.Zero))
{
break;
}
switch(this.titlePositionComboBox.SelectedItem.ToString().ToUpper())
{
case "BEGIN":
if (p.MainWindowTitle.StartsWith(this.targetAppTitleTextBox.Text))
{
this.processWindowHandle = p.MainWindowHandle;
}
break;
.
.
}
}
The program loops through the list of running processes and tries to match the title of the process given.
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd
);
[DllImport("User32.dll")]
private static extern bool SetActiveWindow(IntPtr hWnd
);
SetForegroundWindow(this.processWindowHandle);
SetActiveWindow(this.processWindowHandle);
There is no direct call in the .NET api to activate a window. Hence I reference the relevant win32 calls using the DllImport attribute and call the function with the process handle of the target application I found in step 1.
XPathNavigator nav;
try
{
XPathDocument xpDoc = new XPathDocument(xmlFileName);
nav = xpDoc.CreateNavigator();
}
catch(Exception ex)
{
bufFileItem.SubItems[1].Text = "Error! in xml document.";
continue;
}
ExecuteKeySequence(nav);
We create an XPathDocument of the xml file. This will allow us to use XPath search/select commands to find data easily.
struct RepeatInfo
{
public int repeatStartPos;
public int repeatCount;
public RepeatInfo(int repeatStartPos, int repeatCount)
{
this.repeatCount = repeatCount;
this.repeatStartPos = repeatStartPos;
}
}
While implementing the key sequence I had to extend the sequences to include control structures. One of the essentials was looping. The structure above represents a repeat loop. Whenever the code finds a REPEAT: in the key sequence, it adds a repeat info entry into a stack and repeats that part of the key sequence until REPEATEND: for the specified number of times. The above structure, RepeatInfo, stores the repeat information: start position of repeat and the number of times left to repeat respectively.
if (s.StartsWith("REPEAT:"))
{
int repeatCount = Convert.ToInt32(s.Replace("REPEAT:", "").Trim());
repeatStack.Push(new RepeatInfo(cmdIndex, repeatCount));
continue;
}
else if (s.StartsWith("REPEATEND:"))
{
if (repeatStack.Count >= 1)
{
RepeatInfo lastRepeatInfo = (RepeatInfo)repeatStack.Pop();
if (lastRepeatInfo.repeatCount > 1)
{
cmdIndex = lastRepeatInfo.repeatStartPos;
lastRepeatInfo.repeatCount--;
repeatStack.Push(lastRepeatInfo);
}
}
continue;
}
This function loops through the set of key sequences. It checks the type of key sequence - if it is a special key sequence like WAIT, REPEAT, REPEATEND, // or XML or whether they are keys to be entered on the target application. Depending on the type, the program extracts or assigns keys that are to be sent to the application.
while (cmdIndex+1 < this.sendKeysSequence.Length)
{
cmdIndex++;
string s = this.sendKeysSequence[cmdIndex];
string sendChars = "";
if (s.StartsWith("XML:"))
{
if (nav == null)
{
throw new Exception("Error. XML navigator was null. " +
"No file associated with XML: command "+ s);
}
string xmlName = s.Replace("XML:", "");
XPathNodeIterator iterator = nav.Select("//" + xmlName);
if (iterator.MoveNext())
{
sendChars = iterator.Current.Value;
foreach(string specialChar in this.specialCharsInSendKeys)
{
sendChars = sendChars.Replace(specialChar, "{"+specialChar+"}");
}
}
}
else if (s.StartsWith("WAIT:"))
{
int sleepTime = 5000;
sleepTime = Convert.ToInt32(s.Replace("WAIT:", ""))*1000;
Thread.Sleep(sleepTime);
continue;
}
} ...
Finally we send the keys to the application using the SendKeys method. Note that the target application needs to be active at this point.
SendKeys.SendWait(sendChars);
There are quite a few issues in the program. This program assumes ideal case - if there are unexpected dialogs (like error dialogs) or changes in UI, then this will not work. If another window becomes active while the program is running, the key sequences will be sent to that application; I can't quite decide if that is a feature or a bug.
The code was written to suit my needs and for the most part it was quickly thrown together. I added a few itty bitty features thereafter but they were mostly make up. So the core of the whole program itself could possibly be improved. Adding more control structures like IF-THEN, GOTO etc. would be cool too. Best of luck!
| You must Sign In to use this message board. | ||||||||
|
||||||||
|
||||||||
|
||||||||
|
||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 13 Jan 2004 Editor: Nishant Sivakumar |
Copyright 2004 by SathishVJ Everything else Copyright © CodeProject, 1999-2009 Web17 | Advertise on the Code Project |