Public/Get-IntuneRemediationResults.ps1
|
function Get-IntuneRemediationResults { <# .SYNOPSIS Retrieves Intune remediation script results and exports them to a CSV file. .DESCRIPTION This function connects to Microsoft Graph API using Connect-MgGraph, retrieves the specified Intune remediation script results, and exports the data to a CSV file. Uses direct REST API calls for data retrieval. .PARAMETER RemediationName The display name of the Intune remediation script to retrieve results for. If not provided, lists available scripts and prompts for selection. .PARAMETER CsvPath The file path where the CSV results should be saved. .EXAMPLE Get-IntuneRemediationResults -RemediationName "Fix Disk Space" -CsvPath "C:\Reports\remediation.csv" Retrieves results for the "Fix Disk Space" remediation and saves to the specified CSV file. .EXAMPLE Get-IntuneRemediationResults -CsvPath ".\results.csv" Lists available remediation scripts and prompts for selection before exporting. #> [CmdletBinding()] param( [Parameter(Mandatory=$false)] [string]$RemediationName, [Parameter(Mandatory=$true)] [string]$CsvPath ) function Get-AllGraphResults { <# .SYNOPSIS Handles pagination for Graph API requests using Invoke-MgGraphRequest. #> param( [Parameter(Mandatory=$true)] [string]$Uri ) $allResults = @() $nextLink = $Uri do { try { $response = Invoke-MgGraphRequest -Method GET -Uri $nextLink } catch { throw "Graph API request failed: $_" } if ($response.value) { $allResults += $response.value } else { $allResults += $response } $nextLink = $response.'@odata.nextLink' } while ($nextLink) return $allResults } try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Cyan # Ensure we're connected to Microsoft Graph $context = Get-MgContext if (-not $context) { Write-Host "Not connected to Microsoft Graph. Initiating connection..." -ForegroundColor Yellow Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All", "DeviceManagementManagedDevices.Read.All" } else { Write-Host "Using existing Microsoft Graph connection (Tenant: $($context.TenantId))" -ForegroundColor Green } # Get all device health scripts (remediations) $scriptsUri = "https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts" $allScripts = Get-AllGraphResults -Uri $scriptsUri # If RemediationName not provided, list available scripts and prompt for selection if (-not $RemediationName) { Write-Host "`nAvailable remediation scripts:" -ForegroundColor Yellow $allScripts | ForEach-Object { Write-Host " - $($_.displayName)" -ForegroundColor Gray } Write-Host "" $RemediationName = Read-Host "Enter the remediation name" } Write-Host "Searching for remediation script: $RemediationName" -ForegroundColor Cyan # Find the specific remediation by name $remediation = $allScripts | Where-Object { $_.displayName -eq $RemediationName } if (-not $remediation) { Write-Error "Remediation script '$RemediationName' not found." Write-Host "`nAvailable remediation scripts:" -ForegroundColor Yellow $allScripts | ForEach-Object { Write-Host " - $($_.displayName)" -ForegroundColor Gray } return } Write-Host "Found remediation: $($remediation.displayName) (ID: $($remediation.id))" -ForegroundColor Green # Get device run states for this remediation Write-Host "Retrieving device run states..." -ForegroundColor Cyan $runStatesUri = "https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts/$($remediation.id)/deviceRunStates" $deviceRunStates = Get-AllGraphResults -Uri $runStatesUri if ($deviceRunStates.Count -eq 0) { Write-Warning "No device run states found for this remediation." return } Write-Host "Found $($deviceRunStates.Count) device run state(s)" -ForegroundColor Green # Process results into a more readable format $results = @() $counter = 0 foreach ($runState in $deviceRunStates) { $counter++ Write-Progress -Activity "Processing device run states" -Status "Device $counter of $($deviceRunStates.Count)" -PercentComplete (($counter / $deviceRunStates.Count) * 100) # Get managed device details $deviceName = "Unknown" $deviceUser = "Unknown" $deviceId = $runState.id.Split(":")[1] if ($deviceId) { try { $deviceUri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$($deviceId)" $deviceDetails = Invoke-MgGraphRequest -Method GET -Uri $deviceUri $deviceName = $deviceDetails.deviceName $deviceUser = $deviceDetails.userPrincipalName } catch { Write-Verbose "Could not retrieve device details for $deviceId" } } $resultObject = [PSCustomObject]@{ DeviceName = $deviceName UserPrincipalName = $deviceUser DetectionState = $runState.detectionState LastStateUpdateDateTime = $runState.lastStateUpdateDateTime PreRemediationDetectionScriptOutput = $runState.preRemediationDetectionScriptOutput RemediationState = $runState.remediationState PostRemediationDetectionScriptOutput = $runState.postRemediationDetectionScriptOutput RemediationScriptErrorDetails = $runState.remediationScriptErrorDetails DetectionScriptErrorDetails = $runState.detectionScriptErrorDetails ManagedDeviceId = $deviceId } $results += $resultObject } Write-Progress -Activity "Processing device run states" -Completed # Export to CSV Write-Host "Exporting results to: $CsvPath" -ForegroundColor Cyan $results | Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8 Write-Host "`nExport completed successfully!" -ForegroundColor Green Write-Host "Total records exported: $($results.Count)" -ForegroundColor Cyan # Display summary Write-Host "`nSummary:" -ForegroundColor Yellow $detectionStates = $results | Group-Object DetectionState foreach ($state in $detectionStates) { Write-Host " $($state.Name): $($state.Count)" -ForegroundColor Gray } } catch { Write-Error "An error occurred: $_" throw } } |