Wednesday, July 01, 2015

Citrix Receiver upgrade and double icon issue

I recently had to upgrade Citrix Receiver for one of my clients and I faced numerous issues during the install.
I had to enable SSO for Citrix Receiver and add a storefront URL so when the users launch Citrix Receiver they should be able to launch their apps store directly without going through login prompts and entering the url.

While Citrix Receiver can be installed with the following command:

CitrixReceiver.exe /silent /noreboot /includeSSON ENABLE_SSON=Yes ALLOWADDSTORE=N ALLOWSAVEPWD=S

And Store URL can be set in the ADM template of Citrix Receiver, however, you will need to uninstall the older version before you install the new one.

Other issues faced were for double icons which appeared on those users machines who had added an app store themselves in the previous version. When a new store was added through Group policy, it actually doubled the store and the icons.
The stores are created in the below registry key:
HKCU\Software\Citrix\Dazzle
When I removed this for the user and infact for all the users, it left behind dead icons in Start Menu, Desktop and in Citrix Receiver console. Also due to these dead icons, then I faced issues for Citrix stealing focus from all other applications.

Citrix suggests to use Citrix uninstall utility, but that works only when a logged on user runs it as an administrator which is rare in our environments.

I wrote following script to install, delete dead icons and remove the HKCU keys for all users of Citrix which are left behind.
You will Need:
1) Citrix Receiver
2) Receiver Cleanup Utility
to be in the same install  folder as these scripts.

Script 1

install.vbs

'Created: Piyush Nasa
'Date: 05-May-2015

Dim oExplorer
Dim oShell                   ' Windows Scripting Host shell
Dim oFSO                            ' File system object
Dim sCurDir, AppName, srd ' Script path
Dim sWinDir ' Windows root path
Dim scpf86, spf, strAppMsg, oEnv
dim strComputer, oReg, strKeyPath, strValueName, StringVal

'===========================================
' Main

'On Error Resume Next

Set oShell = CreateObject("WScript.Shell")

set oEnv = oShell.Environment("PROCESS")

oEnv("SEE_MASK_NOZONECHECKS") = 1

sCurDir = Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName, "\") - 1)

sWinDir = oShell.ExpandEnvironmentStrings ("%WinDir%")

const HKEY_LOCAL_MACHINE = &H80000002

'Check if previous version exists
'--------------------------------------

strComputer = "."

DIM fso  
Set fso = CreateObject("Scripting.FileSystemObject")

'Uninstall if anything left from Citrix
oShell.Run sCurDir & "\ReceiverCleanupUtility.exe /silent", 1, 1

'Uninstall Previous version

If (fso.FileExists("C:\ProgramData\Citrix\Citrix Receiver\TrolleyExpress.exe")) Then
  oShell.Run chr(34) & "C:\ProgramData\Citrix\Citrix Receiver\TrolleyExpress.exe" & chr(34) & " /Uninstall /Cleanup /silent", 1, 1
Else
  'Do Nothing
End If

'Uninstall if anything left from Citrix
oShell.Run sCurDir & "\ReceiverCleanupUtility.exe /silent", 1, 1

'Uninstall any Citrix Shortcuts left behind
oShell.Run sCurDir & "\DeleteShortcuts.vbs", 1, 1

'Uninstall Citrix keys in HKCU left behind
oShell.Run sCurDir & "\UninstallCitrixRegs.vbs", 1, 1

AppName = "Citrix Receiver 4.2.1"


' Install Citrix Receiver 4.2.1
oShell.Run sCurDir & "\CitrixReceiver.exe /silent /noreboot /includeSSON ENABLE_SSON=Yes ALLOWADDSTORE=N ALLOWSAVEPWD=S", 1, 1

oEnv.Remove("SEE_MASK_NOZONECHECKS")


'Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")

'strKeyPath = "SOFTWARE\\Applications\CitrixReceiver"

'strValueName = "Installed"
'StringVal = 1

'oReg.CreateKey HKEY_LOCAL_MACHINE,strKeyPath
'oReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,StringVal


Script 2.

DeleteShortcuts.vbs

On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set wshShell    = WScript.CreateObject("WScript.Shell")
'initialize logging
strLogFile = wshShell.ExpandEnvironmentStrings("%TEMP%\CitrixReceiverShortcutClean.log.txt")
Set objLogFile = objFSO.OpenTextFile(strLogFile, 8, True)
objLogFile.WriteLine Now & ": Logging Initialized"
'get list of folders in C:\Users
Set objFolder = objFSO.GetFolder("C:\Users")
objLogFile.WriteLine Now & ": Got list of user folders under C:\Users"
For Each UserSubFolder in objFolder.SubFolders
 'search the users start menu for Citrix shortcuts
'msgbox UserSubFolder.Path
 objStartFolder = UserSubFolder.Path & "\AppData\Roaming\Microsoft\Windows\Start Menu"
'msgbox objStartFolder
 objLogFile.WriteLine Now & ": Searching folder: " & objStartFolder
 Set objSearchFolder = objFSO.GetFolder(objStartFolder)
 Set colFiles = objSearchFolder.Files
 For Each objFile in colFiles
     If InStr(objFile.Name, ".lnk") Then
  IsCitrixShortcut objSearchFolder.Path & "\" & objFile.Name
     End If
 Next
 ShowSubfolders objFSO.GetFolder(objStartFolder)
 ' now search the users desktop for Citrix shortcuts
 objStartFolder = UserSubFolder.Path & "\Desktop"
 objLogFile.WriteLine Now & ": Searching folder: " & objStartFolder
 Set objSearchFolder = objFSO.GetFolder(objStartFolder)
 Set colFiles = objSearchFolder.Files
 For Each objFile in colFiles
     If InStr(objFile.Name, ".lnk") Then
  IsCitrixShortcut objSearchFolder.Path & "\" & objFile.Name
     End If
 Next
 ShowSubfolders objFSO.GetFolder(objStartFolder)
Next
objLogFile.WriteLine Now & ": Script complete"
Sub ShowSubFolders(Folder)

    For Each Subfolder in Folder.SubFolders
        Set objFolder = objFSO.GetFolder(Subfolder.Path)
        Set colFiles = objFolder.Files
        For Each objFile in colFiles

     If InStr(objFile.Name, ".lnk") Then

  IsCitrixShortcut SubFolder.Path & "\" & objFile.Name
     End If
        Next
        ShowSubFolders Subfolder
    Next
End Sub

Sub IsCitrixShortcut(strShortcut)
'msgbox strShortcut
 ' CreateShortcut works like a GetShortcut when the shortcut already exists!
 Set objShortcut2 = wshShell.CreateShortcut(strShortcut)
' WScript.Echo "Target Path       : " & objShortcut2.TargetPath

'WScript.Echo "Full Name         : " & objShortcut2.FullName
'WScript.Echo "Arguments         : " & objShortcut2.Arguments
'WScript.Echo "Working Directory : " & objShortcut2.WorkingDirectory
'WScript.Echo "Target Path       : " & objShortcut2.TargetPath
'WScript.Echo "Icon Location     : " & objShortcut2.IconLocation
'WScript.Echo "Hotkey            : " & objShortcut2.Hotkey
'WScript.Echo "Window Style      : " & objShortcut2.WindowStyle
'WScript.Echo "Description       : " & objShortcut2.Description




 If (InStr(objShortcut2.WorkingDirectory,"Citrix") Or InStr(objShortcut2.TargetPath,"Citrix")) Then
 'msgbox "found citrix"
 objLogFile.WriteLine Now & ": Deleting PNAgent Shortcut: " & strShortcut
If objFSO.FileExists (strShortcut) Then
  objFSO.DeleteFile strShortcut,True
'msgbox "File Deleted"
Else
'msgbox "File not found"
End If
 End If
End Sub


Script 3
UninstallCitrixRegs.vbs

'On Error Resume Next

Const HKEY_CURRENT_USER = &H80000001

Const HKU = &H80000003

strComputer = "."
strKeyPath = "Software\Citrix"
strKeyPath1 = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
sName = "SiteName" ' Change this to site in your environment from which it starts and has common string

Set objRegistry = GetObject("winmgmts:\\" & _
    strComputer & "\root\default:StdRegProv")
Set wmi = GetObject("winmgmts:\\.\root\cimv2")
Set reg = GetObject("winmgmts:\\.\root\default:StdRegProv")

Set profs = wmi.ExecQuery("Select SID from Win32_UserProfile where SID like 'S-1-5-21%'")
For Each prof In profs
  key = prof.SID & "\Software\Citrix"
DeleteSubkeys HKU, key

  key1 = prof.SID & "\" & strKeyPath1

EnumerateKeys HKU, key1


' Call reg.DeleteKey(HKU, key) 'commented out for safety
Next
'End If



Sub DeleteSubkeys(HKU, strKeyPath)
    objRegistry.EnumKey HKU, strKeyPath, arrSubkeys

    If IsArray(arrSubkeys) Then
        For Each strSubkey In arrSubkeys
            DeleteSubkeys HKU, strKeyPath & "\" & strSubkey
        Next
    End If

    objRegistry.DeleteKey HKU, strKeyPath
End Sub

Sub EnumerateKeys(hive, key)
  'WScript.Echo key
  objRegistry.EnumKey hive, key, arrSubKeys
  If Not IsNull(arrSubKeys) Then
    For Each skey In arrSubKeys
      EnumerateKeys hive, key & "\" & skey
      t=(InStr(skey,"sName"))
      If (t=1) Then
      'MsgBox skey
      DeleteSubkeys hive, key & "\" & skey
      End If
     
    Next
  End If
End Sub