VDA update – 7.7 to 7.8 – Unable to install ICATS_x64 [XDML :611b8615 ]

during XD 7.8 vda update, we’ve a “Failure to install VDA”, looking in the log files we saw:
– erreur 1603 lors de l’installation de ICATS_x64
Investigating in the ICATS_x64 MSi log files we found the error entry
– Product: Citrix HDX TS (retail) — Error 1402. Could not open key: HKEY_LOCAL_MACHINE32\SOFTWARE\Citrix\EUEM\LoggedEvents. System error 5. Verify that you have sufficient access to that key, or contact your support personnel.

Ok, let’s check this key then

loggedevents
autorisation

So we need to change the ownership of keys HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\EUEM, and as we do not have only one VDA, we want to script it.
We found a script to change registry hive owership on stackoverflow http://stackoverflow.com/questions/12044432/how-do-i-take-ownership-of-a-registry-key-via-powershell . Following the advise of Axel Limousin, we use Well knows SIDs ( https://support.microsoft.com/fr-fr/kb/243330 ) in our script in place of “local language” group and user names. Please note, after VDA update, hive permissions are reseted by the install, so you should re-run this script.

invoke-command -computername $computers -ScriptBlock {
function Take-Permissions {
    # Developed for PowerShell v4.0
    # Required Admin privileges
    # Links:
    #   http://shrekpoint.blogspot.ru/2012/08/taking-ownership-of-dcom-registry.html
    #   http://www.remkoweijnen.nl/blog/2012/01/16/take-ownership-of-a-registry-key-in-powershell/
    #   https://powertoe.wordpress.com/2010/08/28/controlling-registry-acl-permissions-with-powershell/

    param($rootKey, $key, [System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545', $recurse = $true)

    switch -regex ($rootKey) {
        'HKCU|HKEY_CURRENT_USER'    { $rootKey = 'CurrentUser' }
        'HKLM|HKEY_LOCAL_MACHINE'   { $rootKey = 'LocalMachine' }
        'HKCR|HKEY_CLASSES_ROOT'    { $rootKey = 'ClassesRoot' }
        'HKCC|HKEY_CURRENT_CONFIG'  { $rootKey = 'CurrentConfig' }
        'HKU|HKEY_USERS'            { $rootKey = 'Users' }
    }

    ### Step 1 - escalate current process's privilege
    # get SeTakeOwnership, SeBackup and SeRestore privileges before executes next lines, script needs Admin privilege
    $import = '[DllImport("ntdll.dll")] public static extern int RtlAdjustPrivilege(ulong a, bool b, bool c, ref bool d);'
    $ntdll = Add-Type -Member $import -Name NtDll -PassThru
    $privileges = @{ SeTakeOwnership = 9; SeBackup =  17; SeRestore = 18 }
    foreach ($i in $privileges.Values) {
        $null = $ntdll::RtlAdjustPrivilege($i, 1, 0, [ref]0)
    }

    function Take-KeyPermissions {
        param($rootKey, $key, $sid, $recurse, $recurseLevel = 0)

        ### Step 2 - get ownerships of key - it works only for current key
        $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')
        $acl = New-Object System.Security.AccessControl.RegistrySecurity
        $acl.SetOwner($sid)
        $regKey.SetAccessControl($acl)

        ### Step 3 - enable inheritance of permissions (not ownership) for current key from parent
        $acl.SetAccessRuleProtection($false, $false)
        $regKey.SetAccessControl($acl)
		        ### Step 4 - only for top-level key, change permissions for current key and propagate it for subkeys
        # to enable propagations for subkeys, it needs to execute Steps 2-3 for each subkey (Step 5)
        if ($recurseLevel -eq 0) {
            $regKey = $regKey.OpenSubKey('', 'ReadWriteSubTree', 'ChangePermissions')
            $rule = New-Object System.Security.AccessControl.RegistryAccessRule($sid, 'FullControl', 'ContainerInherit', 'None', 'Allow')
            $acl.ResetAccessRule($rule)
            $regKey.SetAccessControl($acl)
        }

        ### Step 5 - recursively repeat steps 2-5 for subkeys
        if ($recurse) {
            foreach($subKey in $regKey.OpenSubKey('').GetSubKeyNames()) {
                Take-KeyPermissions $rootKey ($key+'\'+$subKey) $sid $recurse ($recurseLevel+1)
            }
        }
    }

    Take-KeyPermissions $rootKey $key $sid $recurse
}

Take-Permissions HKLM SOFTWARE\Wow6432Node\Citrix\EUEM S-1-5-32-544 $true

cd HKLM:\Software\Wow6432Node\citrix\EUEM
$acl = get-acl LoggedEvents
$nrule = New-Object System.Security.AccessControl.RegistryAccessRule([System.Security.Principal.SecurityIdentifier]"S-1-5-20", 'FullControl', 'ContainerInherit', 'None', 'Allow')
$acl.setAccessRule($nrule)
$lrule = New-Object System.Security.AccessControl.RegistryAccessRule([System.Security.Principal.SecurityIdentifier]"S-1-5-18", 'FullControl', 'ContainerInherit', 'None', 'Allow')
$acl.setAccessRule($lrule)
$urule = New-Object System.Security.AccessControl.RegistryAccessRule( [System.Security.Principal.SecurityIdentifier]"S-1-5-32-555", 'FullControl', 'ContainerInherit', 'None', 'Allow')
$acl.setAccessRule($urule)
set-acl LoggedEvents $acl
}