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 www.alexmags.com

Leave a Reply