Using Microsoft Powershell to automate Powerdesigner is easy and fun.
Windows 7, by default, has Powershell installed. Most of Powerdesigner users should be able to access the tool.
In this post, I'm going to use two examples to demonstrate how to integrate Powerdesigner 16.5.3 with Powershell.
First of all, let's start Powershell.
Click Start button->Run...
type powershell. Click OK. Powershell window shows up.
In Powershell window, type the following command:
$pd = new-object -com powerdesigner.application
It tells Powershell to start powerdesigner as com object. Here new-object is a Powershell command.
$pd is a variable to store Powerdesigner object.
Powerdesigner started.
Next, we use powershell command get-member to find Powerdesigner API.
$pd | get-member
TypeName: System.__ComObject#{57c91ea5-68ef-4877-bb3e-757b12ecae55}
Name MemberType Definition
---- ---------- ----------
BeginTransaction Method void BeginTransaction ()
CancelTransaction Method void CancelTransaction ()
ConvertToUTF16 Method void ConvertToUTF16 (string, string)
ConvertToUTF8 Method void ConvertToUTF8 (string, string)
CreateModel Method BaseObject CreateModel (int, string, OpenModelFlags)
CreateModelFromTemplate Method BaseObject CreateModelFromTemplate (string, OpenModelFlags)
CreateModelWithDialog Method BaseObject CreateModelWithDialog (int, string, OpenModelFlags)
EndTransaction Method void EndTransaction ()
EvaluateNamedPath Method string EvaluateNamedPath (string, bool, bool)
ExecuteCommand Method string ExecuteCommand (string, string, CommandExecutionMode)
FileImport Method BaseObject FileImport (string, string, int, string, OpenModelFlags)
GetModuleForModelFile Method BaseObject GetModuleForModelFile (string)
IsKindOf Method bool IsKindOf (int, int)
MapToNamedPath Method string MapToNamedPath (string)
NewGUID Method string NewGUID ()
newPoint Method APoint newPoint (int, int)
NewPtList Method PtList NewPtList ()
NewRect Method ARect NewRect (int, int, int, int)
OpenModel Method BaseObject OpenModel (string, OpenModelFlags)
Output Method void Output (string)
ProfileSnap Method void ProfileSnap (string, bool, int)
Progress Method BaseObject Progress (string, bool)
Rtf2Ascii Method string Rtf2Ascii (string)
Rtf2Html Method string Rtf2Html (string)
ShowHelp Method void ShowHelp (int)
ActiveDiagram Property BaseObject ActiveDiagram () {get}
ActiveGlossary Property BaseObject ActiveGlossary () {get}
ActiveModel Property BaseObject ActiveModel () {get}
ActivePackage Property BaseObject ActivePackage () {get}
ActiveSelection Property ObjectSet ActiveSelection () {get}
ActiveWorkspace Property BaseObject ActiveWorkspace () {get}
CheckPermissionsMode Property bool CheckPermissionsMode () {get} {set}
EclipseWorkspace Property string EclipseWorkspace () {get}
ExternalClientAdapter Property IDispatch ExternalClientAdapter () {get}
HomeDirectory Property string HomeDirectory () {get}
InteractiveMode Property InteractiveModeValue InteractiveMode () {get} {set}
LicenceParameters Property string LicenceParameters () {get}
LicenceStatus Property string LicenceStatus () {get}
Locked Property bool Locked () {get} {set}
MainWindowHandle Property LONG_PTR MainWindowHandle () {get}
MetaModel Property BaseObject MetaModel () {get}
Models Property ObjectSet Models () {get}
PicturesTransparentColor Property OLE_COLOR PicturesTransparentColor () {get} {set}
RegistryHome Property string RegistryHome () {get}
RepositoryConnection Property BaseObject RepositoryConnection () {get}
ScriptInputArray Property Variant ScriptInputArray () {get}
ScriptInputParameters Property string ScriptInputParameters () {get}
ScriptResult Property string ScriptResult () {get} {set}
ShowMode Property bool ShowMode () {get} {set}
UserDataDictionary Property IStringDataDictionary UserDataDictionary () {get}
UserName Property string UserName () {get}
ValidationMode Property bool ValidationMode () {get} {set}
Version Property string Version () {get}
Viewer Property bool Viewer () {get}
From above output, we learn that we can create a model by via $pd.CreateModel.
Let's create a physical model.
# 1) Call Powershell commandl add-type to load two dlls into Powershell. By default, two assembly are in Powerdesigner folder.
add-type -path 'C:\Program Files\Sybase\PowerDesigner 16\Interop.PdCommon.dll'
add-type -path 'C:\Program Files\Sybase\PowerDesigner 16\Interop.PdPDM.dll'
# 2) The following code create a table with a column:
$model=$pd.CreateModel([PdPDM.PdPDM_Classes]::cls_Model,"|Diagram=PhysicalDiagram",0)
$model.name ="MY_PDM"
$diagram=$model.PhysicalDiagrams.Item(0)
$tbl=$model.CreateObject([PdPDM.PdPDM_Classes]::cls_Table,"" , -1, $false)
$tbl.Name="Customer"
$tbl.Code="Customer"
$tbl.Comment="Customer table"
$tbl.Description="The customer table stores customer data"
$coln=$tbl.Columns.CreateNew([PdPDM.PdPDM_Classes]::cls_Column)
$coln.Name="ID"
$coln.Code="ID"
$coln.DataType="integer";
$coln.Primary=$true
$diagram.AttachObject($tbl)
In Powerdesigner, a table is created.
Save above code in a file with .ps1 as suffix. For example, createTable.ps1. In Powershell window, type Table.ps1 and hit return.
Microsoft provides PowerShell ISE (PowerShell Integrated Scripting Environment) to make coding friendly.
Please check http://technet.microsoft.com/en-us/library/dd315244.aspx for more information.
One of the great features in Powershell is its seamless integration with .NET architecure.
You can call Windows API and .NET assembly fairly easily in Powershell.
My next example shows you how to call Windows API in Powershell to open and close PowerDesigner child window.
First of all, we need learn how to call external function in Powershell.
Let's create a file called AutomatPowerdesigner.ps1. Copy the following code in the file:
$signature=@'
[DllImport("user32.dll",SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public static IntPtr GetWindow(string windowName){
return FindWindow(null,windowName);
}
'@
Add-Type -memberDefinition $signature -name "GUI" -namespace PD -passThru
$pd = new-object -com powerdesigner.application
start-sleep 2
[PD.GUI]::GetWindow("PowerDesigner")
Save the file. Start Powershell . Run AutomatPowerdesigner.ps1 in Powershell command prompt.
The output is something like
2100266
This is the window handle value for PowerDesigner window instance.
If you close Powerdesigner and run AutomatPowerdesigner.ps1 again, the output becomes 0.
0 means the window cannot be found.
Let's explain the code in detail.
1)
$signature=@'
[DllImport("user32.dll",SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public static IntPtr GetWindow(string windowName){
return FindWindow(null,windowName);
}
'@
We want to call Microsoft Window function FindWindow. Giving a window's name, it returns the window's handle value.
We create a variable $signature to store the definition. Between @' and '@ is the function definition.
a) DllImport loads user32.dll(FindWindow is defined in user32.dll) into Powershell.
[DllImport("user32.dll",SetLastError = true)]
b) Declare the extern function prototype in C# syntax.
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
c) Define user-defined function in C# syntax.
public static IntPtr GetWindow(string windowName){
return FindWindow(null,windowName);
}
2)
Add-Type -memberDefinition $signature -name "GUI" -namespace PD -passThru
As mentioned above, Add-Type is a Powershell command.
The code defines a type name called GUI and a namespace PD.
3)
Start Powerdesigner. Let's sleep for 2 seconds so Powerdesigner gets enough time to start its window.
$pd = new-object -com powerdesigner.application
start-sleep 2
4)
To call user-defined function, you need specify namespace and type name:
[PD.GUI]::GetWindow("Windows PowerShell")
Now we know how to call Microsoft Window API as extern function.
The example below open an existing PDM(C:\temp\myPDM.pdm).
$signature=@'
[DllImport("user32.dll",SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public static IntPtr GetWindow(string windowName){
return FindWindow(null,windowName);
}
[DllImport("user32.dll",SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
public static IntPtr GetControl(IntPtr value, string controlname){
return FindWindowEx(value, IntPtr.Zero, null, controlname);
}
[DllImport("user32.dll",SetLastError = true)]
public static extern int PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public static void LeftClick(IntPtr handle){
uint WM_LBUTTONDOWM = 0x0201;
uint WM_LBUTTONUP = 0x0202;
PostMessage(handle, WM_LBUTTONDOWM, 0, 0);
PostMessage(handle, WM_LBUTTONUP, 0, 0);
}
[DllImport("user32.dll",SetLastError = true)]
public static extern IntPtr ShowWindow(IntPtr hwnd, int nCmdShow);
public static IntPtr MaximizeWin(IntPtr hwnd){
int SW_MAXIMIZE = 3;
return ShowWindow(hwnd, SW_MAXIMIZE);
}
'@
Add-Type -memberDefinition $signature -name "GUI" -namespace PD -passThru
add-type -path 'C:\Program Files\Sybase\PowerDesigner 16\Interop.PdCommon.dll'
add-type -path 'C:\Program Files\Sybase\PowerDesigner 16\Interop.PdPDM.dll'
Add-Type -AssemblyName System.Windows.Forms # I want to call SendWait.
$pd = new-object -com powerdesigner.application
start-sleep 1
$pd.OpenModel("C:\temp\myPDM.pdm")
start-sleep 1
$PDwin=[PD.GUI]::GetWindow("PowerDesigner")
[PD.GUI]::MaximizeWin($PDwin)
#Send ALT+T
[System.Windows.Forms.SendKeys]::SendWait("%T")
start-sleep 1
#Send Cntrl+Shift+P
[System.Windows.Forms.SendKeys]::SendWait("^+P")