Instigator – Application Launcher

Saturday, September 26, 2009 3:22:12 AM (GMT Daylight Time, UTC+01:00)

I am pretty dependent on Enso for helping me navigate not only my file system, but links related to doing everyday tasks in my job (Bug Tracking, Time Reporting, Requirements, Design Documents, coding… and the list goes on). I recently received a new laptop(with all of the AD policies you could want)… and the build doesn’t seem to want to allow me to run Enso, so I wrote a replacement for it. Basically it is another launcher application.

What I don’t like about some of the other launcher applications is that you have do 2 or 3 steps before you can launch your application (plus their UI is out-dated). Windows 7 has some search capabilities similar to Vista ( but  better) in that you can use the Windows key to drop down the Start menu and begin typing for the application or file that you are looking for.  This works well… but I don’t like the fact that the list is indiscriment… in other words I didn’t ask for everything to be included in the search… I just wanted targeted thing I use all of the time. 

With Enso, launching applications was much easier… a matter of holding down the caps lock while you typed a key word… a little weird but it worked.  It pulled program files and short-cuts to websites and most importantly application or file short-cuts that you added.  It wasn’t a laundry list like we get in Windows.

I call my replacement for Enso… Instigator.  It uses shortcuts stored in folders you identify to launch your applications. It is a single portable executable that requires the 3.5 .NET Framework.  The UI is shown below:

clip_image001

Configuring Instigator

  1. Download the application zip:
  2. Copy the contents to where you would like.
  3. Edit the config file so Instigator knows where to find your short-cuts.  An example config file is shown below. Add a DiscoveryPath to the config of where you would like Instigator to look for short-cuts. Remove any DiscoveryPaths that you do not want Instigator to load.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name ="InstigatorSettings"
             type ="Sysknowlogy.Tool.OS.XmlSerializerSectionHandler, Sysknowlogy.Instigator"/>
  </configSections>
 
  <InstigatorSettings type ="Sysknowlogy.Tool.OS.InstigatorSettings , Sysknowlogy.Instigator">
    <DiscoveryPaths>
      <DiscoveryPath location=".\shortcuts\" />
      <DiscoveryPath location="C:\Documents and Settings\sbraun\Desktop\OpenCommands" />
    </DiscoveryPaths>
  </InstigatorSettings>
</configuration>

Using Instigator

  1. Start the executable, after the splash screen disappears the application is loaded.
  2. Use Ctl-Win to bring up the search window. Right now this is not configurable, it will be in later releases.
  3. This should bring up the application with the list of short-cuts that you defined in your discovery paths.
  4. Begin typing to limit the list of items to launch.  The search uses a contains to filter… as you type it will eliminate your options.
  5. Once the items fore color you are looking for is highlighted, hit enter.

Known Issues

  • Focus set to the filter textbox sometimes gets botched up… typically when Visual Studio is open. VS likes to steal focus a lot. This doesn’t happen a great deal, but does occasionally. To fix it, you will need to click in the filtering textbox with your mouse.
  • If the application process cannot be started, Instigator does not notify you that if failed to launch the application.  It just won’t do anything.

Reporting errors / problems
While in the launch filter textbox, type in “report” which will result in a “report a problem or bug” in the drop down.  Select that item and hit enter.  This will launch the default mail client and allow you to mail be a bug.

Getting Started - Automation of WPF UI

Wednesday, September 23, 2009 3:21:43 AM (GMT Daylight Time, UTC+01:00)

So you ask your self… “Where do I start”… I have been tasked with finding out how we can automate our WPF application for testing or just to drive development unit testing quicker.  You have done some searches and stumbled upon this blog, but you have so many questions.

How does it work from a high level…
The core concept is that we should be able to automate our application via a single API across different platforms (Winforms, WPF, ASP.NET).  Microsoft has spent a great deal of time defining UI interaction patterns, so these can be abstracted out in a API that will allow us to drive the UI from code.  This abstracted API is defined in patterns.  There is a list of the patterns found for accessing controls:

http://msdn.microsoft.com/en-us/library/ms750574.aspx

and here is how to use the patterns to access properties on the element:

http://msdn.microsoft.com/en-us/library/ms752056.aspx

How do I drive the UI from a API standpoint…
First you create some sort of driver application… like a console application. This application then uses code like this to create the process:

Process p = null;
p = Process.Start(@"C:\temp\UI.Shell.exe");

Once you have the process created you can pass the MainWindowHandle property of the process class to the Automation API.  Another approach is to pass in the string found in the titlebar of the application and allow the automation API to search for the window.  From there you use a variety of identifiers to reference the different controls.  One approach is to use the AutomationID, which maps to the xaml controls x:name property.  You can also use the ClassName to identify controls, which then maps to the .NET type of the control.  If you are not sure of a controls AutomationID or ClassName you can use UISpy.exe (comes with the Windows SDK) to find out how you can reference the control.

Here is a code sample to give you an idea of how this all comes together.  The following sample starts a WPF application and then completes a login view and triggers the login from a button.

Console.WriteLine("\nBegin WPF UIAutomation test run\n");
                Console.WriteLine("Launching the application");
                Process p = null;
                p = Process.Start(@"C:\temp\bin\wpfApplication.exe");
 
                int ct = 0;
                do
                {
                    Console.WriteLine("Looking for application process. . . ");
                    ++ct;
                    Thread.Sleep(10);
                }
                while (p == null && ct < 50);
 
                if (p == null)
                    throw new Exception("Failed to find application process");
                else
                    Console.WriteLine("Found application process");
 
                Console.WriteLine("\nGetting Desktop");
                AutomationElement aeDesktop = null;
                aeDesktop = AutomationElement.RootElement;
                if (aeDesktop == null)
                    throw new Exception("Unable to get Desktop");
                else
                    Console.WriteLine("Found Desktop\n");
 
 
                Console.WriteLine("\nLooking for application main window. . . ");
                Thread.Sleep(5000);
                AutomationElement application = AutomationElement.FromHandle(p.MainWindowHandle);
               
                Console.WriteLine("\nCompleting controls. . . ");
                AutomationElement loginView = application.FindFirst(TreeScope.Children,
                     new PropertyCondition(AutomationElement.ClassNameProperty,
                     "LoginView"));
 
                AutomationElement loginPart = loginView.FindFirst(TreeScope.Children,
                    new PropertyCondition(AutomationElement.ClassNameProperty,
                    "LoginPart"));
 
                AutomationElement txtUserName = loginPart.FindFirst(TreeScope.Children,
                    new PropertyCondition(AutomationElement.AutomationIdProperty, 
                    "username"));
                AutomationElement txtPassword = loginPart.FindFirst(TreeScope.Children,
                   new PropertyCondition(AutomationElement.AutomationIdProperty,
                   "password"));
 
                Console.WriteLine("\nSetting input to a030601");
                ValuePattern vptxtUserName = (ValuePattern)txtUserName.GetCurrentPattern(ValuePattern.Pattern);
                vptxtUserName.SetValue("testuser");
                ValuePattern vptxtPassword = (ValuePattern)txtPassword.GetCurrentPattern(ValuePattern.Pattern);
                vptxtPassword.SetValue("p@ssword1");
 
 
                AutomationElement cmdLogin = loginPart.FindFirst(TreeScope.Children,
                   new PropertyCondition(AutomationElement.AutomationIdProperty, "authenticationButton"));
 
                Console.WriteLine("\nClicking on Compute button");
                InvokePattern ipLoginCmd =
                  (InvokePattern)cmdLogin.GetCurrentPattern(
                  InvokePattern.Pattern);
                ipLoginCmd.Invoke();

Are there any good examples that show me how to drive the UI…
There are a number of articles that I found… but the most simplistic and straight forward is an article that was published in MSDN magazine back in March of 2009. Automating UI Tests in WPF Applications

Some more interesting information about WPF and automation for improving the quality of your application can be found in the WPF Application Quality Guide.