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:
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:
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:
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:
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