Troubleshooting Desktop Analytics - Part 2

Profile picture for user PaulW

A few months ago, I wrote a post about troubleshooting desktop analytics as I had come across an issue getting it set up and the troubleshooting available was little and far between.  After working with an outstanding support representative from Microsoft, we discovered that my issue was rooted in poor group policy decisions that we made 2 years ago related to sending telemetry to Microsoft.  These group policies were rooted in not only machine settings but also user settings.

With how it is designed, if any user profile on the computer had telemetry disabled by the policy, it would block sending it to Microsoft.  Without telemetry working, Desktop Analytics would never fully configure.  After a full deployment, I had about 200 of my 3500 systems reporting into Desktop Analytics properly.  The others reported errors, so i had work ahead of me.

Once the policy is updated, there are 3 options to change/fix group policies in a users profile.  The first, is to, log into the computer with that user account.  The second option is to just delete the offending user profiles.  The third option, since policies are just registry settings, is to modify these registry settings in the user's registry hive.

So, being as non-destructive as possible, I chose option 3 to clean up the policies on the user profiles that were blocking telemetry from running.  Within a few weeks, I had over 90% of my systems properly reporting into Desktop Analytics.

Update-TelemetryPolicy.ps1

So..... Here is my script and what it does.

  1. Checks the registry for any profiles that are blocking DA.  The profiles are listed in this registry key:  HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\Users\
  2. Loads the user's hive into the registry and then removes the policy settings from the hive.
  3. Deletes the profile from the key above as that is not automatically cleaned up.
  4. Repeats these steps for any user profile that is listed in the above registry key.
  5. Logs profiles it finds and cleans up to C:\Windows\Logs\Software\Update-TelemetryPolicy.log.
function Write-Log {
    [CmdletBinding()] 
    Param (
        [Parameter(Mandatory = $false)]
        $Message,
 
        [Parameter(Mandatory = $false)]
        $ErrorMessage,
 
        [Parameter(Mandatory = $false)]
        $Component,
 
        [Parameter(Mandatory = $false, HelpMessage = "1 = Normal, 2 = Warning (yellow), 3 = Error (red)")]
        [ValidateSet(1, 2, 3)]
        [int]$Type,
		
        [Parameter(Mandatory = $false, HelpMessage = "Size in KB")]
        [int]$LogSizeKB = 512,

        [Parameter(Mandatory = $true)]
        $LogFile
    )
    <#
    Type: 1 = Normal, 2 = Warning (yellow), 3 = Error (red)
    #>
    Write-Verbose -Message $Message
    If ($ErrorMessage) { Write-Verbose -Message $ErrorMessage }
    Try {
        IF (!(Test-Path ([System.IO.DirectoryInfo]$LogFile).Parent.FullName)) {
            New-Item -ItemType directory -Path ([System.IO.DirectoryInfo]$LogFile).Parent.FullName
        }
    }
    Catch {
        Throw 'Failed to find/set parent directory path'
    }
    $LogLength = $LogSizeKB * 1024
    try {
        $log = Get-Item $LogFile -ErrorAction Stop
        If (($log.length) -gt $LogLength) {
            $Time = Get-Date -Format "HH:mm:ss.ffffff"
            $Date = Get-Date -Format "MM-dd-yyyy"
            $LogMessage = "<![LOG[Closing log and generating new log file" + "]LOG]!><time=`"$Time`" date=`"$Date`" component=`"$Component`" context=`"`" type=`"1`" thread=`"`" file=`"`">"
            $LogMessage | Out-File -Append -Encoding UTF8 -FilePath $LogFile
            Move-Item -Path "$LogFile" -Destination "$($LogFile.TrimEnd('g'))_" -Force
        }
    }
    catch { Write-Verbose "Nothing to move or move failed." }

    $Time = Get-Date -Format "HH:mm:ss.ffffff"
    $Date = Get-Date -Format "MM-dd-yyyy"
 
    if ($ErrorMessage -ne $null) { $Type = 3 }
    if ($Component -eq $null) { $Component = " " }
    if ($Type -eq $null) { $Type = 1 }
 
    $LogMessage = "<![LOG[$Message $ErrorMessage" + "]LOG]!><time=`"$Time`" date=`"$Date`" component=`"$Component`" context=`"`" type=`"$Type`" thread=`"`" file=`"`">"
    $LogMessage | Out-File -Append -Encoding UTF8 -FilePath $LogFile
}

#$Items = get-item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\Users\*'|where {$_.Property.AllowTelemetry -eq 3}

$PSDefaultParameterValues["Write-Log:LogFile"] = "C:\Windows\Logs\Software\Update-TelemetryPolicy.log"
$PSDefaultParameterValues["Write-Log:Verbose"] = $false


$TempHive = 'TempUser'
Write-Log "******************Beginning Telemetry User Blocking Evaluation******************"
Write-Log "Getting all users from registry that are blocking telemetry."
$BlockingUsers = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\Users\*'
Write-Log "Getting all user profiles on this machine."
$MachineUserProfiles = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*'
Write-Log "Getting all user profile hives already loaded on this machine."
$LoadedHives = Get-ChildItem -Path 'Microsoft.PowerShell.Core\Registry::HKEY_USERS' | Where-Object { $_.PSChildName -notlike "*_classes" }
Write-Log "looping through all of the blocking users [$($BlockingUsers.count)]."
Foreach ($user in $BlockingUsers) {
    $UserSid = $User.PSChildName
    Write-Log "Processing user with following SID [$UserSid]."
    If ($User.AllowTelemetry -eq 0) {
        Write-Log "Searching Machine Profiles for user that matches the SID of the blocking user [$UserSid]."
        Foreach ($Profile in $MachineUserProfiles) {
            If ($Profile.PSChildName -eq $UserSid) {
                Write-Log "Found Machine Profile that matches the SID of the blocking user [$UserSid]."
                If ($Profile.PSChildName -in ($LoadedHives.PSChildName)) {
                    Write-Log "Profile matches that of one of the already loaded registry hive files.  No need to load a hive."
                    IF (!([string]::IsNullOrEmpty((Get-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection" -ErrorAction Ignore).AllowTelemetry))) {
                        Write-Log "AllowTelemetry Value found in [HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection]"
                        try {
                            Remove-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection" -Name 'AllowTelemetry'
                            Write-Log "Successfully removed AllowTelemetry value from HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection"
                        }
                        Catch {
                            Write-Log "Failed to remove AllowTelemetry value from HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection" -Type 3
                            Write-Log "Exception: $($_.Exception.Message) Reason: $($_.CategoryInfo.Reason)" -Type 3
                        }
                    }
                    Else {
                        Write-Log "AllowTelemetry Value Not Found in [HKEY_USERS\$($Profile.PSChildName)\Software\Policies\Microsoft\Windows\DataCollection]" -Type 2
                    }
                }
                else {
                    REG.EXE LOAD HKU\$TempHive "$($Profile.ProfileImagePath)\NTUSER.DAT"
                    If (Test-Path -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$TempHive\Software\Policies\Microsoft\Windows") {
                        Write-Log "Loaded user hive for [$($Profile.PSChildName)] into [HKEY_USERS\$TempHive] successfully."
                        try {
                            Remove-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$TempHive\Software\Policies\Microsoft\Windows\DataCollection" -Name 'AllowTelemetry'
                            Write-Log "Successfully removed AllowTelemetry value from HKEY_USERS\$TempHive\Software\Policies\Microsoft\Windows\DataCollection"
                        }
                        Catch {
                            Write-Log "failed to remove AllowTelemetry value from HKEY_USERS\$TempHive\Software\Policies\Microsoft\Windows\DataCollection" -Type 3
                            Write-Log "Exception: $($_.Exception.Message) Reason: $($_.CategoryInfo.Reason)" -Type 3
                        }
                    }
                    else {
                        Write-Log "Failed to load Hive into temporary space." -Type 3
                    }
                    REG.EXE UNLOAD HKU\$TempHive
                    If (!(Test-Path -Path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$TempHive\Software")) {
                        Write-Log "Successfully Unloaded user hive for [$($Profile.PSChildName)] out of [HKEY_USERS\$TempHive]"
                    }
                    else {
                        Write-Log "Failed to Unloaded user hive for [$($Profile.PSChildName)] out of [HKEY_USERS\$TempHive]" -Type 3
                    }
                }
            }
        }
    }
    Write-Log "Removing Telemetry collected blocking user [$($User.PSPath)]"
    try {
        Remove-Item -Path "$($User.PSPath)" -Force
        Write-Log "Successfully removed Telemetry Collected blocking user [$($User.PSPath)]"
    }
    Catch {
        Write-Log "Error removing Telemetry Collected blocking user [$($User.PSPath)]" -Type 3
        Write-Log "Exception: $($_.Exception.Message) Reason: $($_.CategoryInfo.Reason)" -Type 3
    }
    Write-Log "Completed processing user with following SID [$UserSid]."
}
Write-Log "******************Completed Telemetry User Blocking Evaluation******************"

I set this up as a Package/Program in CM and ran it on a daily schedule.  Could also set it up as a baseline too.  Either will work.

Script is also here on Github.

Hope this helps someone else out.  Enjoy!

Comments

Thanks. I am going to try this out.  I am having similar issues with thousands of clients stuck with "End user disabled Windows Diagnostic data on device" even thought all of the user and computers allowtelemetry gpo and and sccm telemetry settings are applied correctly. All of the other desktop analytic checks are passing and It was working before but we did some GPO cleanup and haven't been able to figure out. I will let you know the results.

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.