Mandatory user profiles and AppV integration with Configuration Manager

There are a number of scenarios where an organisation may require that the user profiles on their workstations are not stored locally, for example if mandatory profiles are configured, or are deleted after the user logs off or VDI machines are in use and are not persistent.

When an organisation uses AppV integrated with Configuration Manager in this scenario it can lead to problems when deploying virtual applications to collections of users. If the user profile is returned to its mandatory state, or if it is deleted after logging off, the AppV files stored in the user profile are also deleted.

This proves problematic when the users eventually log back on to the machines, the shortcuts and part of the virtual applications are not available until the application deployment evaluation cycle runs, which is by default every 7 days.

PowerShell
Edit|Remove
Import-Module "C:\Program Files\Microsoft Application Virtualization\Client\AppvClient\AppvClient.psd1" 
 
# get user SIDs for all profiles 
$userSids = @(Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid" | foreach GetValue("SidString")) 
 
# get App-V 5x packages deployed to the client 
$appv5packages = Get-WmiObject -Namespace ROOT\ccm\CIModels -Class AppV5X_Install_Synclet ` 
    | Select-Object ContentFile,PackageName,PackageGuid,VersionGuid,UserConfigFile 
 
# for each App-V 5x package, re-publish for each user to which it's deployed 
foreach ($appv5package in $appv5packages) { 
 
    foreach ($userSid in $userSids) { 
 
        # get the policy namespace for the user 
        $actualConfigNamespace = "ROOT\ccm\Policy\" + $userSid.Replace("-","_") + "\ActualConfig" 
         
        # get app assignments for the user 
        $appAssignments = Get-WmiObject -Namespace $actualConfigNamespace -Class CCM_ApplicationCIAssignment ` 
            | Select-Object AssignmentId,AssignmentName 
 
        # for each app assignment, check whether it's one of the App-V packages 
        foreach ($appAssignment in $appAssignments) { 
 
            # assignment name starts with the package name 
            if ($appAssignment.AssignmentName.StartsWith($appv5package.PackageName)) {  
                 
                # WMI query filter for CacheInfoEx class 
                $wmiFilter = "ExcludeFileList = '" + $appv5package.ContentFile + "'" 
                 
                # get CacheInfoEx instances for the App-V package 
                $cacheInfos = Get-WmiObject -Namespace ROOT\ccm\SoftMgmtAgent -Class CacheInfoEx -Filter $wmiFilter ` 
                    | Select-Object Location,LastReferenced 
 
                # if none were found, move on to the next app assignment 
                if ($cacheInfos.Count -eq 0) { continue } 
 
                # store the Location and LastReferenced value of the first CacheInfoEx in the list 
                $cacheFolder = $cacheInfos[0].Location 
                $highVal = $cacheInfos[0].LastReferenced 
 
                # if there is more than one cache folder, use the most recent one 
                if ($cacheInfos.Count -gt 1) { 
 
                    foreach ($cacheInfo in $cacheInfos) { 
 
                        # if more recent than previous ones 
                        if ($cacheInfo.LastReferenced -gt $highVal) { 
                             
                            # store the Location and LastReferenced value of the more recent one 
                            $cacheFolder = $cacheInfo.Location 
                            $highVal = $cacheInfo.LastReferenced 
                        } 
                    } 
                } 
                
               # concat the cache folder and App-V package's user config file 
               $userConfigFile = $cacheFolder + "\" + $appv5package.UserConfigFile 
                
               # re-publish the package to the user  
               Publish-AppvClientPackage -PackageId $appv5package.PackageGuid ` 
                -VersionId $appv5package.VersionGuid ` 
                -DynamicUserConfigurationPath $userConfigFile ` 
                -UserSID $userSid                                                                               
            }  
        } 
    }  
}