A Case Study

In today’s enterprise environments, organizations frequently use a combination of management tools to oversee their device fleets. One such combination is Microsoft’s System Center Configuration Manager (SCCM) and Microsoft Intune. This dual approach is often referred to as Co-management, where workloads can be distributed between SCCM and Intune according to the organization’s needs.

The Scenario

A recent case involved a customer experiencing issues due to the coexistence of

SCCM and Intune. All workloads were managed by Intune, yet the SCCM agent remained active. This scenario generated numerous complications that necessitated a streamlined solution.

Issues with SCCM Agent

The SCCM agent was causing myriad problems in the managed environment. These included:

  • Conflicts with Intune policies and configurations
  • Performance degradation of the devices
  • Network latency and bandwidth consumption

The customer’s primary objective was to remove the SCCM agent seamlessly without disrupting their ongoing operations. However, SCCM task sequences were still utilized to build machines due to specific network requirements that Autopilot could not fulfill.

Proposed Solution

To address the customer’s needs, a comprehensive script was developed to uninstall the SCCM agent post-task sequence execution. The script encompassed several critical steps:

  • Uninstalling the SCCM agent
  • Cleaning up associated folders and registry entries
  • Updating the externallymanaged registry key to zero
  • Triggering a synchronization task to ensure the device reports to Intune

Steps in Detail

1. Uninstall SCCM Agent: The uninstallation process started with stopping the SCCM services, then using the built-in uninstall command to remove the agent.

2. Cleanup Folders and Registry: Post-uninstallation, residual files and registry keys can cause conflicts. The script meticulously identified and deleted all SCCM-related folders and registry entries to ensure a clean removal.

3. Update Registry Key: The registry key externallymanaged was set to zero, indicating that the device is no longer managed by external software, thereby allowing Intune to take over fully.

4. Trigger Synchronization: Finally, a scheduled task was configured to run a synchronization script. This script ensured that the device connected to Intune and started reporting properly, completing the transition smoothly.

The Script

<# DISCLAIMER STARTS 

This Sample Code is provided for the purpose of illustration only and is not intended to be used in a #production environment.
THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" #WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO #THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

DISCLAIMER ENDS #>


<#
.COPYRIGHT

Copyright (c) Microsoft Corporation. All rights reserved.

.SYNOPSIS 

This script is created to uninstall SCCM agent from the machine and delete the registry keys and folders.

AUTHOR
Bindusar Kushwaha

Version 4.1

.EXAMPLE

.PARAMETER

#>

Function Write-Host()
{
    PARAM(
        [Parameter(Mandatory=$true)]$Message,
        $Info="Information"
         )
    [System.Diagnostics.EventLog]::WriteEntry("UninstallSMSAgent", "$Message", $Info, 100)
}

Function Write-Error()
{
    PARAM(
        [Parameter(Mandatory=$true)]$Message,
        $Info="Error"
         )
    [System.Diagnostics.EventLog]::WriteEntry("UninstallSMSAgent", "$Message", $Info, 101)
}

Write-Host "Script was triggered by $($env:UserName) on $($env:COMPUTERNAME) at $([System.DateTime]::Now)" -Info "Information"
Write-Host "This is used in GPO to uninstall SCCM Agent" -Info "Information"

# Uninstall SCCM Agent script (UninstallSCCM.ps1)
$ccmSetupPath = "$env:windir\ccmsetup\ccmsetup.exe"
$LogFile = "$env:windir\ccmsetup\Logs\ccmsetup.log"

#Copy SMSTS log file to C:\Windows\Temp
$SMSTSLog = "$env:windir\ccm\logs\smsts*.log"
$SMSTSLogDestination = "C:\Windows\Temp"
Copy-Item -Path $SMSTSLog -Destination $SMSTSLogDestination -Force

$matches.Clear() | Out-Null

Write-Host "Path for SCCM setup: $ccmSetupPath"
try
{
    If(Test-Path $ccmSetupPath)
    {
        Write-Host "Uninstalling SCCM Agent... Please wait..."
        Start-Process $ccmSetupPath -ArgumentList "/uninstall" -NoNewWindow

        # Monitor the ccmsetup.log for the exit code
        $ExitCode = $null
        while ($null -eq $ExitCode)
        {
            Start-Sleep -Seconds 5
            if (Test-Path $LogFile)
            {
                Write-host "Found Logfile at $LogFile"
                $LogContent = Get-Content -Path $LogFile -Tail 10
                foreach ($Line in $LogContent)
                {
                    Write-Host "Reading $Line"
                    if ($Line -match "return code (\d+)")
                    {
                        Write-Host "Found matching Value... Breaking the loop"
                        $ExitCode = $matches[0]
                        break
                    }
                }
            }
        }

        if ($ExitCode -eq "return code 0")
        {
            Write-Host "Successfully uninstalled SCCM agent with exit code: $ExitCode"

            try {
                # Delete the folder of the SCCM Client installation: "C:\Windows\CCM"
                Remove-Item -Path "$($Env:WinDir)\CCM" -Force -Recurse -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted CCM folder"
            } catch {
                Write-Error "Error occurred while deleting CCM folder: $_"
            }

            try {
                # Delete the folder of the SCCM Client Cache of all the packages and Applications that were downloaded and installed on the Computer: "C:\Windows\ccmcache"
                Remove-Item -Path "$($Env:WinDir)\CCMSetup" -Force -Recurse -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted CCMSetup folder"
            } catch {
                Write-Error "Error occurred while deleting CCMSetup folder: $_"
            }

            try {
                # Delete the folder of the SCCM Client Setup files that were used to install the client: "C:\Windows\ccmsetup"
                Remove-Item -Path "$($Env:WinDir)\CCMCache" -Force -Recurse -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted CCMCache folder"
            } catch {
                Write-Error "Error occurred while deleting CCMCache folder: $_"
            }

            try {
                # Delete the file with the certificate GUID and SMS GUID that current Client was registered with
                Remove-Item -Path "$($Env:WinDir)\smscfg.ini" -Force -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted smscfg.ini file"
            } catch {
                Write-Error "Error occurred while deleting smscfg.ini file: $_"
            }

            try {
                # Delete the certificate itself
                Remove-Item -Path 'HKLM:\Software\Microsoft\SystemCertificates\SMS\Certificates\*' -Force -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted SMS certificates"
            } catch {
                Write-Error "Error occurred while deleting SMS certificates: $_"
            }

            try {
                # Remove all the registry keys associated with the SCCM Client that might not be removed by ccmsetup.exe
                Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\CCM' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\CCM' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\SMS' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\SMS' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\Software\Microsoft\CCMSetup' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\Software\Wow6432Node\Microsoft\CCMSetup' -Force -Recurse -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted registry keys"
            } catch {
                Write-Error "Error occurred while deleting registry keys: $_"
            }

            try {
                #Check for externally managed Key. If it is 1, then change it to 0.
                $enrollmentKeyPath = 'HKLM:\SOFTWARE\Microsoft\Enrollments'
                $externallyManagedValue = Get-ItemProperty -Path $enrollmentKeyPath -Name 'ExternallyManaged' -ErrorAction Stop

                if ($externallyManagedValue.ExternallyManaged -eq 1) {
                    Set-ItemProperty -Path $enrollmentKeyPath -Name 'ExternallyManaged' -Value 0 -ErrorAction Stop
                    Write-Host "ExternallyManaged value changed to 0"
                } else {
                    Write-Host "ExternallyManaged value is already 0"
                }
            } catch {
                Write-Error "Error occurred while checking or updating ExternallyManaged value: $_"
            }

            try {
                # Remove the service from "Services"
                Remove-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\CcmExec' -Force -Recurse -ErrorAction Stop -Verbose
                Remove-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\ccmsetup' -Force -Recurse -ErrorAction Stop -Verbose
                Write-Host "Successfully deleted services"
            } catch {
                Write-Error "Error occurred while deleting services: $_"
            }

            try {
                # Remove the Namespaces from the WMI repository
                Get-CimInstance -query "Select * From __Namespace Where Name='CCM'" -Namespace "root" | Remove-CimInstance -Verbose -ErrorAction Stop
                Get-CimInstance -query "Select * From __Namespace Where Name='CCMVDI'" -Namespace "root" | Remove-CimInstance -Verbose -ErrorAction Stop
                Get-CimInstance -query "Select * From __Namespace Where Name='SmsDm'" -Namespace "root" | Remove-CimInstance -Verbose -ErrorAction Stop
                Get-CimInstance -query "Select * From __Namespace Where Name='sms'" -Namespace "root\cimv2" | Remove-CimInstance -Verbose -ErrorAction Stop
                Get-CimInstance -query "Select * From __Namespace Where Name='sms'" -Namespace "root\ccm" | Remove-CimInstance -Verbose -ErrorAction Stop #need to verify this
                Write-Host "Successfully deleted WMI namespaces"
            } catch {
                Write-Error "Error occurred while deleting WMI namespaces: $_"
            }

        }
        else
        {
            Write-Error "Uninstallation failed with exit code: $ExitCode"
            exit 1
        }
    }
    else
    {
        Write-Host "SCCM Agent is not installed on this machine"
        exit 0
    }
}
catch {
    Write-Error "Error occurred while uninstalling SCCM Agent"
    Write-Error $_.Exception.Message
}


# Script to delete registry keys
Try
{
    Write-Host "Deleting registry keys..."
    #Delete registry keys
    Remove-Item -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SCCM" -Recurse -Force | Out-Null
    Remove-Item -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SMS" -Recurse -Force | Out-Null
    Remove-Item -Path "HKLM:\software\Microsoft\ccm" -Recurse -Force| Out-Null
    Remove-Item -Path "HKLM:\software\Microsoft\CCMSETUP" -Recurse -Force | Out-Null
    Remove-Item -Path "HKLM:\software\Microsoft\SMS" -Recurse -Force | Out-Null
    Remove-Item -Path "HKLM:\software\Microsoft\Systemcertificates\SMS\Certificates" -Recurse -Force | Out-Null

    #Delete registry key
    Remove-ItemProperty -Path "HKLM:\Software\Microsoft\DeviceManageabilityCSP\Provider\WMI_Bridge_Server" -Name "ConfigInfo" -Force | Out-Null

    Write-Host "Registry keys deleted successfully"
}
catch
{
    Write-Error "Error occurred while deleting registry keys"
    Write-Error $_.Exception.Message
}

#Delete folders from following locations
Try
{
    Write-Host "Deleting folders..."
    Remove-Item -Path "C:\Windows\ccm" -Recurse -Force | Out-Null
    Remove-Item -Path "C:\Windows\ccmcache" -Recurse -Force | Out-Null
    Remove-Item -Path "C:\Windows\ccmsetup" -Recurse -Force | Out-Null
    Remove-Item -Path "C:\Windows\smscfg.ini" -Force | Out-Null

    Write-Host "Folders deleted successfully"
}
catch
{
    Write-Error "Error occurred while deleting folders"
    Write-Error $_.Exception.Message
}

# Detect Intune Sync Button and Trigger Sync only if mmpcenrollmentflag registry does not exist with value 0
Try
{
    $mmpcEnrollmentFlagPath = 'HKLM:\SOFTWARE\Microsoft\Enrollments'
    $mmpcEnrollmentFlagValue = Get-ItemProperty -Path $mmpcEnrollmentFlagPath -Name 'mmpcenrollmentflag' -ErrorAction SilentlyContinue

    while ($null -eq $mmpcEnrollmentFlagValue -or $mmpcEnrollmentFlagValue.mmpcenrollmentflag -ne 0)
    {
        Write-Host "Checking Intune Sync status..."
        $syncStatus = Get-ScheduledTask | ? {$_.TaskName -eq 'PushLaunch'}

        if ($syncStatus -ne $null)
        {
            Write-Host "Intune Sync task found. Triggering sync..."
            Get-ScheduledTask | ? {$_.TaskName -eq 'PushLaunch'} | Start-ScheduledTask
            Write-Host "Intune Sync triggered successfully"
            Start-Sleep -Seconds 120
        }
        else
        {
            Write-Error "Intune Sync task not found"
        }

        # Re-check the mmpcenrollmentflag value
        $mmpcEnrollmentFlagValue = Get-ItemProperty -Path $mmpcEnrollmentFlagPath -Name 'mmpcenrollmentflag' -ErrorAction SilentlyContinue
    }

    Write-Host "mmpcenrollmentflag registry exists with value 0. Exiting script."
    exit 0
}
catch
{
    Write-Error "Error occurred while checking or triggering Intune Sync"
    Write-Error $_.Exception.Message
    exit 1
}

Conclusion

This case illustrates the complexities involved in managing co-managed environments and the importance of a well-planned transition strategy. By developing a targeted script to remove the SCCM agent and ensuring all necessary cleanup and synchronization steps were followed, the customer’s devices could successfully transition to being fully managed by Intune, enhancing performance and reducing conflicts.

Leave a comment

I’m Bindusar

Welcome to BINLABS, my cozy corner of the internet dedicated to IT admins and their daily encounter. Here, I invite you to join me for daily challenges with solution faced by admins using scripts. Let’s script together!

Let’s connect