VMware View Client as desktop shell
You can repurpose Windows PCs as thin clients in a VMware View VDI environment. Swap the Windows explorer shell (start menu and desktop) with View Client. This also works for Windows Embedded thin clients. This works best with VMware View Client v5.4.0. Newer versions (View Client 2.0 and above, don’t ask me why the version numbers are out of order) VMware changed the View Client behaviour. When you disconnect from your VDI session, the View Client doesn’t close (so Windows doesn’t logoff). Do your own testing here. Create a (user) group policy object linked to an active directory OU containing repurposed desktops. Edit the scope of the GPO, filter it on a security group containing users that need this configuration (useful if you want to switch users between connection brokers, e.g. failover between datacentres). Add the VMware View Client administrative templates so you can configure how the View Client behaves (see View admin docs on where to find these .ADM files) Replace explorer.exe with a view client wrapper script. View client doesn’t have a “run as shell” mode so you’ll need the wrapper to wait until View Client closes. Update 2015/12 See this tool to help with building up the command line to launch view client: https://labs.vmware.com/flings/view-auto-connection-utility GPO setting:``` User configuration \ Policies \ Administrative Templates \ System \ Custom User Interface
wscript.exe "<path to script in user logon script area of GPO>"
```
* * *
```
Option Explicit
dim objFs : Set objFs = WScript.CreateObject("Scripting.FileSystemObject")
dim objShell : Set objShell = WScript.CreateObject("WScript.Shell")
Dim blIs64Bit : blIs64Bit=objFs.FolderExists(objShell.ExpandEnvironmentStrings("%windir%\\sysWOW64"))
Dim strParentFolder : strParentFolder=objFs.GetFile(WScript.ScriptFullName).parentFolder
strParentFolder="C:\\Program Files\\VMware\\VMware View\\Client\\bin"
dim objNetwork : Set objNetwork = WScript.CreateObject("WScript.Network")
Dim strCommandLine, intExitcode, strErrorDescription
'Dim ViewArguments : ViewArguments="-desktopLayout multimonitor -connectUSBOnStartup true -connectUSBOnInsert true -logInAsCurrentUser true -desktopProtocol PCOIP -serverURL "
Dim ViewArguments : ViewArguments="-desktopLayout multimonitor -connectUSBOnStartup true -connectUSBOnInsert true -logInAsCurrentUser true"
Const blDebug=False
Const MsgBoxTitles="VMware View Client Shell"
Const EventSuccess=0, EventError=1, EventWarning=2, EventInformation=4, EventAuditSuccess=8, EventAuditFailure=16
Const AlertMailTo="VDI-SupportDistributionGroup@yourcompanyhere.com"
Const AlertMailForm="noreply\_ViewShellGPO@yourcompanyhere.com"
Const SMTPServer="smtp.yourcompanyhere.com"
' assuming your SMTP allows anonymous email relay internal.
dim ViewEXEPath : ViewEXEPath=strParentFolder & "\\wswc.exe"
If objfs.FileExists(ViewEXEPath)=False Then
errorMessage "VMware View client not found at " & ViewEXEPath & ". Please install."
sendEmail AlertMailForm,AlertMailTo,"View client error on " & objNetwork.UserName & " on " & objNetwork.ComputerName,"VMware View client is not installed. So please install it.",SMTPServer
WScript.Quit
End If
Dim objCommandLineArgs : set objCommandLineArgs=WScript.Arguments.Unnamed
If objCommandLineArgs.length=0 and blDebug=True Then
errorMessage "No server URL specified"
WScript.quit
ElseIf objCommandLineArgs.length>0 Then
ViewArguments=ViewArguments & WScript.Arguments.Unnamed.Item(0)
End If
strCommandLine=QuoteWrap(ViewEXEPath) & " " & ViewArguments
If blDebug Then infoMessage strCommandLine
' Launch7 View client
intExitcode=objshell.Run(strCommandLine,1,True)
' Do something with exit code
'http://pubs.vmware.com/view-50/index.jsp?topic=/com.vmware.view.administration.doc/GUID-00A46C94-A421-4561-A624-C258E6010740.html
Select Case intExitcode
Case -1
strErrorDescription="Fatal error in kiosk mode"
Case 0
strErrorDescription="Success"
Case 1
strErrorDescription="Connection failed"
Case 2
strErrorDescription="Login failed."
Case 3
strErrorDescription="Desktop failed to start"
Case 4
strErrorDescription="RDP failed to start."
Case 5
strErrorDescription="RDP operation failed"
Case 6
strErrorDescription="Tunnel connection lost."
Case 7
strErrorDescription="Local desktop transfer failure"
Case 8
strErrorDescription="Local desktop check-in failure"
Case 9
strErrorDescription="Local desktop check-out failure."
Case 10
strErrorDescription="Local desktop check-out failure."
Case 11
strErrorDescription="Local desktop check-out failure."
Case 12
strErrorDescription="Local desktop check-out failure."
Case 13
strErrorDescription="Received request to use an unknown authentication method."
Case 14
strErrorDescription="Invalid server response."
Case 15
strErrorDescription="Desktop was disconnected."
Case 16
strErrorDescription="Tunnel was disconnected."
Case 17
strErrorDescription="Reserved for future development."
Case 18
strErrorDescription="Reserved for future development."
Case 19
strErrorDescription="Unsupported kiosk operation."
Case 20
strErrorDescription="Remote mouse, keyboard, or screen (RMKS) connection error."
Case 21
strErrorDescription="PIN error."
Case 22
strErrorDescription="PIN mismatch."
Case 23
strErrorDescription="Password mismatch."
Case 24
strErrorDescription="View Connection Server error."
Case 25
strErrorDescription="Desktop was not available."
End Select
If intExitcode 'fatal
sendEmail AlertMailForm,AlertMailTo,"Fatal view client error. " & objNetwork.UserName & " on " & objNetwork.ComputerName,"View client had a fatal error. Check C:\\Users\\" & objNetwork.UserName & "\\AppData\\Local\\VMware\\VDM\\logs",SMTPServer
ElseIf intExitcode=0 Then
' success
Else
' non-fatal
sendEmail AlertMailForm,AlertMailTo,"Non-fatal view client error on " & objNetwork.ComputerName & " " & strErrorDescription,strErrorDescription & ". Check C:\\Users\\" & objNetwork.UserName & "\\AppData\\Local\\VMware\\VDM\\logs",SMTPServer
errorMessage strErrorDescription
End if
' if bldebug=false Then objShell.Run "logoff.exe",0,True ' logoff.exe doesn't exist on XP thin clients
if bldebug=false Then objShell.Run "shutdown.exe /l /f",0,True
WScript.Quit intExitcode
Function QuoteWrap(strPath)
QuoteWrap="""" & strPath & """"
End Function
Function sendEmail(ByVal strFrom,byval strTo,byval strSubject,ByVal strBody, byVal strSMTPRelay)
on error resume next ' continue if thin client does not have MAPI support
Dim objEmail : Set objEmail = CreateObject("CDO.Message")
' Expand environment variables and set defaults
strBody=objShell.ExpandEnvironmentStrings(strBody)
strFrom=objShell.ExpandEnvironmentStrings(strFrom)
strSubject=objShell.ExpandEnvironmentStrings(strSubject)
If strFrom="" Then strFrom=WScript.ScriptName
'objEmail.bcc = strTo
objEmail.To = strTo
If InStr(ucase(strBody),"")=0 Then objEmail.Textbody = strBody Else objEmail.HTMLbody = strBody End If
objEmail.From = strFrom
If InStr(strFrom,"@")=0 Then
objEmail.ReplyTo = strTo ' reply to recipent...
End If
objEmail.Subject = strSubject
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSMTPRelay
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 10
objEmail.Configuration.Fields.Update
On Error Resume Next
Err.clear
' continue without crashing if e-mail relay is not available
objEmail.Send
Select Case Err.Number
Case 0
sendEmail=True
'InfoMessage "Mail sent to " & objEmail.To & " from " & objEmail.From
Case &h8004020C
' recipient required
errorMessage hex(err.Number) & " " & Err.Description & ". Failed send to " & objEmail.To & " from " & objEmail.From & " via " & strSMTPRelay
sendEmail=False
Case Else
errorMessage hex(err.Number) & " " & Err.Description & ". Failed send to " & objEmail.To & " from " & objEmail.From & " vai " & strSMTPRelay
sendEmail=False
End Select
On Error GoTo 0
Set objEmail=Nothing
End Function
Sub errorMessage(strMessage)
msgbox strMessage,vbCritical,MsgBoxTitles
objShell.LogEvent EventError,strMessage
writeToLog "ERROR: " & strMessage
End Sub
Sub infoMessage(strMessage)
msgbox strMessage,vbinformation,MsgBoxTitles
objShell.LogEvent EventInformation,strMessage
writeToLog "INFO: " & strMessage
End Sub
Sub debugMessage(strMessage)
If blDebug=true Then WScript.Echo strMessage
'objShell.LogEvent EventInformation,strMessage
writeToLog "DEBUG: " & strMessage
End Sub
Sub writeToLog(ByVal strMessage)
On Error Resume next
strMessage=Now() & " " & strMessage
Const ForReading = 1, ForWriting = 2, ForAppending=8
Dim strLogFilePath, objLogFile
strLogFilePath=objShell.ExpandEnvironmentStrings("%temp%")
strLogFilePath="C:\\windows\\temp"
strLogFilePath=strLogFilePath & "\\" & WScript.ScriptName & ".log"
Set objLogFile = objfs.OpenTextFile(strLogFilePath, ForAppending, True)
objLogFile.WriteLine strMessage
objLogFile.close
Err.clear
On Error GoTo 0
Err.clear
End Sub
```
* * *
Find more IT Infrastructure tips at [blog.alexmags.com](http://blog.alexmags.com/)