Installing a driver with VMware ThinApp
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") Then15 ' Does nothing
16 Else
17 strComputer = "."
18 strProcessToFind = "Entry_Point_Name.exe"
19 20 If IsProcessRunning(strComputer, strProcessToFind) = True Then21 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 If37 End If38 39 End Function40 41 ' Custom functions
42 Function EnvString(variable)
43 variable = "%" & variable & "%"44 EnvString = objWSHShell.ExpandEnvironmentStrings(variable)45 End Function46 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 Then56 IsProcessRunning = True
57 Else
58 IsProcessRunning = False
59 End If60 61 End Function62
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!