A few days ago, I ran into a troublesome situation in a VDI environment with linked-clones. There was an application a customer wanted to have virtualized but this application was involving the use of a barcode scanner. Unfortunately, this scanner required the installation of a driver and ThinApp does not support driver virtualization. Adding a driver implied a modification to the current XP golden image then a recompose of hundreds virtual machines. This wasn’t desired since a few people were using this application with a barcode scanner. So I set up a little trick with the scripting possibilities offered by the ThinApp API Calls.

A little recap of the application:

It had several entry points and for only one of them the driver was required. Each entry point had a PermittedGroup assigned. The application requires a COM port installed on the system to execute without error. The golden image had no serial port so the application was giving some errors about no COM port detected. The driver was installing a fake COM port allowing USB redirection of the scanner (well, it’s a really old app…). The COM port must be installed before the application start or the scanner won’t work even if it was installed just a few seconds after the app started.

Regarding the script, in this situation, I didn’t have a lot of choices among ThinApp APIs Calls. Plus, I had to pass local admin credentials to make the device installation possible (no need for a domain account). As example, I’ll used PsExec from the Sysinternals tools to pass the credentials but you can use any third-party tools allowing you to do so. Better, if you have PowerShell in your golden image you can use a PSCredential object to accomplish this.

Note: If you have a Windows 7 golden image, you can follow this procedure in order to avoid passing a local admin credentials.

Here is a list of third-party tools you might find around Internet (didnt’t test them personally):

The script is easily customizable and might help people in a similar situation:

01
' Declare variables
02
Dim objWSHShell, objFSO, strLogonServer, strPsExec, strDriverPath, strUsername, strPassword, strParameters 
03
Dim objWMIService, strWMIQuery, objProcess, colProcess
04
Dim strComputer, strProcessToFind
05
 
06
' Set global variables
07
Set objWSHShell = CreateObject("Wscript.Shell")
08
Set objFSO = CreateObject("Scripting.FileSystemObject")
09
 
10
' This Thinapp API function is called only when an application first locks the sandbox
11
Function OnFirstSandboxOwner
12
 
13
	' If the driver folder exists, does nothing
14
	If objFSO.FolderExists("C:\Program Files\Driver") Then
15
		' Does nothing
16
	Else
17
		strComputer = "."
18
		strProcessToFind = "Entry_Point_Name.exe"
19
 
20
		If IsProcessRunning(strComputer, strProcessToFind) = True Then
21
 
22
			' Driver setup variables
23
			strLogonServer = EnvString("LOGONSERVER")
24
			strPsExec = strLogonServer & "\NETLOGON\PsExec.exe"
25
			strDriverPath = "Driver_Path"
26
			strParameters = "Installer_parameters"
27
 
28
			' Local admin account credentials
29
			strUsername = "Local_Administrator"
30
			strPassword = "Password"
31
 
32
			' Driver installation
33
			id = ExecuteExternalProcess(strPsExec & "  /accepteula -u " & strUsername & " -p " & strPassword & " cmd /c " & Chr(34) & strDriverPath & Chr(34) & " " & strParameters)
34
			' Wait for process to finish
35
			exitCode = WaitForProcess(id, 0)
36
		End If
37
	End If
38
 
39
End Function 
40
 
41
' Custom functions
42
Function EnvString(variable)
43
	variable = "%" & variable & "%"
44
	EnvString = objWSHShell.ExpandEnvironmentStrings(variable)
45
End Function
46
 
47
Function IsProcessRunning(ByVal strComputer,ByVal strProcessName)
48
 
49
	strWMIQuery = "SELECT * FROM Win32_Process WHERE Name LIKE '" & strProcessName & "'"
50
 
51
	Set objWMIService = GetObject("winmgmts:" _
52
	& "{impersonationLevel=impersonate}!\\" _ 
53
	& strComputer & "\root\cimv2") 
54
 
55
	If objWMIService.ExecQuery(strWMIQuery).Count > 0 Then
56
		IsProcessRunning = True
57
	Else
58
		IsProcessRunning = False
59
	End If
60
 
61
End Function 
62

Since I wanted to install the driver only when a specific entry point was executed, I had to make a specific verification. I couldn’t use the API Call GetCurrentProcessName as it would return the data container name, not very helpful here.
Also, in order to prevent a driver setup inside a same session I chose to check if a certain folder of the driver exists because it doesn’t exist in the golden image and a refresh happens at the user logoff.

This little workaround might be helpful for you and give others some nice scripting ideas! ;-)