MECM: clean uninstall

Just another Tech site

MECM: clean uninstall

Trying to clean up MECM clients that have failed to get updated or have corrupt installs

 


<#
    MECM Full Removal Script
    - Graceful uninstall (if possible)
    - Forced cleanup of all MECM components
    - Logging to file
    - Summary report at end
#>

# ============================
# Logging + Summary Functions
# ============================

$Global:LogFile = "C:\Windows\Temp\MECM_Removal_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$Global:Summary = @()

function Write-Log {
    param(
        [string]$Message,
        [string]$Level = "INFO"
    )

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $entry = "[$timestamp] [$Level] $Message"

    Write-Host $entry
    Add-Content -Path $Global:LogFile -Value $entry
}

function Add-Summary {
    param([string]$Message)
    $Global:Summary += $Message
}

# ============================
# MECM Uninstall Function
# ============================

function Uninstall-MECM {
    $ccmSetup = "$Env:SystemDrive\Windows\ccmsetup\ccmsetup.exe"

    if (Test-Path $ccmSetup) {
        Write-Log "Stopping MECM services..."
        Stop-Service CcmExec -Force -ErrorAction SilentlyContinue
        Stop-Service ccmsetup -Force -ErrorAction SilentlyContinue

        Write-Log "Running MECM uninstaller..."
        Add-Summary "Started MECM uninstall"

        Start-Process -FilePath $ccmSetup -ArgumentList "/uninstall" -Wait

        Write-Log "Waiting for ccmsetup.exe to fully exit..."
        Wait-Process -Name ccmsetup -ErrorAction SilentlyContinue

        Write-Log "MECM uninstall completed."
        Add-Summary "MECM uninstall completed"
    }
    else {
        Write-Log "ccmsetup.exe not found — skipping uninstall." "WARN"
        Add-Summary "Uninstall skipped (ccmsetup.exe not found)"
    }
}

# ============================
# MECM Forced Removal Function
# ============================

function Remove-MECM {
    Write-Log "Beginning forced MECM cleanup..."
    Add-Summary "Forced cleanup started"

    Write-Log "Stopping MECM services..."
    Stop-Service CcmExec -Force -ErrorAction SilentlyContinue
    Stop-Service ccmsetup -Force -ErrorAction SilentlyContinue

    # Remove folders
    $folders = @(
        "$Env:WinDir\CCM",
        "$Env:WinDir\CCMSetup",
        "$Env:WinDir\CCMCache"
    )

    foreach ($folder in $folders) {
        if (Test-Path $folder) {
            Write-Log "Removing folder: $folder"
            takeown /F $folder /R /A /D Y | Out-Null
            Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue
            Add-Summary "Removed folder: $folder"
        }
        else {
            Write-Log "Folder not found: $folder" "WARN"
        }
    }

    # Remove smscfg.ini
    Write-Log "Removing smscfg.ini..."
    Remove-Item "$Env:WinDir\smscfg.ini" -Force -ErrorAction SilentlyContinue
    Add-Summary "Removed smscfg.ini"

    # Remove certificates
    Write-Log "Removing MECM certificates..."
    Remove-Item 'HKLM:\Software\Microsoft\SystemCertificates\SMS\Certificates\*' -Force -ErrorAction SilentlyContinue
    Get-ChildItem Cert:\LocalMachine\SMS -ErrorAction SilentlyContinue | Remove-Item -Force
    Add-Summary "Removed MECM certificates"

    # Registry keys
    $regKeys = @(
        'HKLM:\SOFTWARE\Microsoft\CCM',
        'HKLM:\SOFTWARE\Wow6432Node\Microsoft\CCM',
        'HKLM:\SOFTWARE\Microsoft\SMS',
        'HKLM:\SOFTWARE\Wow6432Node\Microsoft\SMS',
        'HKLM:\SOFTWARE\Microsoft\CCMSetup',
        'HKLM:\SOFTWARE\Wow6432Node\Microsoft\CCMSetup',
        'HKLM:\SYSTEM\CurrentControlSet\Services\CcmExec',
        'HKLM:\SYSTEM\CurrentControlSet\Services\ccmsetup'
    )

    foreach ($key in $regKeys) {
        Write-Log "Removing registry key: $key"
        Remove-Item -Path $key -Recurse -Force -ErrorAction SilentlyContinue
    }
    Add-Summary "Removed MECM registry keys"

    # Scheduled tasks
    Write-Log "Removing MECM scheduled tasks..."
    Get-ScheduledTask -TaskPath "\Microsoft\Configuration Manager\" -ErrorAction SilentlyContinue |
        Unregister-ScheduledTask -Confirm:$false
    Add-Summary "Removed MECM scheduled tasks"

    # WMI namespaces
    Write-Log "Removing MECM WMI namespaces..."
    $wmiNamespaces = @(
        @{ Namespace = "root"; Name = "CCM" },
        @{ Namespace = "root"; Name = "CCMVDI" },
        @{ Namespace = "root"; Name = "SmsDm" },
        @{ Namespace = "root\cimv2"; Name = "sms" }
    )

    foreach ($ns in $wmiNamespaces) {
        Write-Log "Removing WMI namespace: $($ns.Namespace)\$($ns.Name)"
        Get-CimInstance -Namespace $ns.Namespace -Query "SELECT * FROM __Namespace WHERE Name='$($ns.Name)'" -ErrorAction SilentlyContinue |
            Remove-CimInstance -ErrorAction SilentlyContinue

        Add-Summary "Removed WMI namespace: $($ns.Name)"
    }

    # WMI repair
    Write-Log "Verifying WMI repository..."
    $verify = (winmgmt /verifyrepository)
    if ($verify -notmatch "consistent") {
        Write-Log "WMI repository inconsistent — attempting repair..." "WARN"
        winmgmt /salvagerepository | Out-Null
        Add-Summary "WMI repository repaired"
    }
    else {
        Add-Summary "WMI repository verified healthy"
    }

    Write-Log "Forced MECM cleanup completed."
    Add-Summary "Forced cleanup completed"
}

# ============================
# Run Script
# ============================

Uninstall-MECM
Remove-MECM

# ============================
# Summary Report
# ============================

Write-Log "Generating summary report..."

$summaryHeader = "===== MECM Removal Summary ====="
Write-Host $summaryHeader
Add-Content -Path $Global:LogFile -Value $summaryHeader

foreach ($item in $Global:Summary) {
    Write-Host " - $item"
    Add-Content -Path $Global:LogFile -Value " - $item"
}

$summaryFooter = "===== End of Summary ====="
Write-Host $summaryFooter
Add-Content -Path $Global:LogFile -Value $summaryFooter

Write-Log "Summary report completed. Log saved to $Global:LogFile"