Tutorial: Advanced Application Scripting

In our previous guide we built a simple script for wordpad. But a seasoned IT pro as yourself might like a bigger challenge and more usable examples. In this guide we will go deeper in to application scripting. We will expand the existing WordPad script we made before and add more actions (the example script can be downloaded from this page below). We are going to use the following functions:

  • Adding more Variables in a single application
  • If Else statements
  • Timers that measure the time taken of an action

We are going to do the following assignments

  1. Saving a file that might already exist
  2. Open an existing file (and what if it does not exist)
  3. Printing to PDF
  4. Adding Timers

Assignment 1. Saving a file that might already exist

When we created the first application script in the previous chapter we saved a file. This script always works if there is no file that already exists with the same name. If there is a file with the same name the script will stop working correctly and will not save the file. And might even get stuck and ruin the Login Enterprise measurements. To mitigate this risk we need to add an If statement. So if we run the script and the file does not exist it will run correctly but if the file does exist it will deal with it as well. 

Commands used:

  • Var
  • If
  • FindWindow
  • Click
  • ContinueOnError
  • Timeout

Once you are done it should look like this:

Hints:

What is important here that when you create the variable in the code you need to pay attention to the timeout or error response. By default the FindWindow waits 30 seconds to find a window. But in this case we dont want to wait that long so we can do a very quick ContinueOnError:true or a TimeOut:5 to wait 5 seconds. 

The If statement can be done by simply verifying if a window exists or not. 

The code looks something like this:

var ConfirmSaveDialog=FindWindow(className : "Win32 Window:#32770", title : "Confirm Save As", processName : "wordpad", timeout:1, continueOnError:true);

if (ConfirmSaveDialog!=null){

ConfirmSaveDialog.FindControl(className : "Button:CCPushButton", title : "&Yes").Click();

}

Assignment 2. Open an existing file (and what if it does not exist)

This assignment is split in to two parts. The first part is to open a file that exists. We will open the "Open File" window, select a file and open it. The commands used are:

  • Var
  • FindWindow
  • TypeToControl
  • Click

Once done the result should look something like this:

Hints:

Of course we need to open the "open" dialog, this can be via button or keyboard command. A variable is needed to define the newly opened window so we do not focus on the main window when we do an action. We can either select the file or type the location / file name. And the opening of the file can be done by clicking and keyboard commands. Last but not least make sure to verify the file is open.

The code should look something like this:

MainWindow.FindControl(className : "Document:RICHEDIT50W", title : "Rich Text Window").Type("{ctrl+o}");

var OpenFileDialog=FindWindow(className : "Win32 Window:#32770", title : "Open", processName : "wordpad", timeout:1, continueOnError:true);

OpenFileDialog.FindControl(className : "Edit:Edit", title : "File name:").Type("Existing File.rtf");

OpenFileDialog.FindControl(className : "Button:Button", title : "&Open").Click();

FindWindow(className : "Win32 Window:WordPadClass", title : "Existing File.rtf - WordPad", processName : "wordpad");
Assignment 2.1. Opening a file that does not exist
The second part of assignment 2 is the answer to the question; "What if the file, that i want to open, does not exist?". So what we need to check is if the file that we want to open exists there are multiple ways to do this but you will need an If - Else statement, and dont forget the timeout. The commands used:
  • If
  • Else
  • FindWindow
  • Var
  • Click
  • ContinueOnError
  • Timeout

The result should look something like this:

Hints:

The FindWindow action must focus on the error message that appears and not other windows. You might want to focus on if the file exists by verifying the document name, but that is not possible right now. For the If/Else statement you can check previous made statements. 

The code should look something like this:

var ErrorDialog=OpenFileDialog.FindControl(className : "Win32 Window:#32770", title : "Open", timeout:1, continueOnError:true);

if (ErrorDialog!=null)

{

ErrorDialog.FindControl(className : "Button:CCPushButton", title : "OK").Click();

OpenFileDialog.FindControl(className : "Button:Button", title : "Cancel").Click();

}

else

{

FindWindow(className : "Win32 Window:WordPadClass", title : "Existing File.rtf - WordPad", processName : "wordpad");

}

FindWindow(className : "Win32 Window:WordPadClass", title : "*WordPad", processName : "wordpad");

Assignment 3. Printing to a PDF file 

The next assignment is adding a printing action to the application. I.e. saving file to pdf using the print to pdf action built-in to wordpad. We are going to use all previous skills to make sure that what ever happens the script will not crash. This means putting a fail safe at critical locations. These are the used commands: 

  • If
  • Else
  • FindWindow
  • Var
  • Click
  • ContinueOnError
  • Timeout

The result should look something like this:

Hints:

Make sure that you check every aspect where the application can fail. And make sure you set the correct timeout and continueOnErrors at the right locations. Use variables where necessary and verify that it is robust enough to sustain unexpected behavior. 

The code should look something like this:

MainWindow.FindControl(className : "Document:RICHEDIT50W", title : "Rich Text Window").Type("{ctrl+P}");

varPrintDialog=FindWindow(className : "Win32 Window:#32770", title : "Print", processName : "wordpad", timeout:1, continueOnError:true);

if (PrintDialog!=null){

varPrinterExists=PrintDialog.FindControl(className : "ListItem", title : "Microsoft Print to PDF", timeout:1, continueOnError:true);

if (PrinterExists!=null)

{

PrintDialog.FindControl(className : "ListItem", title : "Microsoft Print to PDF").Click();

PrintDialog.FindControl(className : "Button:Button", title : "&Print").Click();

varSavePrintAs=FindWindow(className : "Win32 Window:#32770", title : "Save Print Output As", processName : "wordpad", timeout:1, continueOnError:true);

if (SavePrintAs!=null)

{

SavePrintAs.FindControl(className : "Edit:Edit", title : "File name:").Type("My First PDF.pdf");

SavePrintAs.FindControl(className : "Button:Button", title : "&Save").Click();

varConfirmSavePDF=FindWindow(className : "Win32 Window:#32770", title : "Confirm Save As", processName : "wordpad", timeout:1, continueOnError:true);

if (ConfirmSavePDF!=null)

{

ConfirmSavePDF.FindControl(className : "Button:CCPushButton", title : "&Yes").Click();

}

}

}

else

{

PrintDialog.Close();

}

}

FindWindow(className : "Win32 Window:WordPadClass", title : "Existing File.rtf - WordPad", processName : "wordpad").Focus();

Assignment 4. Adding Timers

This assignment is the easiest of them all, placing the timers. But this is the most crucial of the actions. Timers need to be placed at correct locations in order to get valid and correct data. There are three timer commands, you can find more about this here. 

What is shown below is an example of Timer Placements and the results within the Login Enterprise dashboard.

StartTimer(name:"Print_Sequence");
StartTimer(name:"Print_Window");

MainWindow.FindControl(className : "Document:RICHEDIT50W", title : "Rich Text Window").Type("{ctrl+P}");
var PrintDialog=FindWindow(className : "Win32 Window:#32770", title : "Print", processName : "wordpad", timeout:1, continueOnError:true);

if (PrintDialog!=null){

StopTimer(name:"Print_Window");
var PrinterExists=PrintDialog.FindControl(className : "ListItem", title : "Microsoft Print to PDF", timeout:1, continueOnError:true);

if (PrinterExists!=null){

PrintDialog.FindControl(className : "ListItem", title : "Microsoft Print to PDF").Click();
StartTimer(name:"Save_Print_Output_Window");
PrintDialog.FindControl(className : "Button:Button", title : "&Print").Click();
var SavePrintAs=FindWindow(className : "Win32 Window:#32770", title : "Save Print Output As", processName : "wordpad", timeout:3, continueOnError:true);

if (SavePrintAs!=null){

StopTimer(name:"Save_Print_Output_Window");
SavePrintAs.FindControl(className : "Edit:Edit", title : "File name:").Type("My First PDF.pdf");
SavePrintAs.FindControl(className : "Button:Button", title : "&Save").Click();
var ConfirmSavePDF=FindWindow(className : "Win32 Window:#32770", title : "Confirm Save As", processName : "wordpad", timeout:1, continueOnError:true);

if (ConfirmSavePDF!=null){

ConfirmSavePDF.FindControl(className : "Button:CCPushButton", title : "&Yes").Click();
}
}

else{

PrintDialog.Close();
CancelTimer(name:"Save_Print_Output_Window");
}
}

else{

PrintDialog.Close();
CancelTimer(name:"Print_Sequence");
CancelTimer(name:"Print_Window");

}
}

StopTimer(name:"Print_Sequence");

FindWindow(className : "Win32 Window:WordPadClass", title : "Existing File*", processName : "wordpad").Focus();

As you can see the CancelTimer function is used in the Else statement so if something fails we do not end up with extreme results. The results in the dashboard can be viewed below:

I have set thresholds to visualize the any out-of-ordinary behavior. 

Note: When i uploaded the application script i did need to make some changes to the script as it did not work out of the box. This is because i created the script on a different machine, my own machine, and the target machine used in Login Enterprise is completely different these are the changes i needed to do:

- Add the "existing file.rtf" to the users
- Set the Microsoft PDF printer as default printer in the user profiles
- Focus on "Existing file.rtf - WordPad" changed to "Existing file*" as the .rtf was not visible in the target environment.