Most of the times when I talk to our customers they want some functionality in ThinApp which it doesn’t offered out of the box. For example:
- Allow to run a virtualized application only until a specific date.
- Update a configuration file every time the applications is launched.
- Allow an application only to be executed when user is inside the corporate office.
- Messure the usage of an application.
- Enforce licensing restriction.
- And so on…
While such functionality, as already said, isn’t offered by ThinApp out of the box there is something else much more powerful available. With ThinApp you have a fully fledged scripting engine available in each and every ThinApp package. This allows you to implement advanced functionalities like the examples mentioned above.
ThinApp supports running VBScript-based scripts out of the box. Just place your .vbs files side by side to the package.ini, run build.bat and you have successfully integrated your script in your ThinApp package. While it is really that simple there are some very helpful things you should know about.
The ThinApp script engine natively supports VBScript. Besides the whole spectrum of VBScript functions the ThinApp script engine itself provides some additional functions. For example:
This function allows us to convert a macro folder to a system folder.
With this function it is possible to launch a process outside the virtual environment.
GetBuildOption lets us look inside the package.ini file.
With this function we are able to check if a file has for example a specific version.
This option show the command line argument a entry point was called with.
Show the name of the current process which triggered the VBScript launch.
With the help of this function you can change the registry isolation mode for a specific key during the runtime.
These are just a few example of functions the ThinApp script engine supports. All of them are documented in the ThinApp User’s Guide. Using a bit of VBScript and some of the specific ThinApp functions you could for example implement your own little help function to your ThinApp packages which works as follows:
Here is the code realizing this little helper.
Function OnFirstParentStart ' Check command line input for help parameter (-thinstallhelp) If InStr(GetCommandLine(), "-thinstallhelp") Then ' Get current entry point / process strCurrentProcess = GetCurrentProcessName ' Get build options from package.ini strInventoryName = GetBuildOption("InventoryName") strSandboxName = GetBuildOption("SandboxName") strCaptureRuntime = GetBuildOption("CapturedUsingVersion") strOptAppLinks = GetBuildOption("OptionalAppLinks") strReqAppLinks = GetBuildOption("RequiredAppLinks") ' Set message box title strTitle = "ThinApp Help" ' Compose output strMessage = "Current entry point / process: " & strCurrentProcess & Vbcrlf & Vbcrlf & "InventoryName: " & strInventoryName & Vbcrlf & "SandboxName: " & strSandboxName & Vbcrlf & "Capture Runtime: " & strCaptureRuntime & Vbcrlf & "Optional AppLinks: " & strOptAppLinks & Vbcrlf & "Required AppLinks: " & strReqAppLinks ' Display message box with Ok button and title Msgbox strMessage, 0, strTitle ' Exit process as we just want to show the help message ExitProcess 0 End If End Function
As soon as you add a VBScript to your ThinApp package the script gets executed every time a process gets launched within your ThinApp package. This equally applies to manually launched entry points and automatically launched child processes. As you can imagine this isn’t a very good behavior performance wise. For this reason the ThinApp scripting engine includes so-called callback functions. Callback functions help to control when and how often your VBScript code is executed.
When to use?
|OnFirstSandboxOwner||Use this callback function if you want to run your code each time your sandbox gets locked. This means as soon as the first process launches and locks your sandbox, normally the first entry point your launching, your code gets executed.|
|OnFirstParentStart||This function is called every time a ThinApp entry point is launched.|
|OnFirstParentExit||OnFirstParentExit is executed each time a parent process (an executable launched by an entry point) is closed. It is also executed if some child processes are left.|
|OnLastProcessExit||This function is useful if you want to run your code when all processes of your virtual application are closed. As soon as the last process quits this script gets executed.|
|-||When you not place your code in one of these callback functions your code will be executed each time a new process in your ThinApp package launched.|
For a better understanding which functions is called when try the following example. Just save the code below as example.vbs file in your ThinApp project directory, rebuild your application and start using it. The example script displays a pop up message with the name of the function currently executed and the name of the process triggering the function.
Function OnFirstSandboxOwner strMessage = "OnFirstSandboxOwner: " & GetCurrentProcessName MsgBox(strMessage) End Function Function OnFirstParentStart strMessage = "OnFirstParentStart: " & GetCurrentProcessName MsgBox(strMessage) End Function Function OnFirstParentExit strMessage = "OnFirstParentExit: " & GetCurrentProcessName MsgBox(strMessage) End Function Function OnLastProcessExit strMessage = "OnLastProcessExit: " & GetCurrentProcessName MsgBox(strMessage) End Function strMessage = "OnEveryProcess: " & GetCurrentProcessName MsgBox(strMessage)
As you may have discovered in your own testing you can add more than one script (.vbs) file to your project directory. If you add multiple scripts every script gets executed in alphanumerical ascending or descending order. The callback function OnFirstSandboxOwner is using an ascending order while all other callback functions are using a descending order. Have a look at an example using two scripts called A.vbs, B.vbs and C.vbs and the callback functions OnFirstSandboxOwner and OnFirstParentExit:
Execution order OnFirstSandboxOwner:
Execution order OnFirstParentExit:
As you see it is a bit chaotic and I strongly advice only to work with one VBScript file.
Also if you are using AppLinks and you linking two or more ThinApp packages each containing VBScripts you have to be aware of the following circumstances. Let’s suppose you have two ThinApp packages each containing a bunch of scripts. ThinApp package 1 contais A.vbs, B.vbs, D.vbs and Z.vbs while ThinApp package 2 contains A.vbs and C.vbs. ThinApp package 1 has ThinApp package 2 configured as an AppLink. What do you think happens now? Here is an example when the scripts are executed in the callback function OnFirstParentStart:
- A.vbs (from ThinApp package 2)
- B.vbs (from ThinApp package 1)
- C.vbs (from ThinApp package 2)
- D.vbs (from ThinApp package 1)
- Z.vbs (from ThinApp package 1)
As you can see the order is still the same as discussed in the .vbs file section with one exception. As both packages contained the A.vbs file only the A.vbs file from the second ThinApp package is executed. This behavior is anticipated as files from a child AppLink package (in this case ThinApp package 2) are always overwriting files from its parent AppLink package (in this case ThinApp package 1).
You now know that ThinApp has an integrated script engine which natively supports VBScript, callback and some addition function. You also know how the ThinApp script engine works. With these insights you should now be able to realize some if not all of the missing functions you always wanted ThinApp to have – assumed you have a little bit of know how in the VBScript corner.