COM automation with FastTrack Automation Studio

COM is short for Component Object Model, which is a technology that allows software components to communicate.

COM is a great technology because you can interact with any component that exposes a COM interface that you might not be able to script otherwise. The drawback of COM (in a scripting sense) is that it is late binding. Late binding means that methods and properties of the COM interface are determined at run-time and not at compile-time. This effectively means that working with COM interfaces from scripts is a time-consuming trial-and-error process. Another drawback of late binding is that you have to find documentation from the vendor of the COM interface and convert that into the syntax of your scripting language.

COM automation

Comparison

If you have used VBScript, you are probably familiar with common COM interfaces like WScript.Network and Scripting.FileSystemObject. These are interfaces that sit on top of the Windows API. When using FastTrack, however, these types of COM interface become superfluous, as FastTrack uses the Windows API directly, voiding the need for late binding.

By way of comparison, let's look at a very simple example of connecting a share in three different ways:
Connect Network Share - VBScript version:
Set objNetwork = WScript.CreateObject("WScript.Network")
objNetwork.MapNetworkDrive "F:", "\\AcmeServer\Share"

Connect Network Share - FastTrack COM version

Exec CreateObject(WScript.Network).MapNetworkDrive(F:,\\AcmeServer\Share)


Connect Network Share - FastTrack native version

ConnectShare F:,\\AcmeServer\Share

It immediately becomes clear why the native FastTrack version is preferred: When you write the script line in the script editor, it is validated that ConnectShare is, in fact, a valid command and that its parameters are also valid. The other two versions require you to know that the way to connect a network share is to instantiate an object from the WScript.Network COM interface. You also have to know that this interface has a method called "MapNetworkDrive" and which parameters this method can take. The only way to validate that everything is syntactically and semantically correct, is to execute the script and see if it fails.

When to use COM with FastTrack

The example above was very simple; when working with more complex COM integration from scripts in any scripting language, script construction becomes chaotic and often impossible to make robust. For this reason COM was introduced as late as version 6.2 in FastTrack, because COM interfaces must be used as a last resort. As a general rule, do not use COM if you can avoid it. The use of COM interfaces is an "expensive" way for an administrator to facilitate the Windows API. You will probably never actually need to work with COM interfaces, as FastTrack has native functionality to replace COM interfaces that reflect the API of the operating system.

However, you will need to work with COM interfaces if you need to automate Excel, for instance. Automating Excel is outside the scope of FastTrack because it will never provide native functionality for the thousands of methods and properties in Excel's COM interface. Let's look at a simple example of using COM with Excel:

ShowMessage You have excel version [ObjectValue CreateObject(Excel.Application).Version]

In this case we have created a COM object by using the CreateObject function, specifying "Excel.Application" as the COM interface. On this object we are getting the value of the property "Version" and displaying that through the ShowMessage command. When Office 2010 is installed, this is the result:

Excel Automation


This would be useful information for a logon script if, for example, you are unsure that every computer on the network has been upgraded to Office 2010. Instead of trying to "guess" the installed version from registry keys or similar, why not just ask the application itself? In case a computer has an old version, you could store the version information in a log file (AppendFile command) or a central xml file (WriteXMLValue command), send an e-Mail to the HelpDesk (SendMail command) or simply ask the user to contact HelpDesk at their convenience. The latter could look like this:

If ObjectExists Excel.Application Then

  If [ObjectValue CreateObject(Excel.Application).Version]<>14.0 Then ShowMessage You do not have Office 2010, contact HelpDesk.

End If

Advanced COM example

The COM functionality of FastTrack can also be used for more advanced COM tasks. The following sections will explain the details of FastTrack's COM syntax, but let's look at an Excel automation example first, to give you an idea of what advanced COM usage might look like. This type of COM usage in general could be useful for creating a report summarizing computer information. We will however simplify the example to simply insert static numbers, use various custom formatting and then insert a formula to sum up cell values. The report will look like this:


Excel Automation


To get this example to work, a deeper knowledge of the Excel COM interface is needed from the vendor. In this case, the interface is well-documented here on the Microsoft Developer Network (MSDN). Armed with this, the above example can be constructed like this:

''Create Excel object

SetObject MyExcel = CreateObject(Excel.Application)

 

''Create new workbook

Exec MyExcel.Workbooks.Add()

 

''Insert example text into cell A1 - set bold and change font size

SetValue MyExcel.Cells(1,1).Value = FastTrack Excel Formula Test Sheet

SetValue MyExcel.Cells(1,1).Font.Bold = True

SetValue MyExcel.Cells(1,1).Font.Size = 18

 

''Insert 10 rows with values - center cells and use number format

For Row = 3 to 12

  SetValue MyExcel.Cells([Var Row],2).Value = [Calc [Var Row]-2]

  SetValue MyExcel.Cells([Var Row],2).NumberFormat = (string)0,00

  SetValue MyExcel.Cells([Var Row],2).HorizontalAlignment = 3

End For

 

''Insert formula at B14 - use number format, center, set bold and set wider

SetValue MyExcel.Cells(14,2).Formula = "=Sum(B3:B12)"

SetValue MyExcel.Cells(14,2).NumberFormat = (string)0,00

SetValue MyExcel.Cells(14,2).HorizontalAlignment = 3

SetValue MyExcel.Cells(14,2).Font.Bold = True

SetValue MyExcel.Cells(14,2).ColumnWidth = 30

 

''Set visible

SetValue MyExcel.Visible = True

The above script is directly available in the script editor: Go to the "Documentation" tab and select "COM Automation" under the "Insert Example Script" submenu.

FastTrack COM syntax

As you may have noticed in the previous sections, working with the items under the editor's "COM Automation" uses a very different syntax than all other items. This is because when you are using the COM Automation items, you are effectively programming without the benefits of compiling code, which is a good reason to stay away from COM when possible.

To provide the highest readability possible in your scripts, the COM Automation items work with a property, method and parameter syntax known from Object-Oriented Programming Languages: Methods and properties are used by using a dot notation on an object, while method parameters are insides parentheses. It's important to understand that any property or method is also an object in itself - which is all explained in more detail in the "Inline Initializers" section further down.

Let's look at the COM items:
COM Overview
CreateObject function: Any COM operation must start with CreateObject, used to create a COM object or to connect to a running COM interface.
SetObject command: Sets an internal object for all other COM commands and functions. This is used to break COM operations into multiple script lines.
Exec command: Executes a method on a COM object.
SetValue command: Sets a property value on a COM object.
ObjectValue function: Gets a property value or the return value of a method from a COM object.
ObjectExists conditions: Determines if a COM interface for CreateObject exists or not.
You might be surprised that you only need these few items for any type of COM operation. This is because most of the COM complexities are resolved by the engine in order to simplify your scripting as much as possible when dealing with COM operations. For example, to get a value, you do not need to know when an object is a method or property. When you use the ObjectValue function to get the value of a property or the result of a method, it will automatically be determined for you at run-time, if the object is, in fact, a property or method. This is why there is only one "ObjectValue" function and not two "ObjectProperty" and "ObjectMethod" functions. Likewise, there is no distinction between CreateObject and GetObject, known from other scripting languages (see next section for details).

The CreateObject function

If you are familiar with VBScript or KiXtart, you will know that any COM operation will have to start with a CreateObject or GetObject command. CreateObject creates a COM object and GetObject connects to a running COM component. Sometimes it can be confusing to know when to use which, which is why FastTrack automatically resolves which to use at run-time. Therefore there is no GetObject function, as the CreateObject function will automatically detect the correct method of use behind the scenes. CreateObject will simply do both.

A function is normally used as [Function <Parameters>]. CreateObject is also a function, but it's the exception to this rule. Let's look at an example:

SetObject MyExcel = CreateObject(Excel.Application)

You might have expected to use it a SetObject MyExcel=[CreateObject Excel.Application]. The reason for this syntactical difference is because of the general object dot notation on COM objects. Let's look at CreateObject in another context: SetObject can be used with just the CreateObject function, as above, but anywhere CreateObject is used, any sub-object or sub-property can be retrieved instead, simply by dotting your way to the desired object. Below, an object is retrieved to a system folder object of the executing engine's parent folder. The second line displays the "Name" property of this object, which is the name of the parent folder. For simplicity, we will display results with the ShowMessage command in the examples from here on.

SetObject ParentFolder = CreateObject(Scripting.FileSystemObject).GetFile([FastTrackExe]).ParentFolder

ShowMessage Parent folder: [ObjectValue ParentFolder.Name]

Looping through objects

Some methods can return a collection of objects. To loop through an object collection, use the ForEachObject looping construct. In the example below CreateObject connects to the WMI interface on the local computer and performs a WMI query to retrieve the Name property of each disk object from the Win32_LogicalDisk disk WMI collection.

ForEachObject Drive in CreateObject(winmgmts:).ExecQuery("Select * from Win32_LogicalDisk")

  ShowMessage [ObjectValue Drive.Name]

End ForEachObject

Other properties than "Name" can then be used inside the loop on the "Drive" object. The most common use of COM is using WMI objects, as explained in this article and in the example above. For this reason there is also a CreateWMIObject function, which is basically the same as CreateObject, except that is assumes that the object is "winmgmts:" and the method is "ExecQuery". The above can therefore be written in this way also:

ForEachObject Drive in CreateWMIObject("Select * from Win32_LogicalDisk")

  ShowMessage [ObjectValue Drive.Name]

End ForEachObject

The SetObject command

All COM related commands, functions and the ForEachObject loop can use the CreateObject function. Any object set with SetObject can be used instead of CreateObject as the first parameter, if preferred. The result of any COM operation can be used as an object, meaning that the looping construct above could also be written as shown below, with the same result.

SetObject WMI=CreateObject(winmgmts:)

SetObject DisksCollection=WMI.ExecQuery("Select Name from Win32_LogicalDisk")

ForEachObject Drive in DisksCollection

  ShowMessage [ObjectValue Drive.Name]

End ForEachObject

It's important to understand that every time CreateObject is used, a new instance of the object is created. Usually COM operations are relatively simple and do just one thing, in which case there is no need to use SetObject first. However, in our earlier Excel spreadsheet example, there had to be a single SetObject which was to be used in all other operations. If CreateObject was used in every script line, a new Excel spreadsheet would have been created every time, and the script would not work.

Inline initializers

In the previous sections, we have used dot notations multiple times. Let's look at how that actually works. FastTrack can automatically initialize and use objects in-line to an indefinite level, which can make your COM scripts much shorter than similar scripts created with other languages. Consider this example:

SetObject FSO = CreateObject(Scripting.FileSystemObject)

SetObject MyDrive = FSO.GetDrive(C:)

ShowMessage Free space: [ObjectValue MyDrive.FreeSpace]

This is relatively straight-forward and similar to what you would see with other scripting languages. First an instance of Scripting.FileSystemObject is created. Then we need to call the method "GetDrive" to get an object on which we need the property named "FreeSpace". We don't really have any use for the "GetDrive" object itself in this example, so we can let FastTrack initialize it dynamically as part of retrieving the property like this:

SetObject FSO=CreateObject(Scripting.FilesystemObject)

ShowMessage Free space: [ObjectValue FSO.GetDrive(C:).FreeSpace]

...or, alternatively, as part of setting the object:

SetObject FSO=CreateObject(Scripting.FilesystemObject).GetDrive(C:)

ShowMessage Free space: [ObjectValue FSO.FreeSpace]

The above example will produce the same result because CreateObject can also be used as an in-line initializer itself. Anywhere you would use an object, you can dynamically initialize the root object by creating a COM object with the CreateObject function. This means our example can be written down to one single line without really losing readability:

ShowMessage Free space: [ObjectValue CreateObject(Scripting.FileSystemObject).GetDrive(C:).FreeSpace]

Please note that this example is for demonstration purposes only; it could also be simply done by using the FreeDiskSpace function:

ShowMessage Free space: [FreeDiskSpace]

Type casting

The last thing about which you must be aware when using COM interfaces in any language, is that they are strongly typed. This means that the type of parameters must be explicit. Consider these three lines from the Excel example earlier on this page:

SetValue MyExcel.Cells(14,2).NumberFormat = (string)0,00

SetValue MyExcel.Cells(14,2).HorizontalAlignment = 3

SetValue MyExcel.Cells(14,2).Font.Bold = True

FastTrack will automatically convert parameters and values. In almost any case, the conversion is correct, which saves you the trouble of explicitly specifying types any time you use a value or parameter. However, in a special case, you could be forced to explicitly overrule the conversion and this can be done by "type casting" a value or parameter to String, Int, Boolean, Decimal, Double, DateTime, Byte or Char. If we look at the example lines above, the last two lines will be correctly converted to integer and boolean respectively. The first line, however, would have been converted to a Decimal value, but since we mean a cell-formatting string, we need to type cast it to a string, which is why the value is prefixed with the (string) type cast.

Advanced COM automation example 1: Getting Microsoft Office information from the Excel COM interface

This example will query the COM interface of Microsoft Excel for information like installed version, installation path and language. The information can then be used in a logon script for example to determine, if an upgrade is needed.

This example is also available in the script editor: Go to the "Documentation" tab and select "Get Office Install Info" under the "Insert Example Script" submenu.

''==== DEFAULT TO EMPTY ====

Set OfficeVer=[Blank]   ''Contains 2007 or 2010 or blank

Set OfficePath=[Blank]  ''Full path of the office binary directory

Set OfficeLang=[Blank]  ''Language code, e.g. 1 for US; Codes here: http://support.microsoft.com/kb/111388

Set OfficeBits=[Blank]  ''32 or 64

 

''==== TEST IF OFFICE INSTALLED AT ALL ====

If ObjectExists Excel.Application Then

  SetObject Excel=CreateObject(Excel.Application)

 

  ''==== CONVERT VERSION STRING ====

  If [ObjectValue Excel.Version]=12.0 Then Set OfficeVer=2007

  If [ObjectValue Excel.Version]=14.0 Then Set OfficeVer=2010

  If [ObjectValue Excel.Version]=15.0 Then Set OfficeVer=2013

 

  ''==== GET PATH AND LANGUAGE ====

  Set OfficePath=[ObjectValue Excel.Path]

  Set OfficeLang=[ObjectValue Excel.International(1)]

 

  ''==== TEST BITS ON ANY OFFICE EXE ====

  If FileIs32Bit [Var OfficePath]\WinWord.Exe Then Set OfficeBits=32

  If FileIs64Bit [Var OfficePath]\WinWord.Exe Then Set OfficeBits=64

End If


Advanced COM automation example 2: Controlling Hyper-V machines with the COM interface and WMI

This example will list all Hyper-V machines on the local machine and control the state of the selected machine. With 5 virtual machines, the initial menu could look like this:

Hyper-V Automation


This example is also available in the script editor: Go to the "Documentation" tab and select "Hyper-V State Controller" under the "Insert Example Script" submenu.

''==== CREATE WMI INSTANCE AND MACHINE COLLECTION ===

SetObject WMI = CreateObject("winmgmts:\\.\root\virtualization")

CreateCollection MachineList

 

''==== LOOP THROUGH MACHINES - THE LOCAL COMPUTER WILL ALSO BE RETURNED AND MUST BE IGNORED ===

ForEachObject Machine in WMI.ExecQuery("SELECT * FROM Msvm_ComputerSystem")

  Set MachineName = [ObjectValue Machine.ElementName]

  If [Var MachineName]<>[ComputerName] Then AddToCollection MachineList,[ObjectValue Machine.ElementName]

End ForEachObject

 

''==== WMI WILL NOT RETURN IN SORTED ORDER - FIX IT IN DISPLAYING THE LIST ===

:Restart

EnableMenuSorting

 

''==== ASK TO SELECT ===

Set SelectedMachine=[ListMenu Select virtual machine,[Collection MachineList]]

 

''==== TEST FOR NOT CANCELLED ===

If Not VarIsEmpty SelectedMachine Then

 

  ''==== GET SELECTED MACHINE WMI INSTANCE ===

  SetObject Machine = WMI.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName='[Var SelectedMachine]'").ItemIndex(0)

 

  ''==== ASK TO SELECT ===

  DisableMenuSorting

  Set NewState=[Menu Select action,Turn on,Turn off,Reboot,Pause,Suspend]

 

  ''==== EXEC ===

  Switch [Var NewState]

  Case Turn on

    Exec Machine.RequestStateChange(2)

  Case Turn off

    Exec Machine.RequestStateChange(3)

  Case Reboot

    Exec Machine.RequestStateChange(10)

  Case Pause

    Exec Machine.RequestStateChange(32768)

  Case Suspend

    Exec Machine.RequestStateChange(32769)

  End Switch

 

  Goto Restart


Advanced COM automation example 3: ActiveX Data Objects

This example is an extract from the Interacting with SQL Server page, where ADO is used to retrieve data from SQL Server. In the example, data is read from a logon audit table with three columns: LogonID, UserName and LogonTime. The example loops through the returned records from the SQL statement using COM. For more information, please refer to the full article on the Interacting with SQL Server page.

SetObject SQL = CreateObject("ADODB.connection")

Exec SQL.Open("Provider=SQLNCLI10;Server=AcmeServer\SQL;Database=LogonAudit;Trusted_Connection=yes;")

SetObject Logons = SQL.Execute("SELECT * FROM Logons WHERE UserName='[UserName]' ORDER BY LogonTime Desc")

While [ObjectValue Logons.EOF]=false

  Set LogonID = [ObjectValue Logons.LogonID]

  Set LogonTime = [ObjectValue Logons.UserName]

  ''.... do something with the variables

  Exec Logons.MoveNext

End While

Exec SQL.Close



Rating: 5 out of 5

"Use this as a replacement for VBScript and PowerShell"

"It's easy to include attractive GUI elements in FastTrack scripts, beyond the basic dialog boxes and text input that VBScript offers ... Another powerful feature is the ability to distribute scripts as Windows Installer (.msi) or standard .exe files. Although interesting in its own right, this ability results in a much more intriguing capability: to repackage -- or wrap -- software installers as .msi files without using snapshots. If you've ever created an .msi installer file from before-and-after system snapshots, for use with a software distribution system such as Group Policy or SCCM, then you know how hit-and-miss the results can be."

Read full review


Rating: 8 out of 10

"Faster than the rest"

"We found the FastTrack syntax to be more transparent and easier to learn than Microsoft's PowerShell – the editor in particular provided good support in this regard. the Script Editor offers a large number of options from the command set through to simple output of graphical elements, which cannot be achieved at all with PowerShell or other solutions or only with a significantly greater level of effort."

"Anyone wanting to tackle the many hurdles in everyday admin and especially anyone for whom logon scripts and client automation is a priority will benefit from the variety of functions offered by FastTrack."

Review in English      Review in German