613 lines
23 KiB
PowerShell
613 lines
23 KiB
PowerShell
<#
|
|
|
|
.Description
|
|
Script to remove SCCM agent from PCs
|
|
|
|
Completly based on James Chambers and Chad Simmons powershell scripts to remove the SCCM agent.
|
|
Updated with other scripts and testing.
|
|
|
|
$ccmpath is path to SCCM Agent's own uninstall routine.
|
|
|
|
.Notes
|
|
|
|
Script created or based on the following:
|
|
|
|
Source: https://github.com/robertomoir/remove-sccm/blob/master/remove-sccmagent.ps1
|
|
Source: https://www.optimizationcore.com/deployment/sccm-client-complete-remove-uninstall-powershell-script/
|
|
Source: https://jamesachambers.com/remove-microsoft-sccm-by-force/
|
|
Source: https://github.com/ChadSimmons/Scripts/blob/default/ConfigMgr/Troubleshooting/Remove-ConfigMgrClient.ps1
|
|
|
|
#>
|
|
|
|
#region Functions
|
|
|
|
function Test-IsAdmin {
|
|
<#
|
|
.SYNOPSIS
|
|
Checks if the current user has administrative privileges.
|
|
|
|
.DESCRIPTION
|
|
Function determines whether the current user has administrative privileges by attempting to create a new WindowsPrincipal object and checking the IsInRole method for the "Administrator" role.
|
|
If the check fails, it throws an exception indicating the lack of administrative privileges.
|
|
|
|
.EXAMPLE
|
|
Test-IsAdmin
|
|
If the current user has administrative privileges, the function completes without any output. If not, it throws an exception.
|
|
|
|
.NOTES
|
|
This function should be called at the beginning of scripts that require administrative privileges to ensure proper execution.
|
|
|
|
#>
|
|
|
|
try {
|
|
# Create a new WindowsPrincipal object for the current user
|
|
$currentUser = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
|
|
|
|
# Check if the current user is in the "Administrators" role
|
|
if (-not $currentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
throw "Script needs to run with Administrative privileges."
|
|
}
|
|
} catch {
|
|
throw "Must be run with Administrative priviliges."
|
|
}
|
|
}
|
|
|
|
function Stop-WinService {
|
|
<#
|
|
.SYNOPSIS
|
|
Stops a specified Windows service if it exists and is running.
|
|
|
|
.DESCRIPTION
|
|
Function checks if a specified Windows service exists and retrieves its status. If the service is running,
|
|
it attempts to stop it. Includes error handling to catch and throw any issues encountered, with specific messages
|
|
for services that do not exist.
|
|
|
|
.PARAMETER ServiceName
|
|
The name of the Windows service to stop.
|
|
|
|
.EXAMPLE
|
|
Stop-WinService -ServiceName "wuauserv"
|
|
Attempts to stop the Windows Update service if it exists and is running.
|
|
|
|
.NOTES
|
|
This function requires administrative privileges to stop Windows services.
|
|
#>
|
|
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$ServiceName
|
|
)
|
|
|
|
try {
|
|
# Check if the service exists
|
|
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
|
|
if ($null -eq $service) {
|
|
throw "Service '$ServiceName' does not exist."
|
|
}
|
|
|
|
# Check if the service is running
|
|
if ($service.Status -eq 'Running') {
|
|
# Attempt to stop the service
|
|
Write-Host "Stopping service '$ServiceName'..."
|
|
Stop-Service -Name $ServiceName -Force -ErrorAction Stop
|
|
Write-Host "Service '$ServiceName' stopped successfully."
|
|
} else {
|
|
Write-Host "Service '$ServiceName' is not running."
|
|
}
|
|
} catch {
|
|
throw "$_"
|
|
}
|
|
}
|
|
|
|
function Remove-RegKey {
|
|
<#
|
|
.SYNOPSIS
|
|
Deletes a specified registry key and its subkeys.
|
|
|
|
.DESCRIPTION
|
|
This function removes a specified registry key from the Windows Registry, including all its subkeys and values.
|
|
It includes error handling to catch and throw any issues encountered during the operation.
|
|
|
|
.PARAMETER RegKeyPath
|
|
The path of the registry key to delete.
|
|
|
|
.EXAMPLE
|
|
Remove-RegKey -RegKeyPath "HKLM:\SOFTWARE\MyApp"
|
|
Deletes the "MyApp" key and all its subkeys and values from the HKEY_LOCAL_MACHINE\SOFTWARE path.
|
|
|
|
.NOTES
|
|
This function requires administrative privileges to modify the Windows Registry.
|
|
#>
|
|
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$RegKeyPath
|
|
)
|
|
|
|
try {
|
|
# Check if the registry key exists
|
|
if (Test-Path -Path $RegKeyPath) {
|
|
# Attempt to remove the registry key
|
|
Write-Host "Removing registry key '$RegKeyPath'..."
|
|
Remove-Item -Path $RegKeyPath -Recurse -Force -Confirm:$false -ErrorAction Stop
|
|
Write-Host "Registry key '$RegKeyPath' removed successfully."
|
|
} else {
|
|
Write-Host "Registry key '$RegKeyPath' does not exist."
|
|
}
|
|
} catch {
|
|
throw "Error removing registry key '$RegKeyPath'"
|
|
}
|
|
}
|
|
|
|
function Clear-Files {
|
|
<#
|
|
.SYNOPSIS
|
|
Deletes specified files or folders, including subdirectories, and takes ownership if necessary.
|
|
|
|
.DESCRIPTION
|
|
This function iterates through an array of file paths, taking ownership of each file or directory and then deleting it.
|
|
It ensures both files and subdirectories are removed, handling any errors encountered during the process.
|
|
|
|
.PARAMETER FilePaths
|
|
An array of file paths to delete. These can be files or directories.
|
|
|
|
.EXAMPLE
|
|
$filesToDelete = @("C:\Temp\File1.txt", "C:\Temp\Folder1")
|
|
Clear-Files -FilePaths $filesToDelete
|
|
|
|
.NOTES
|
|
This function requires administrative privileges to take ownership and delete files or directories.
|
|
#>
|
|
param (
|
|
[string[]]$FilePaths
|
|
)
|
|
|
|
foreach ($FilePath in $FilePaths) {
|
|
try {
|
|
# Take ownership of the file or folder
|
|
$null = takeown.exe /F "$FilePath" /R /A /D Y 2>&1
|
|
|
|
# Delete the file or folder, including subdirectories
|
|
Remove-Item -Path $FilePath -Force -Recurse -ErrorAction Stop
|
|
|
|
Write-Host "Successfully deleted: $FilePath"
|
|
} catch {
|
|
Write-Host "Error deleting $($FilePath)"
|
|
}
|
|
}
|
|
}
|
|
|
|
function Remove-WmiNamespace {
|
|
<#
|
|
.SYNOPSIS
|
|
Removes a specified WMI namespace.
|
|
|
|
.DESCRIPTION
|
|
This function checks if a specified WMI namespace exists and removes it if found. It uses CIM (Common Information Model) cmdlets
|
|
to query and delete the WMI namespace. Errors are handled silently to ensure smooth execution.
|
|
|
|
.PARAMETER WmiName
|
|
The name of the WMI namespace to be removed.
|
|
|
|
.PARAMETER WmiNameSpace
|
|
The parent namespace where the specified WMI namespace resides.
|
|
|
|
.EXAMPLE
|
|
Remove-WmiNamespace -WmiName "ccm" -WmiNameSpace "root\ccm"
|
|
|
|
.NOTES
|
|
Ensure the script runs with administrative privileges to modify WMI namespaces.
|
|
|
|
.SOURCE
|
|
References:
|
|
- https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.1
|
|
- https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-powershell-cim-cmdlets?view=powershell-7.1
|
|
|
|
#>
|
|
param (
|
|
[string]$WmiName,
|
|
[string]$WmiNameSpace
|
|
)
|
|
|
|
try {
|
|
# Query for the specified WMI namespace
|
|
$WmiRepository = Get-CimInstance -query "SELECT * FROM __Namespace WHERE Name='$WmiName'" -Namespace "$WmiNameSpace" -ErrorAction SilentlyContinue
|
|
|
|
# Check if the namespace exists
|
|
if ($null -ne $WmiRepository) {
|
|
Write-Host "Found WMI Repository $WmiName, removing..."
|
|
|
|
# Remove the WMI namespace
|
|
Get-CimInstance -query "SELECT * FROM __Namespace WHERE Name='$WmiName'" -Namespace "$WmiNameSpace" | Remove-CimInstance -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
else {
|
|
Write-Host "WMI Repository $WmiName not found"
|
|
}
|
|
}
|
|
catch {
|
|
throw "Error udpating WMI namespace."
|
|
}
|
|
}
|
|
|
|
|
|
function Verify-SccmClientDelete {
|
|
<#
|
|
.SYNOPSIS
|
|
Verifies the deletion of the SCCM client by checking for the absence of specific services and files.
|
|
|
|
.DESCRIPTION
|
|
Checks if the SCCM (System Center Configuration Manager) client has been successfully deleted from the system.
|
|
It does this by verifying the absence of the SCCM client service (`CcmExec`) and the SCCM setup file (`ccmsetup.exe`).
|
|
If neither the service nor the setup file is found, the deletion is considered successful.
|
|
If either the service or the setup file still exists, appropriate warnings are issued, and the function sets an exit code indicating failure.
|
|
|
|
.PARAMETER None
|
|
|
|
.EXAMPLE
|
|
$exitCode = Verify-SccmClientDelete
|
|
Write-Host "Exit Code: $exitCode"
|
|
|
|
.NOTES
|
|
This function requires administrative privileges to check the existence of services and files.
|
|
Ensure that the script is run with appropriate permissions to avoid errors.
|
|
|
|
#>
|
|
# Variables to store the SCCM service name and file path
|
|
$SccmService = "CcmExec"
|
|
$SccmFilePath = "$Env:WinDir\ccmsetup\ccmsetup.exe"
|
|
$ExitCode = 0
|
|
|
|
try {
|
|
# Attempt to retrieve the SCCM service
|
|
$CCMexecService = Get-Service -Name $SccmService -ErrorAction SilentlyContinue
|
|
# Attempt to retrieve the SCCM setup file
|
|
$CCMexecSetupFile = Get-Item -Path $SccmFilePath -ErrorAction SilentlyContinue
|
|
|
|
# Check if both the service and the setup file do not exist
|
|
if (($null -eq $CCMexecService) -and ($null -eq $CCMexecSetupFile)) {
|
|
# SCCM Client deletion confirmed.
|
|
Write-Host "Confirmation. SCCM client service does not exist!"
|
|
}
|
|
else {
|
|
# Check if the SCCM service still exists
|
|
if ($null -ne $CCMexecService) {
|
|
# Set exit code for existing service
|
|
$ExitCode = 90 # 0x431 ERROR_SERVICE_EXISTS / The specified service already exists.
|
|
Write-Warning "Service $CCMexecService still exists, completing with failure $ExitCode"
|
|
}
|
|
|
|
# Check if the SCCM setup file still exists
|
|
if ($null -ne $CCMexecSetupFile) {
|
|
# Set exit code for existing file
|
|
$ExitCode = 91 # The specified file still exists.
|
|
Write-Warning "File $CCMexecSetupFile still exists, completing with failure $ExitCode"
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
# Handle any errors that occur during the check
|
|
throw "Error verifying SCCM client deletion."
|
|
}
|
|
|
|
# Return the exit code
|
|
return $ExitCode
|
|
}
|
|
|
|
function Start-CompleteIntuneSync {
|
|
<#
|
|
.SYNOPSIS
|
|
Initiates an Intune sync session and verifies its completion through Event Viewer logs.
|
|
|
|
.DESCRIPTION
|
|
This function performs an Intune sync by creating and starting an MDM session using Windows.Management.MdmSessionManager.
|
|
It waits for 60 seconds to allow the sync process to initiate. It then checks for specific events in the Event Viewer
|
|
to confirm the sync's start and completion: Looks for events 208 and 209 in the "Applications and Services Logs > Microsoft > Windows > DeviceManagement-Enterprise-Diagnostics-Provider > Admin".
|
|
The function returns the time these events were logged, or "Not found" if the events are not present.
|
|
|
|
The Journey:
|
|
Initial approach used `intunemanagementextension://syncapp` protocol as suggested by Jannik Reinhard's blog (https://jannikreinhard.com/2022/07/31/summary-of-the-intune-management-extension/). However, this method did not yield consistent results across different devices
|
|
Focus then shifted to leveraging the `Windows.Management.MdmSessionManager` class, known for managing Mobile Device Management (MDM) sessions. The use of `[Windows.Management.MdmSessionManager,Windows.Management,ContentType=WindowsRuntime]` to create and start an MDM session was adopted based on documentation and community blogs:
|
|
- https://oofhours.com/2024/03/30/when-does-a-windows-client-sync-with-intune/
|
|
|
|
Note: There was an initial attempt to use `Add-Type -AssemblyName "Windows.Management"` which resulted in an error indicating the assembly could not be found. This led to the realization that direct referencing and instantiation of the Windows Runtime type was necessary.
|
|
|
|
.REFERENCES
|
|
- "Intune Management Extension" by Jannik Reinhard: https://jannikreinhard.com/2022/07/31/summary-of-the-intune-management-extension/
|
|
- "When Does a Windows Client Sync with Intune?" by Michael Niehaus: https://oofhours.com/2024/03/30/when-does-a-windows-client-sync-with-intune/
|
|
|
|
.PARAMETER None
|
|
|
|
.EXAMPLE
|
|
Start-CompleteIntuneSync
|
|
|
|
.NOTES
|
|
This function requires administrative privileges to access Event Viewer logs.
|
|
Make sure to run this script with appropriate permissions.
|
|
#>
|
|
|
|
# Initialize variables for event checking
|
|
$eventLog = "Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin"
|
|
$syncStartEventID = 208
|
|
$syncCompleteEventID = 209
|
|
$syncStartTime = Get-Date
|
|
|
|
# Log the start of the sync attempt
|
|
Write-Host "Starting Intune sync at $syncStartTime"
|
|
|
|
try {
|
|
# Create and start the MDM session using Windows.Management.MdmSessionManager
|
|
[Windows.Management.MdmSessionManager,Windows.Management,ContentType=WindowsRuntime] > $null
|
|
$session = [Windows.Management.MdmSessionManager]::TryCreateSession()
|
|
$session.StartAsync() | Out-Null
|
|
|
|
# Wait for 60 seconds to allow the sync to initiate
|
|
Start-Sleep -Seconds 60
|
|
|
|
# Check for the sync start event in Event Viewer
|
|
$syncStartEvent = Get-WinEvent -LogName $eventLog | Where-Object { $_.Id -eq $syncStartEventID -and $_.TimeCreated -ge $syncStartTime }
|
|
if ($syncStartEvent) {
|
|
Write-Host "Sync start event (ID $syncStartEventID) found."
|
|
$syncStartEventTime = $syncStartEvent.TimeCreated
|
|
} else {
|
|
Write-Host "Sync start event (ID $syncStartEventID) not found."
|
|
$syncStartEventTime = "Not found"
|
|
}
|
|
|
|
# Check for the sync complete event in Event Viewer
|
|
$syncCompleteEvent = Get-WinEvent -LogName $eventLog | Where-Object { $_.Id -eq $syncCompleteEventID -and $_.TimeCreated -ge $syncStartTime }
|
|
if ($syncCompleteEvent) {
|
|
Write-Host "Sync complete event (ID $syncCompleteEventID) found."
|
|
$syncCompleteEventTime = $syncCompleteEvent.TimeCreated
|
|
} else {
|
|
Write-Host "Sync complete event (ID $syncCompleteEventID) not found."
|
|
$syncCompleteEventTime = "Not found"
|
|
}
|
|
|
|
# Return details of the sync process
|
|
return @{
|
|
SyncStartEvent = $syncStartEventTime
|
|
SyncCompleteEvent = $syncCompleteEventTime
|
|
SyncStartTime = $syncStartTime
|
|
}
|
|
} catch {
|
|
throw "Error during Intune sync process. "
|
|
}
|
|
}
|
|
|
|
function WriteAndExitWithSummary {
|
|
<#
|
|
.SYNOPSIS
|
|
Writes a summary of the script's execution to the console and then exits the script with a specified status code.
|
|
|
|
.DESCRIPTION
|
|
The function takes a status code and a summary string as parameters. It writes the summary along with the current date and time to the console using Write-Host.
|
|
After writing the summary, it exits the script with the given status code. If the given status code is below 0 (negative) it changes exit status code to 0.
|
|
|
|
.PARAMETER StatusCode
|
|
The exit status code to be used when exiting the script.
|
|
0: OK
|
|
1: FAIL
|
|
Other: WARNING
|
|
|
|
.PARAMETER Summary
|
|
The summary string that describes the script's execution status. This will be written to the console.
|
|
|
|
.EXAMPLE
|
|
WriteAndExitWithSummary -StatusCode 0 -Summary "All operations completed successfully."
|
|
|
|
.EXAMPLE
|
|
WriteAndExitWithSummary -StatusCode 1 -Summary "Error: SCCM client removal failed."
|
|
|
|
.NOTES
|
|
Last Modified: August 27, 2023
|
|
Author: Manuel Nieto
|
|
#>
|
|
|
|
param (
|
|
[int]$StatusCode,
|
|
[string]$Summary
|
|
)
|
|
|
|
# Combine the summary with the current date and time.
|
|
$finalSummary = "$([datetime]::Now) = $Summary"
|
|
|
|
# Determine the prefix based on the status code.
|
|
$prefix = switch ($StatusCode) {
|
|
0 { "OK" }
|
|
1 { "FAIL" }
|
|
default { "WARNING" }
|
|
}
|
|
|
|
# Easier to read in log file
|
|
Write-Host "`n`n"
|
|
|
|
# Write the final summary to the console.
|
|
Write-Host "$prefix $finalSummary"
|
|
|
|
# Easier to read in log file
|
|
Write-Host "`n`n"
|
|
|
|
# Exit the script with the given status code.
|
|
if ($StatusCode -lt 0) {$StatusCode = 0}
|
|
Exit $StatusCode
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Main
|
|
|
|
# Initialize
|
|
$Error.Clear() # Clear any previous errors.
|
|
$t = Get-Date # Get current date and time.
|
|
$CCMpath = "$Env:WinDir\ccmsetup\ccmsetup.exe" # Path to SCCM setup executable.
|
|
$verifyBeginResult # Variable to store beginning SCCM verification result.
|
|
$verifyEndResult # Variable to store ending SCCM verification result.
|
|
$summary = "" # Initialize summary string.
|
|
$StatusCode = 0 # Initialize status code to zero.
|
|
|
|
# New lines, easier to read Agentexecutor Log file.
|
|
Write-Host "`n`n"
|
|
#Log start time.
|
|
Write-Host "SCCM Agent cleanup start time: $t"
|
|
|
|
try {
|
|
#Test Admin rights
|
|
Test-IsAdmin
|
|
|
|
# Confirm if SCCM client is present.
|
|
$verifyBeginResult = Verify-SccmClientDelete
|
|
|
|
# Only execute if we have confirmation that SCCM client exists.
|
|
if ($verifyBeginResult -gt 0) {
|
|
|
|
# Stopping SCCM services.
|
|
try {
|
|
#Stop SCCM services.
|
|
Stop-WinService CcmExec
|
|
Stop-WinService ccmsetup
|
|
Stop-WinService smstsmgr
|
|
Stop-WinService CmRcService
|
|
$summary += "SCCM services stopped. "
|
|
} catch {
|
|
$summary += "Error stopping SCCM services: $_ "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
# Remove SCCM client.
|
|
try {
|
|
# Remove SCCM client.
|
|
if (Test-Path $CCMpath) {
|
|
Write-Host "Found $CCMpath, Uninstalling SCCM agent. `n"
|
|
#Start Uninstall, Included -WorkingDirectory to Start-Process cmdlet as Workaround to error when working directory has characters "[" "]"
|
|
Start-Process -WorkingDirectory $Env:WinDir -FilePath $CCMpath -ArgumentList "/uninstall" -Wait -NoNewWindow
|
|
# wait for exit
|
|
$CCMProcess = Get-Process ccmsetup -ErrorAction SilentlyContinue
|
|
try {
|
|
$CCMProcess.WaitForExit()
|
|
} catch {}
|
|
$summary += "SCCM client removed. "
|
|
}
|
|
else {
|
|
$summary += "SCCM client not found. "
|
|
}
|
|
} catch {
|
|
$summary += "Error removing SCCM client. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
# Removing services from registry
|
|
try {
|
|
# Remove Services from Registry.
|
|
$CurrentPath = "HKLM:\SYSTEM\CurrentControlSet\Services"
|
|
Remove-RegKey "$CurrentPath\CcmExec"
|
|
Remove-RegKey "$CurrentPath\CCMSetup"
|
|
Remove-RegKey "$CurrentPath\smstsmgr"
|
|
Remove-RegKey "$CurrentPath\CmRcService"
|
|
$summary += "SCCM services removed from registry. "
|
|
} catch {
|
|
$summary += "Error removing SCCM services from registry: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Remove SCCM Client from Registry
|
|
$CurrentPath = "HKLM:\SOFTWARE\Microsoft"
|
|
Remove-RegKey "$CurrentPath\CCM"
|
|
Remove-RegKey "$CurrentPath\CCMSetup"
|
|
Remove-RegKey "$CurrentPath\SMS"
|
|
$CurrentPath = "HKLM:\SOFTWARE\Wow6432Node\Microsoft"
|
|
Remove-RegKey "$CurrentPath\CCM"
|
|
Remove-RegKey "$CurrentPath\CCMSetup"
|
|
Remove-RegKey "$CurrentPath\SMS"
|
|
$summary += "SCCM client registry keys removed. "
|
|
} catch {
|
|
$summary += "Error removing SCCM client registry keys: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Remove WMI Namespaces
|
|
Remove-WmiNamespace "ccm" "root"
|
|
Remove-WmiNamespace "sms" "root\cimv2"
|
|
$summary += "SCCM WMI namespaces removed. "
|
|
} catch {
|
|
$summary += "Error removing SCCM WMI namespaces: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Reset MDM Authority
|
|
Write-Host "MDM Authority, reviewing and deleting registry key if necessary"
|
|
$CurrentPath = "HKLM:\SOFTWARE\Microsoft"
|
|
Remove-RegKey "$CurrentPath\DeviceManageabilityCSP"
|
|
$summary += "MDM authority reset. "
|
|
} catch {
|
|
$summary += "Error resetting MDM authority. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Remove Folders and Files
|
|
$CurrentPath = "$Env:WinDir"
|
|
Clear-Files "$CurrentPath\CCM"
|
|
Clear-Files "$CurrentPath\ccmsetup"
|
|
Clear-Files "$CurrentPath\ccmcache"
|
|
Clear-Files "$CurrentPath\SMSCFG.ini"
|
|
Clear-Files "$CurrentPath\SMS*.mif"
|
|
$summary += "SCCM related files and folders removed. "
|
|
} catch {
|
|
$summary += "Error removing SCCM files and folders: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Remove SCCM certificates
|
|
$CurrentPath = "HKLM:\SOFTWARE\Microsoft\SystemCertificates\SMS\Certificates"
|
|
Remove-RegKey "$CurrentPath\*"
|
|
$summary += "SCCM certificates removed. "
|
|
} catch {
|
|
$summary += "Error removing SCCM certificates: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
try {
|
|
# Confirm if SCCM client was removed.
|
|
$verifyEndResult = Verify-SccmClientDelete
|
|
if ($verifyEndResult -eq 0) {
|
|
$summary += "SCCM client removal verified. "
|
|
} else {
|
|
$StatusCode = $verifyEndResult
|
|
$summary += "SCCM client removal failed with code $verifyEndResult. "
|
|
}
|
|
} catch {
|
|
$summary += "Error verifying SCCM client removal: $_. "
|
|
$StatusCode = -2
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
catch {
|
|
# Log error and set status code to failure
|
|
$summary += "Execution Error: $_ "
|
|
$StatusCode = 1
|
|
}
|
|
|
|
# Perform Intune sync and log the result. Only if no errors.
|
|
if ($StatusCode -le 0) {
|
|
try {
|
|
$syncDetails = Start-CompleteIntuneSync
|
|
$summary += "Intune sync request: $($syncDetails.SyncStartTime), Start: $($syncDetails.SyncStartEvent), Completed: $($syncDetails.SyncCompleteEvent). "
|
|
} catch {
|
|
$summary += "Error during Intune sync. "
|
|
}
|
|
}
|
|
|
|
# Write the summary and exit with the appropriate status code
|
|
WriteAndExitWithSummary -StatusCode $StatusCode -Summary $summary
|
|
|
|
#Finished!
|
|
|
|
#endregion
|