Home
Solutions
Download
Purchase
Documentation
Get Help
Reseller
My Account
Testimonials
Customers
Contact
SyncDir

Custom commands and functions

A custom command or function is basically a script block wrapped as a separate command or function, making it look exactly like any native command or function to the script constructor.

Some of the pros of structuring scripts this way, would be to encapsulate the complexity of script blocks and thereby make scripts easier to create and maintain. Another pro is ensuring reuse, to make sure any one operation executes the same way from any script.

Custom commands and functions can also be used as building blocks to split workloads. An external consultant could have made custom commands and functions for a customer, to use as building blocks to make scripter easier to construct and maintain. Or the custom commands and functions could have been downloaded from the internet - or it could simply be that one administrator has deeper technical knowledge that other internal script constructors and makes custom commands and functions for others to use.

Custom commands

Let's create two custom commands. One to delete all files in a directory tree older than a specific number of days and the other to backup all sql server databases. These commands could be used to backup sql server files and then subsequently delete obsolete backup files. Our two custom commands look like this:

''Deletes all files older than a specific number of days from a directory tree

Command MyDeleteFilesOlderThan(Path,Days)

  Loop File,[SubFileTree [Param Path]]

    If [FileCreationDate [Var File]]<[SubtractDays [Param Days]] Then

      DeleteFile [Var File]

    End If

  End Loop

End Command

 

''Backs up all SQL server database files

Command MySqlBackup(InstanceName,Destination)

  StopService [Param InstanceName]

  SyncDir [ProgramFilesDir]\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA,[Param Destination]

  StartService [Param InstanceName]

End Command

A custom command is a script block between a "Command" and "End Command" statement. We have decided to call our two commands "MyDeleteFilesOlderThan" and "MySqlBackup", both of which take two parameters. If a command takes no parameters, an empty set of parenthesis must be used. Inside the command, the "Param" function can be used to extract the parameter values for the command.

In the screenshot below, the above script lines were typed in to a new script. While keying in letters, something interesting happens. The script editor will at all times automatically sense when custom commands and functions are typed in or changed. The two custom commands we just typed in, are now showed along with all other commands and functions in the engine browser tree. All custom commands and functions will be shown under a root item called "Custom Commands and Functions".

Custom commands with Fasttrack Scripting Host example 1 `
So now our two commands behave just like any other command, so if "M" is typed, our two new commands will show up in the command completion window:

Custom commands with Fasttrack Scripting Host example 2 `
The command script blocks can be placed anywhere in a script or in included files. When using our new commands, our script lines calling them can be before or after the command blocks.

So putting our two new commands to work could look like this:

Custom commands with Fasttrack Scripting Host example 3 `
Observe how the context helper now showed a useful help to using our "MyDeleteFilesOlderThan" command. Where did that come from? Let's look at the script again:

''Deletes all files older than a specific number of days from a directory tree

Command MyDeleteFilesOlderThan(Path,Days)

  Loop File,[SubFileTree [Param Path]]

    If [FileCreationDate [Var File]]<[SubtractDays [Param Days]] Then

      DeleteFile [Var File]

    End If

  End Loop

End Command

At the location of starting command or function block, the script editor looks at the previous line. If this line is a comment, this comment is used in the context helper in relation to this custom command or function. A comment block starting with /* and ending with */ can be also used to create multi-line help.

Custom functions

Custom functions are defined much the same way custom commands are, using a "Function" and "End Function" block instead. The main difference is that a function has to return a value. This is done with the "Return" command. A custom command can also use the "Return" command without parameters, in case it has to exit prematurely. The return value a function is not limited to one value; a list of values can also be returned, effectively making it a custom collection.

Let's try a scenario with a custom function. In a logon script, I would like to collect system information from clients, including screen information. Investigating "Screen" in the engine browser, reveals that I can get information about screen resolution, but I would also like to know if some users are still using legacy non-wide screen displays. This could of course be determined by collecting heights and widths, but it would be easier to just implement my own "ScreenRatio" function that I consider missing. So let's try that:

''Returns the ratio of the screen width and height

Function ScreenRatio()

  Return [Round [Calc [ScreenWidth]/[ScreenHeight]],2]

End Function

 

WriteXMLValue \\AcmeServer\Log$\Screens.xml,/ScreenRatios/[ComputerName],[ScreenRatio]

The engine already provides the functions to get height, width and the required math functions. So we simply divide the width and height, format that nicely with two decimals and return the result. We then use WriteXMLValue to log values from the logon script, using an XML file to make sure that we only keep one value per client, as values per computer are overridden in subsequent logons. With three example computers, the XML could look like this, revealing that PC8 is indeed using a legacy 4:3 screen:
<ScreenRatios>
  <PC1>1.6</PC1>
  <PC7>1.78</PC7>
  <PC8>1.33</PC8>
</ScreenRatios>
As a footnote, observe that your custom functions and commands are slightly differently colored in the syntax highlighting. This way you do not need to investigate further, to determine if it is a custom function or not.

Encapsulation

Our last example was implemented as a custom function. The same result could have been produced with a single script line:

WriteXMLValue \\AcmeServer\Log$\Screens.xml,/ScreenRatios/[ComputerName],[Round [Calc [ScreenWidth]/[ScreenHeight]],2]

This is much shorter, so why bother to split it at all? The answer is that in many cases, there might be no point to splitting it. If you are sure you will not need ScreenRatio ever again, it might be overkill. But if you suspect you might need any given functionality elsewhere again, it makes good sense. Suppose our function was 10-20 lines and much more complex. Then it makes good sense to encapsulate it into its own custom command or function with a simple interface. This will make scripts, where it is used, much easier to maintain.

Custom commands and functions are fully resolved through included files hierarchies. As more and more custom commands and functions are built, it will be a good idea to collect these in one or more include files. And if multiple administrators work on scripting, the encapsulation of complexity will make script construction a lot easier. One administrator knows how to create a script snippet that deletes files older than a specific number of days. The other administrators do not need to know how to do this - they can just call a command with two parameters.

If we put our example custom commands and functions presented here into its own included script file, we have effectively created a small script library. Our commands and functions are now encapsulated inside this include file, so our consuming script can be very simple:

Include MyScriptLib.fsh

 

MySqlBackup MSSQL$SQLEXPRESS,O:\SQLBackups\[Date]

MyDeleteFilesOlderThan O:\SQLBackups,90


NOAA GLS Maersk Kawasaki Disney Goodyear Telenor AJG All testimonials ->
More customers ->