EnhancedIntuneAO.psm1

#Region '.\Public\Check-IntuneCertificates.ps1' -1

function Check-IntuneCertificates {
    <#
    .SYNOPSIS
    Checks for the presence of certificates in the specified certificate store, issued by a specified issuer, within a given timeout period.
 
    .DESCRIPTION
    This function waits for up to a specified timeout for certificates to be created in the specified certificate store, looking specifically for certificates issued by the provided issuer name. It logs the waiting process and the outcome, successfully finding the certificates or timing out.
 
    .PARAMETER CertStorePath
    The path of the certificate store to check for certificates. Default is the local machine's personal certificate store.
 
    .PARAMETER IssuerName
    The name of the issuer to check for in the certificates. Default is "CN=Microsoft Intune MDM Device CA".
 
    .PARAMETER Timeout
    The maximum amount of time, in seconds, to wait for the certificates. Default is 30 seconds.
 
    .EXAMPLE
    Check-IntuneCertificates
    Checks for certificates issued by Microsoft Intune in the local machine's personal certificate store with the default timeout of 30 seconds.
 
    .EXAMPLE
    Check-IntuneCertificates -CertStorePath 'Cert:\LocalMachine\My\' -IssuerName "CN=Microsoft Intune MDM Device CA" -Timeout 60
    Checks for certificates with a custom timeout of 60 seconds in the specified certificate store and issuer.
 
    .NOTES
    Ensure that the 'Write-EnhancedLog' function is defined in your environment for logging.
    #>


    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false, HelpMessage = "Specify the certificate store path to check.")]
        [ValidateNotNullOrEmpty()]
        [string]$CertStorePath = 'Cert:\LocalMachine\My\',

        [Parameter(Mandatory = $false, HelpMessage = "Specify the issuer name to check.")]
        [ValidateNotNullOrEmpty()]
        [string]$IssuerName = "CN=Microsoft Intune MDM Device CA",

        [Parameter(Mandatory = $false, HelpMessage = "Specify the maximum time (in seconds) to wait for the certificate.")]
        [ValidateRange(1, 300)]
        [int]$Timeout = 30
    )

    Begin {
        Write-EnhancedLog -Message "Starting Check-IntuneCertificates function." -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
        Write-EnhancedLog -Message "Waiting for certificates from issuer: $IssuerName in store: $CertStorePath" -Level "INFO"
    }

    Process {
        try {
            $remainingTime = $Timeout

            # Loop to wait for the certificate to appear, or until the timeout is reached
            while ($remainingTime -gt 0) {
                try {
                    $certificates = Get-ChildItem -Path $CertStorePath | Where-Object { $_.Issuer -match $IssuerName }
                }
                catch {
                    Write-EnhancedLog -Message "Error accessing certificates in path: $CertStorePath. Error: $($_.Exception.Message)" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                    return
                }

                if ($certificates) {
                    Write-EnhancedLog -Message "Certificate(s) found for issuer: $IssuerName." -Level "INFO"
                    break
                }

                Write-EnhancedLog -Message "Waiting... ($remainingTime seconds remaining)" -Level "INFO"
                Start-Sleep -Seconds 1
                $remainingTime--
            }

            # Check if the loop ended due to timeout
            if ($remainingTime -eq 0) {
                Write-EnhancedLog -Message "Timed out waiting for certificate from issuer: $IssuerName in store: $CertStorePath" -Level "WARNING"
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred during the certificate check process. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return
        }
    }

    End {
        Write-EnhancedLog -Message "Check-IntuneCertificates function has completed." -Level "Notice"
    }
}
#EndRegion '.\Public\Check-IntuneCertificates.ps1' 92
#Region '.\Public\Check-RegistryKeys.ps1' -1

function Check-RegistryKeys {
    <#
    .SYNOPSIS
    Checks for specific registry keys under given GUIDs and outputs their subkeys and values.
 
    .DESCRIPTION
    The Check-RegistryKeys function searches the registry under "HKLM:\SOFTWARE\Microsoft\Enrollments" for specified GUIDs, checks for specific subkeys (DeviceEnroller, DMClient, Poll, Push), and lists all items within these subkeys as a table of key name and value pairs.
 
    .PARAMETER EnrollmentGUIDs
    The GUIDs under which to search for specific registry subkeys.
 
    .EXAMPLE
    Check-RegistryKeys -EnrollmentGUIDs @("GUID1", "GUID2")
    Searches for and lists details of specific registry subkeys under the specified GUIDs.
 
    .NOTES
    Ensure the 'Write-EnhancedLog' function is defined in your environment for logging.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Provide the Enrollment GUIDs to search for.")]
        [ValidateNotNullOrEmpty()]
        [string[]]$EnrollmentGUIDs
    )

    Begin {
        Write-EnhancedLog -Message "Starting registry key check for specified GUIDs." -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Base registry path
        $BaseKey = "HKLM:\SOFTWARE\Microsoft\Enrollments"
        Write-EnhancedLog -Message "Checking registry base path: $BaseKey" -Level "INFO"

        # Initialize an array to store the properties of found subkeys
        $allProperties = [System.Collections.Generic.List[PSCustomObject]]::new()
    }

    Process {
        foreach ($GUID in $EnrollmentGUIDs) {
            $GUIDPath = Join-Path -Path $BaseKey -ChildPath $GUID
            Write-EnhancedLog -Message "Processing GUID: $GUID" -Level "INFO"

            if (Test-Path -Path $GUIDPath) {
                Write-EnhancedLog -Message "Found registry path: $GUIDPath" -Level "INFO"
                
                try {
                    $SubKeys = Get-ChildItem -Path $GUIDPath -ErrorAction Stop

                    foreach ($SubKey in $SubKeys) {
                        if ($SubKey.Name -match "DeviceEnroller|DMClient|Poll|Push") {
                            $SubKeyProperties = Get-ItemProperty -Path $SubKey.PSPath

                            foreach ($Property in $SubKeyProperties.PSObject.Properties) {
                                # Add each property to the list as a custom object
                                $allProperties.Add([PSCustomObject]@{
                                    SubKeyName    = $SubKey.PSChildName
                                    PropertyName  = $Property.Name
                                    PropertyValue = $Property.Value
                                })
                            }
                        }
                        else {
                            Write-EnhancedLog -Message "No relevant subkeys (DeviceEnroller, DMClient, Poll, Push) found under $GUIDPath." -Level "WARNING"
                        }
                    }
                }
                catch {
                    Write-EnhancedLog -Message "Error retrieving subkeys for GUID $GUID. Error: $($_.Exception.Message)" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                }
            }
            else {
                Write-EnhancedLog -Message "GUID $GUID not found under $BaseKey." -Level "WARNING"
            }
        }
    }

    End {
        # Output all collected properties in a table
        if ($allProperties.Count -gt 0) {
            Write-EnhancedLog -Message "Displaying properties found in relevant subkeys." -Level "INFO"
            $allProperties | Format-Table -AutoSize
        }
        else {
            Write-EnhancedLog -Message "No relevant properties found under the specified GUIDs." -Level "WARNING"
        }

        Write-EnhancedLog -Message "Completed registry key check for specified GUIDs." -Level "Notice"
    }
}
#EndRegion '.\Public\Check-RegistryKeys.ps1' 92
#Region '.\Public\Check-TaskSchedulerEntriesAndTasks.ps1' -1

function Check-TaskSchedulerEntriesAndTasks {
    <#
    .SYNOPSIS
    Checks for scheduled tasks and their folders related to a specific Enrollment GUID.
 
    .DESCRIPTION
    The Check-TaskSchedulerEntriesAndTasks function lists all scheduled tasks under the Enterprise Management path that match the specified Enrollment GUID. It also checks for the existence of corresponding task folders.
 
    .PARAMETER EnrollmentGUID
    The GUID of the enrollment entries related to the tasks to be checked.
 
    .EXAMPLE
    Check-TaskSchedulerEntriesAndTasks -EnrollmentGUID "YourGUIDHere"
    Lists all scheduled tasks and checks folders under Enterprise Management that match the given GUID.
 
    .NOTES
    Uses Write-EnhancedLog for logging information.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Specify the Enrollment GUID.")]
        [ValidateNotNullOrEmpty()]
        [string]$EnrollmentGUID
    )

    Begin {
        Write-EnhancedLog -Message "Starting Check-TaskSchedulerEntriesAndTasks for GUID: $EnrollmentGUID" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Initialize Task Scheduler connection
        try {
            Write-EnhancedLog -Message "Connecting to Task Scheduler service." -Level "INFO"
            $taskScheduler = New-Object -ComObject Schedule.Service
            $taskScheduler.Connect()
        }
        catch {
            Write-EnhancedLog -Message "Failed to connect to Task Scheduler service. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return
        }
    }

    Process {
        Write-EnhancedLog -Message "Searching for scheduled tasks matching GUID: $EnrollmentGUID" -Level "INFO"

        # Search for tasks under the Task Scheduler
        try {
            $tasksFound = Get-ScheduledTask | Where-Object { $_.TaskPath -match $EnrollmentGUID }
            if ($tasksFound.Count -gt 0) {
                foreach ($task in $tasksFound) {
                    Write-EnhancedLog -Message "Found task: $($task.TaskName)" -Level "INFO"
                }
            }
            else {
                Write-EnhancedLog -Message "No tasks found for GUID: $EnrollmentGUID" -Level "WARNING"
            }
        }
        catch {
            Write-EnhancedLog -Message "Error while searching for tasks: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return
        }

        # Check for the existence of task folders
        $taskFolders = @(
            "$env:WINDIR\System32\Tasks\Microsoft\Windows\EnterpriseMgmt\$EnrollmentGUID",
            "$env:WINDIR\System32\Tasks\Microsoft\Windows\EnterpriseMgmtNoncritical\$EnrollmentGUID"
        )

        foreach ($taskFolder in $taskFolders) {
            if (Test-Path $taskFolder) {
                Write-EnhancedLog -Message "Found task folder at path: $taskFolder" -Level "INFO"
            }
            else {
                Write-EnhancedLog -Message "No task folder found at path: $taskFolder" -Level "WARNING"
            }
        }
    }

    End {
        Write-EnhancedLog -Message "Task Scheduler entry and folder check for GUID: $EnrollmentGUID completed." -Level "Notice"
    }
}
#EndRegion '.\Public\Check-TaskSchedulerEntriesAndTasks.ps1' 85
#Region '.\Public\Enable-MDMAutoEnrollment.ps1' -1

function Enable-MDMAutoEnrollment {
    <#
    .SYNOPSIS
    Enables MDM AutoEnrollment by creating necessary registry entries and invoking the enrollment process.
 
    .DESCRIPTION
    This function checks if the required registry key and property for MDM AutoEnrollment are present. If not, it creates them and invokes the device enrollment process using `deviceenroller.exe`.
 
    .NOTES
    Ensure the 'Write-EnhancedLog' function is defined for logging, and the `Check-IntuneCertificates` function is available for certificate verification after enrollment.
    #>


    [CmdletBinding()]
    Param()

    Begin {
        Write-EnhancedLog -Message "Starting MDM AutoEnrollment process." -Level "Notice"
    }

    Process {
        try {
            $registryPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\MDM"

            # Check if the registry key exists
            if (-not (Test-Path $registryPath)) {
                Write-EnhancedLog -Message "Creating registry key for MDM AutoEnrollment: $registryPath" -Level "INFO"
                New-Item -Path $registryPath -ErrorAction Stop | Out-Null
            }
            else {
                Write-EnhancedLog -Message "Registry key for MDM AutoEnrollment already exists. Skipping creation." -Level "INFO"
            }

            # Check if the AutoEnrollMDM property exists
            try {
                $propertyExists = [bool](Get-ItemProperty -Path $registryPath -Name AutoEnrollMDM -ErrorAction Stop)
            }
            catch {
                $propertyExists = $false
            }

            # Set the AutoEnrollMDM property if it doesn't exist
            if (-not $propertyExists) {
                Write-EnhancedLog -Message "Setting AutoEnrollMDM property in $registryPath." -Level "INFO"
                New-ItemProperty -Path $registryPath -Name AutoEnrollMDM -Value 1 -ErrorAction Stop | Out-Null
            }
            else {
                Write-EnhancedLog -Message "AutoEnrollMDM property already exists. Skipping." -Level "INFO"
            }

            # Invoke the device enrollment process
            Write-EnhancedLog -Message "Invoking device enrollment process with deviceenroller.exe." -Level "INFO"
            & "$env:windir\system32\deviceenroller.exe" /c /AutoEnrollMDM

            Write-EnhancedLog -Message "MDM AutoEnrollment process completed successfully." -Level "Success"
        }
        catch {
            Write-EnhancedLog -Message "An error occurred during the MDM AutoEnrollment process. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        Write-EnhancedLog -Message "MDM AutoEnrollment function has completed." -Level "Notice"

        # Optional post-check for certificates after enrollment
        Write-EnhancedLog -Message "Checking for Intune certificates post enrollment." -Level "INFO"
        Check-IntuneCertificates
    }
}

# Example invocation
# Enable-MDMAutoEnrollment
#EndRegion '.\Public\Enable-MDMAutoEnrollment.ps1' 73
#Region '.\Public\Get-ManagementGUID.ps1' -1

function Get-ManagementGUID {
    [CmdletBinding()]
    param (
        [string]$taskRoot = "\Microsoft\Windows\EnterpriseMgmt"
    )

    Begin {
        Write-EnhancedLog -Message "Starting Get-ManagementGUID function" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Initialize variables and objects
        try {
            Write-EnhancedLog -Message "Connecting to the Task Scheduler service." -Level "INFO"
            $taskScheduler = New-Object -ComObject Schedule.Service
            $taskScheduler.Connect()

            # Initialize a list to store collected GUIDs
            $EnrollmentGUIDs = [System.Collections.Generic.List[object]]::new()

            # Regular expression to validate GUID format
            $guidRegex = '^[{(]?[0-9A-Fa-f]{8}[-]?(?:[0-9A-Fa-f]{4}[-]?){3}[0-9A-Fa-f]{12}[)}]?$'
        }
        catch {
            Write-EnhancedLog -Message "Failed to connect to the Task Scheduler service. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return
        }
    }

    Process {
        Write-EnhancedLog -Message "Checking if the task root exists: $taskRoot" -Level "INFO"
        try {
            $rootFolder = $taskScheduler.GetFolder($taskRoot)
            if ($null -eq $rootFolder) {
                Write-EnhancedLog -Message "Task root '$taskRoot' does not exist." -Level "WARNING"
                return
            }

            Write-EnhancedLog -Message "Task root exists. Retrieving subfolders from the task root: $taskRoot" -Level "INFO"
            $subfolders = $rootFolder.GetFolders(0)
        }
        catch {
            if ($_.Exception.HResult -eq -2147024894) { # HRESULT for "The system cannot find the file specified"
                Write-EnhancedLog -Message "The task root '$taskRoot' does not exist or cannot be found." -Level "WARNING"
            } else {
                Write-EnhancedLog -Message "Failed to retrieve subfolders from '$taskRoot'. Error: $($_.Exception.Message)" -Level "ERROR"
                Handle-Error -ErrorRecord $_
            }
            return
        }

        foreach ($folder in $subfolders) {
            if ($folder.Name -match $guidRegex) {
                Write-EnhancedLog -Message "Valid GUID found: $($folder.Name)" -Level "INFO"
                try {
                    $EnrollmentGUIDs.Add($folder.Name)
                }
                catch {
                    Write-EnhancedLog -Message "Failed to add GUID: $($_.Exception.Message)" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                }
            }
            else {
                Write-EnhancedLog -Message "Skipping non-GUID folder: $($folder.Name)" -Level "INFO"
            }
        }
    }

    End {
        if ($EnrollmentGUIDs.Count -gt 0) {
            Write-EnhancedLog -Message "Successfully collected $($EnrollmentGUIDs.Count) GUID(s)." -Level "INFO"
            return $EnrollmentGUIDs
        }
        else {
            Write-EnhancedLog -Message "No GUIDs found in the task root '$taskRoot'." -Level "WARNING"
        }

        Write-EnhancedLog -Message "Completed Get-ManagementGUID function" -Level "Notice"
    }
}
#EndRegion '.\Public\Get-ManagementGUID.ps1' 81
#Region '.\Public\Perform-IntuneCleanup.ps1' -1

function Perform-IntuneCleanup {
    <#
    .SYNOPSIS
    Performs an Intune cleanup by removing MDM certificates, task scheduler entries, and registry keys associated with Intune enrollment GUIDs.
 
    .DESCRIPTION
    This function first checks for Intune-related certificates, removes MDM certificates, and cleans up task scheduler entries, registry keys, and associated GUIDs related to Intune. It also performs checks before and after the cleanup to verify that the cleanup was successful. Finally, it provides a summary report of the cleanup process.
 
    .NOTES
    Assumes that `Check-IntuneCertificates`, `Remove-MDMCertificates`, `Get-ManagementGUID`, `Check-RegistryKeys`, `Check-TaskSchedulerEntriesAndTasks`, `Remove-TaskSchedulerEntriesAndTasks`, and `Remove-RegistryEntries` are defined elsewhere in the script or module.
    #>


    [CmdletBinding()]
    param ()

    Begin {
        # Initialize counters and summary table
        $successCount = 0
        $warningCount = 0
        $errorCount = 0
        $summaryTable = [System.Collections.Generic.List[PSCustomObject]]::new()

        Write-EnhancedLog -Message "Starting Intune cleanup process." -Level "Notice"
    }

    Process {
        try {
            # Check for Intune-related certificates before removal.
            Write-EnhancedLog -Message "Checking for Intune certificates before removal." -Level "INFO"
            Check-IntuneCertificates

            # Define the parameters for certificate removal in a hashtable and call with splatting.
            $certParams = @{
                CertStorePath = 'Cert:\LocalMachine\My\'
                IssuerName    = "CN=Microsoft Intune MDM Device CA"
            }

            Write-EnhancedLog -Message "Removing MDM certificates." -Level "INFO"
            Remove-MDMCertificates @certParams

            # Check for Intune-related certificates after removal.
            Write-EnhancedLog -Message "Re-checking for Intune certificates after removal." -Level "INFO"
            Check-IntuneCertificates

            # Obtain the current management GUIDs.
            Write-EnhancedLog -Message "Retrieving enrollment GUIDs." -Level "INFO"
            $EnrollmentGUIDs = Get-ManagementGUID

            if ($EnrollmentGUIDs.Count -eq 0) {
                Write-EnhancedLog -Message "No enrollment GUIDs found. Exiting cleanup process." -Level "Warning"
                $warningCount++
                return
            }

            foreach ($EnrollmentGUID in $EnrollmentGUIDs) {
                Write-EnhancedLog -Message "Processing cleanup for enrollment GUID: $EnrollmentGUID" -Level "INFO"

                # Check registry keys before cleanup.
                Write-EnhancedLog -Message "Checking registry keys before cleanup for GUID: $EnrollmentGUID." -Level "INFO"
                Check-RegistryKeys -EnrollmentGUIDs @($EnrollmentGUID)

                # Check task scheduler entries before cleanup.
                Write-EnhancedLog -Message "Checking task scheduler entries for GUID: $EnrollmentGUID." -Level "INFO"
                Check-TaskSchedulerEntriesAndTasks -EnrollmentGUID $EnrollmentGUID

                # Remove task scheduler entries.
                Write-EnhancedLog -Message "Removing task scheduler entries for GUID: $EnrollmentGUID." -Level "INFO"
                Remove-TaskSchedulerEntriesAndTasks -EnrollmentGUID $EnrollmentGUID

                # Verify task scheduler entries after removal.
                Write-EnhancedLog -Message "Verifying task scheduler entries cleanup for GUID: $EnrollmentGUID." -Level "INFO"
                Check-TaskSchedulerEntriesAndTasks -EnrollmentGUID $EnrollmentGUID

                # Remove registry entries associated with the GUID.
                Write-EnhancedLog -Message "Removing registry entries for GUID: $EnrollmentGUID." -Level "INFO"
                Remove-RegistryEntries -EnrollmentGUID $EnrollmentGUID

                # Verify registry cleanup after removal.
                Write-EnhancedLog -Message "Verifying registry cleanup for GUID: $EnrollmentGUID." -Level "INFO"
                Check-RegistryKeys -EnrollmentGUIDs @($EnrollmentGUID)

                # Add success record to the summary table
                $summaryTable.Add([PSCustomObject]@{
                    EnrollmentGUID = $EnrollmentGUID
                    Status         = "Success"
                })
                $successCount++
            }

            Write-EnhancedLog -Message "Intune cleanup process completed." -Level "Success" -ForegroundColor Green
        }
        catch {
            Write-EnhancedLog -Message "An error occurred during the Intune cleanup process. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            $errorCount++
            $summaryTable.Add([PSCustomObject]@{
                EnrollmentGUID = $EnrollmentGUID
                Status         = "Failed"
            })
        }
    }

    End {
        # Final Summary Report
        Write-EnhancedLog -Message "----------------------------------------" -Level "INFO"
        Write-EnhancedLog -Message "Final Cleanup Summary Report" -Level "NOTICE"
        Write-EnhancedLog -Message "Total GUIDs processed: $($successCount + $warningCount + $errorCount)" -Level "INFO"
        Write-EnhancedLog -Message "Successfully processed GUIDs: $successCount" -Level "INFO"
        Write-EnhancedLog -Message "Warnings: $warningCount" -Level "WARNING"
        Write-EnhancedLog -Message "Failed GUIDs: $errorCount" -Level "ERROR"
        Write-EnhancedLog -Message "----------------------------------------" -Level "INFO"

        # Color-coded summary for the console
        Write-Host "----------------------------------------" -ForegroundColor White
        Write-Host "Final Intune Cleanup Summary Report" -ForegroundColor Cyan
        Write-Host "Total GUIDs processed: $($successCount + $warningCount + $errorCount)" -ForegroundColor White
        Write-Host "Successfully processed GUIDs: $successCount" -ForegroundColor Green
        Write-Host "Warnings: $warningCount" -ForegroundColor Yellow
        Write-Host "Failed GUIDs: $errorCount" -ForegroundColor Red
        Write-Host "----------------------------------------" -ForegroundColor White

        # Display the summary table of GUIDs and their statuses
        Write-Host "Intune Cleanup Summary:" -ForegroundColor Cyan
        $summaryTable | Format-Table -AutoSize

        # Optionally log the summary to the enhanced log as well
        foreach ($row in $summaryTable) {
            Write-EnhancedLog -Message "EnrollmentGUID: $($row.EnrollmentGUID), Status: $($row.Status)" -Level "INFO"
        }
    }
}
#EndRegion '.\Public\Perform-IntuneCleanup.ps1' 132
#Region '.\Public\Remove-MDMCertificates.ps1' -1

function Remove-MDMCertificates {
    <#
    .SYNOPSIS
    Removes MDM certificates from the specified certificate store based on issuer name.
 
    .DESCRIPTION
    The Remove-MDMCertificates function searches for and removes certificates from the specified certificate store path that are issued by the specified issuer, logging each removal action.
 
    .PARAMETER CertStorePath
    The path of the certificate store from which to remove certificates.
 
    .PARAMETER IssuerName
    The name of the issuer whose certificates should be removed.
 
    .EXAMPLE
    $parameters = @{
        CertStorePath = 'Cert:\LocalMachine\My\'
        IssuerName = "CN=Microsoft Intune MDM Device CA"
    }
    Remove-MDMCertificates @parameters
    Removes all MDM certificates issued by Microsoft Intune from the LocalMachine's My certificate store.
 
    .NOTES
    Uses Write-EnhancedLog for detailed logging.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Provide the certificate store path.")]
        [ValidateNotNullOrEmpty()]
        [string]$CertStorePath,

        [Parameter(Mandatory = $true, HelpMessage = "Provide the issuer name to filter certificates by.")]
        [ValidateNotNullOrEmpty()]
        [string]$IssuerName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Remove-MDMCertificates function" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Validate the certificate store path
        if (-not (Test-Path $CertStorePath)) {
            throw "The specified certificate store path does not exist: $CertStorePath"
        }

        Write-EnhancedLog -Message "Searching for certificates in store: $CertStorePath with issuer: $IssuerName" -Level "INFO"
    }

    Process {
        try {
            # Retrieve certificates issued by the specified issuer
            $mdmCerts = Get-ChildItem -Path $CertStorePath | Where-Object Issuer -eq $IssuerName
            
            if ($mdmCerts.Count -eq 0) {
                Write-EnhancedLog -Message "No certificates found from issuer: $IssuerName in $CertStorePath" -Level "Warning"
                return
            }

            # Loop through and remove each certificate
            foreach ($cert in $mdmCerts) {
                Write-EnhancedLog -Message "Removing certificate issued by $IssuerName $($cert.Subject)" -Level "INFO"
                Remove-Item -Path $cert.PSPath -ErrorAction Stop
                Write-EnhancedLog -Message "Successfully removed certificate: $($cert.Subject)" -Level "INFO"
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred while removing certificates: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw
        }
    }

    End {
        Write-EnhancedLog -Message "Completed Remove-MDMCertificates function" -Level "Notice"
    }
}
#EndRegion '.\Public\Remove-MDMCertificates.ps1' 78
#Region '.\Public\Remove-RegistryEntries.ps1' -1

function Remove-RegistryEntries {
    <#
    .SYNOPSIS
    Removes specified registry entries under the Microsoft Enrollments key that match a given GUID.
 
    .DESCRIPTION
    The Remove-RegistryEntries function searches for and removes registry keys under "HKLM:\SOFTWARE\Microsoft\Enrollments" that match the specified EnrollmentGUID. It logs the process, including successes and warnings, using the Write-EnhancedLog function.
 
    .PARAMETER EnrollmentGUID
    The GUID of the enrollment entries to be removed from the registry.
 
    .EXAMPLE
    Remove-RegistryEntries -EnrollmentGUID "12345678-1234-1234-1234-1234567890ab"
    Removes all registry entries under Microsoft Enrollments that match the given GUID.
 
    .NOTES
    Uses the Write-EnhancedLog function for logging. Ensure this function is defined in your script or module.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Provide the Enrollment GUID for the registry entries to be removed.")]
        [ValidateNotNullOrEmpty()]
        [string]$EnrollmentGUID
    )

    Begin {
        Write-EnhancedLog -Message "Starting registry entry removal for GUID: $EnrollmentGUID" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Define the registry path to search for enrollment entries
        $RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Enrollments"

        Write-EnhancedLog -Message "Checking registry path: $RegistryKeyPath" -Level "INFO"
    }

    Process {
        try {
            if (Test-Path -Path $RegistryKeyPath) {
                # Get and remove registry entries matching the Enrollment GUID
                $registryEntries = Get-ChildItem -Path $RegistryKeyPath | Where-Object { $_.Name -match $EnrollmentGUID }

                if ($registryEntries.Count -gt 0) {
                    foreach ($entry in $registryEntries) {
                        try {
                            Remove-Item -Path $entry.PSPath -Recurse -Force -ErrorAction Stop
                            Write-EnhancedLog -Message "Removed registry entry for GUID: $EnrollmentGUID from path: $($entry.PSPath)" -Level "INFO"
                        }
                        catch {
                            Write-EnhancedLog -Message "Error removing registry entry at $($entry.PSPath). Error: $($_.Exception.Message)" -Level "ERROR"
                            Handle-Error -ErrorRecord $_
                        }
                    }
                }
                else {
                    Write-EnhancedLog -Message "No registry entries found matching GUID: $EnrollmentGUID under $RegistryKeyPath" -Level "WARNING"
                }
            }
            else {
                Write-EnhancedLog -Message "Registry key path $RegistryKeyPath not found." -Level "WARNING"
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred while accessing the registry path $RegistryKeyPath. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        Write-EnhancedLog -Message "Completed registry entry removal for GUID: $EnrollmentGUID" -Level "Notice"
    }
}
#EndRegion '.\Public\Remove-RegistryEntries.ps1' 73
#Region '.\Public\Remove-TaskSchedulerEntriesAndTasks.ps1' -1

function Remove-TaskSchedulerEntriesAndTasks {
    <#
    .SYNOPSIS
    Removes scheduled tasks and their folders related to a specific Enrollment GUID.
 
    .DESCRIPTION
    The Remove-TaskSchedulerEntriesAndTasks function finds and removes all scheduled tasks under the Enterprise Management path that match the specified Enrollment GUID. It also removes the corresponding task folders if they exist.
 
    .PARAMETER EnrollmentGUID
    The GUID of the enrollment entries related to the tasks to be removed.
 
    .EXAMPLE
    Remove-TaskSchedulerEntriesAndTasks -EnrollmentGUID "YourGUIDHere"
    Removes all scheduled tasks and folders under Enterprise Management that match the given GUID.
 
    .NOTES
    Uses Write-EnhancedLog for logging steps and outcomes.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Provide the Enrollment GUID for the tasks and folders to be removed.")]
        [ValidateNotNullOrEmpty()]
        [string]$EnrollmentGUID
    )

    Begin {
        Write-EnhancedLog -Message "Starting Remove-TaskSchedulerEntriesAndTasks for GUID: $EnrollmentGUID" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        try {
            Write-EnhancedLog -Message "Connecting to Task Scheduler service." -Level "INFO"
            $taskScheduler = New-Object -ComObject Schedule.Service
            $taskScheduler.Connect()
        }
        catch {
            Write-EnhancedLog -Message "Failed to connect to Task Scheduler service. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return
        }

        # Initialize an array to store unregistered tasks information
        $unregisteredTasks = [System.Collections.Generic.List[PSCustomObject]]::new()
    }

    Process {
        try {
            Write-EnhancedLog -Message "Removing scheduled tasks for GUID: $EnrollmentGUID" -Level "INFO"

            # Search for tasks matching the Enrollment GUID and unregister them
            $tasks = Get-ScheduledTask | Where-Object { $_.TaskPath -match $EnrollmentGUID }
            foreach ($task in $tasks) {
                try {
                    Unregister-ScheduledTask -TaskName $task.TaskName -Confirm:$false
                    Write-EnhancedLog -Message "Unregistered task: $($task.TaskName)" -Level "INFO"

                    # Add unregistered task details to the list
                    $unregisteredTasks.Add([PSCustomObject]@{
                        TaskName = $task.TaskName
                        TaskPath = $task.TaskPath
                    })
                }
                catch {
                    Write-EnhancedLog -Message "Failed to unregister task: $($task.TaskName). Error: $($_.Exception.Message)" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                }
            }

            # Paths to task folders for removal
            $taskFolders = @(
                "$env:WINDIR\System32\Tasks\Microsoft\Windows\EnterpriseMgmt\$EnrollmentGUID",
                "$env:WINDIR\System32\Tasks\Microsoft\Windows\EnterpriseMgmtNoncritical\$EnrollmentGUID"
            )

            # Remove the task folders
            foreach ($folderPath in $taskFolders) {
                if (Test-Path $folderPath) {
                    try {
                        Remove-Item -Path $folderPath -Force -ErrorAction Stop
                        Write-EnhancedLog -Message "Removed task folder at path: $folderPath" -Level "INFO"
                    }
                    catch {
                        Write-EnhancedLog -Message "Failed to remove task folder at path: $folderPath. Error: $($_.Exception.Message)" -Level "ERROR"
                        Handle-Error -ErrorRecord $_
                    }
                }
                else {
                    Write-EnhancedLog -Message "Task folder not found at path: $folderPath" -Level "WARNING"
                }
            }

            # Remove parent folder from Task Scheduler
            try {
                $rootFolder = $taskScheduler.GetFolder("\")
                $rootFolder.DeleteFolder("\Microsoft\Windows\EnterpriseMgmt\$EnrollmentGUID", 0)
                Write-EnhancedLog -Message "Parent task folder for GUID - $EnrollmentGUID removed successfully" -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "Failed to remove parent task folder for GUID - $EnrollmentGUID. Error: $($_.Exception.Message)" -Level "ERROR"
                Handle-Error -ErrorRecord $_
            }
        }
        catch {
            Write-EnhancedLog -Message "Error during task and folder cleanup: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        # Display unregistered tasks
        if ($unregisteredTasks.Count -gt 0) {
            Write-EnhancedLog -Message "Unregistered tasks for GUID: $EnrollmentGUID" -Level "INFO"
            $unregisteredTasks | Format-Table -AutoSize
        }
        else {
            Write-EnhancedLog -Message "No tasks were found or unregistered for GUID: $EnrollmentGUID" -Level "WARNING"
        }

        Write-EnhancedLog -Message "Cleanup process for GUID: $EnrollmentGUID completed." -Level "Notice"
    }
}
#EndRegion '.\Public\Remove-TaskSchedulerEntriesAndTasks.ps1' 122