This is the continuation of

Automate PowerDesigner Using Microsoft Powershell Script — Part One

In this article we discuss how to automate Powerdesigner GUI using Microsoft UI Automation.

I am on Windows 7 64bit environment. PowerDesigner is on 16.5.5 64bit.

Preparation


First of all, we need obtain UI Automation assemblies and several tools.

In case you have not installed Microsoft Windows SDK for Windows 7 and .NET Framework 4 or 4.5, click the link:

Download Microsoft Windows SDK for Windows 7 and .NET Framework 4 from Official Microsoft Download Center

Once you install the SDK, go to Start->All Programs->Microsoft SDK v7.0->Tools.  We’ll use

     Microsoft Inspect Tool

to get GUI automation information. In addition, we’ll use the following assemblies:

    UIAutomationClient.dll

    UIAutomationTypes.dll

    WindowsBase.dll


The files can be found at

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework.

I use .Net Framework 4.5 for my testing.

Secondly, we’ll use Windows PowerShell ISE as primary editor.

To start the editor, click Start button. In Search programs and files, type

Windows PowerShell ISE and hit Return.

Note: I only test  my code on 64bit PowerShell ISE.

Finally, let’s get familiar with several UI Automation components.

System.Windows.Automation                                     Contains all automation APIs and definitions

System.Windows.Automation.AutomationElement    Defines a window object.

System.Windows.Automation.ControlType                Defines an control object type. Example: Window, Button, Pane.

System.Windows.Automation.PropertyCondition       Stores condition you want to apply to an object.

System.Windows.Automation.AndCondition              You have two conditions and you want both them to be true.

System.Windows.Automation.OrCondition                You have two conditions and you want one of them to be true.

System.Windows.Automation.TreeScope                  Use this structure to define how to find an object.

Get hand-on experience


Start PowerShell ISE. Click File->New to open a new file.

Copy and paste the following code and click Run

  add-type -path “C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\UIAutomationClient.dll”

  add-type -path “C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\UIAutomationTypes.dll”

  $PowerDesigner = new-object -com powerdesigner.application

  Start-Sleep -Seconds 4

  # The following code searches for window with title PowerDesigner

  $title=’PowerDesigner’

  # Declare control type as window

  $type=[System.Windows.Automation.ControlType]::Window

  # In order to use control type Window, we need set control type property

  $controlProperty=[System.Windows.Automation.AutomationElement]::ControlTypeProperty

  # To find name PowerDesigner, we need set name property

  $nameProperty  =[System.Windows.Automation.AutomationElement]::NameProperty

  # Create condition with window as search object

  $typeCondition = new-object System.Windows.Automation.PropertyCondition $controlProperty, $type

  # Create another condition with name( PowerDesigner) as search object

  $nameCondition = new-object System.Windows.Automation.PropertyCondition  $nameProperty, $title

  # Create AndConditon. Make both namecodition and typecodition to be true

  $andCondition  = new-object System.Windows.Automation.AndCondition $typeCondition, $nameCondition

  # Define how to search specified object. You can use Descendants, Children, Subtree

  $descendants = [System.Windows.Automation.TreeScope]::Descendants


  # In UI Automation, Window is root object. Must use root element to find window object

  # The code below means find the first object which is a window and its name is PowerDesigner

  $handle=[System.Windows.Automation.AutomationElement]::RootElement.FindFirst($descendants, $andCondition)

  # The code below is very similar to above. It define two properties. One for menu and another for menu name File

  # Then use $handle above to find the correct object.
  $title=’File’

  $type=[System.Windows.Automation.ControlType]::MenuItem

  $controlProperty=[System.Windows.Automation.AutomationElement]::ControlTypeProperty

  $nameProperty  =[System.Windows.Automation.AutomationElement]::NameProperty

  $typeCondition = new-object System.Windows.Automation.PropertyCondition $controlProperty, $type

  $nameCondition = new-object System.Windows.Automation.PropertyCondition  $nameProperty, $title

  $andCondition  = new-object System.Windows.Automation.AndCondition $typeCondition, $nameCondition

  $descendants = [System.Windows.Automation.TreeScope]::Descendants

 

  # Important.

  # Use window handle we got from above to find menu

  $menu=$handle.FindFirst($descendants, $andCondition)

  $pattern=[System.Windows.Automation.ExpandCollapsePattern]::Pattern

  # Click menu with name File
  $menu=$menu.GetCurrentPattern($pattern)
  $menu.Expand()

The code starts PowerDesigner and mimics mouse click on menu File.

Look at the code carefully,  it consists of two blocks,  each one starting from $title=… until $descendants=…

The blocks show how UI Automation deals with a specific GUI object.

For those who are not familiar with PowerShell Script, I’ll demonstrate how to embed C# or Visual Basic code

into PowerShell Script. In fact, most developers adopt this approach.

Run C# or Visual Basic in PowerShell ISE


PowerShell can run C# or Visual Basic code on the fly. The following is an example in C#

  $source= @’
  using System;
  using System.IO;

  namespace PD
  {

    public static class Epoch
    {
      public static void HelloWorld()
      {
          Console.WriteLine(“Hello World”);
      }
    }
  }

‘@
  Add-Type -TypeDefinition $source -Language ‘CSharp’

  [PD.Epoch]::HelloWorld()

This is the equivalent code in Visual Basic:

  $source= @’

  Imports System

  Imports System.IO

  Namespace PD

    Public Class Epoch

      Public Shared Sub HelloWorld()

          Console.WriteLine(“Hello World”)

      End Sub

    End Class

  End Namespace

‘@


  Add-Type -TypeDefinition $source -Language ‘VisualBasic’

  [PD.Epoch]::HelloWorld()

Run the code in Powershell ISE:

Capture.PNG

Get Automation Object Information


Automation process needs know GUI object’s name or ID (In UI Automation, it is called AutomationID).

Inspect Objects provides this information.

Clicking Start Button. Go to All Programs->Microsoft Windows SDK v7.0->Tools->Inspect Objects.

When the application starts, select UI Automation in the dropdown.

Start Powerdesigner. Mouse hovers over the GUI. Inspect Objects shows detail on object property. See screenshot below.

The value of Name and AutomationId will be used frequently in our coding.

Capture.PNG

Develop an application


I present two examples in this article.


The code is in powershellscript_test.txt.zip, attached at bottom.

Unzip the file after download. It creates powershellscript_test.txt.

Rename powershellscript_test.txt to powershellscript_test.zip

Unzip the file.

.
UIautomationLibrary.ps1 contains C# library which can be used to access many Windows GUI objects.

.

The first example is reverse engineering a database.

Open reverseEng.ps1. Modify DBMS, database account. If you are not sure what DBMS name is,  go to

File->Reverse Engineer->Database. Click DBMS dropdown. Write down the name.

Close Powerdesigner instance if there is one.

Start PowerShell ISE. Execute UIautomationLibrary.ps1.  Execute reverseEng.ps1

Capture.PNG

Remark: The application keeps using function find and findById to obtain GUI object handle.

The value of the second parameter in both functions can be got from Inspect Objects.

Functions such as InvokeButton mimics mouse click on Button. All these functions belong to class

Robot under namespace PD. The definition of the class is in UIautomationLibrary.ps1




The second example is convert a LDM to PDM.

It creates an empty PDM. Open given LDM. Then mimics mouse click Tools->Generate Physical Data Model…

Execute proper pre-transformation. Generate a brand new PDM.

Then execute proper post-transformation to rename foreign key in the PDM.


Find a folder to store the following files: 

  project.ldm                         

  PDMtest.xem

  LDMtest.xem

  Open ldm2pdm.ps1.  Modify variable $workingPlace so it points to correct location.

  Execute UIautomationLibrary.ps1 if you haven’t done.

  Execute ldm2pdm.ps1


Capture.PNG

  Remark: System.windows.Forms.SendKeys belongs to Windows .Net Forms. It mimics keyboard typing.

  SetFocus() and leftClick() are not part of UIAutomation. They inherit from user32.dll

  Send-MailMessage ,  a very useful function fromPowerShell


  LDMtest.xem creates an extended attribute called ALIAS in entity level. We assign alias for each

  entity and store it in ALIAS. For example, we have an entity called Customer, its alias is CUST.

  We then run pre-transformation collectAliasFromLdm. It adds alias to entity name in format

      entityname:alias ( example: Customer:CUST)


  After PDM gets generated, PDMtest.xem will run post-transformation RenameFK to find alias from table name field.

  And use alias to generate foreign key name. The screenshot below shows the final result:

Capture.PNG

 

Use third party product

 


UI Automation PowerShell Extensions is an Open Source product. It contains far more features

than my library does. For those who does GUI automation testing in daily base, this is a wonderful tool. 

It can be downloaded from

            http://uiautomation.codeplex.com/


This site also has good document on how to use the extension.


reverseEng2.ps1 demonstrates how to call API in the extension.

I am using UI Automation 0.8.7 Beta 3 .NET35

Open the file, we need change DBMS and database account. We also need specify the location of

UIAutomation.dll.


Capture.PNG

 
Develop C# project to run automation 


Some programmer prefer C# or Visual Basic as develop tool. Attached is a project sample.

I use Microsoft Visual Studio Express 2012 to create the project.

Download CSharpAutomation.txt.zip.

Unzip the file. It creates  CSharpAutomation.txt.

Rename file CSharpAutomation.txt to CSharpAutomation.zip.

Unzip the file.

This is C# version of reverse engineer. You need modify DBMS and database account information in the code.

Start Powerdesigner first.

Run the code.

Capture.PNG


 




To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply