Public/Get-EFManagementAgentHealth.ps1
|
function Get-EFManagementAgentHealth { <# .SYNOPSIS Checks the local Intune and Configuration Manager agent health without contacting management services. .DESCRIPTION Reads fixed, local evidence for the Microsoft Intune Management Extension and the Microsoft Configuration Manager client. It checks the agent service, its startup setting, a standard local log timestamp, and the local Configuration Manager interface. This command does not contact Intune, a Configuration Manager management point, or any other computer. It does not read log contents, tenant or site details, management-service device IDs, policies, applications, account names, or server addresses. Local evidence cannot prove cloud registration, compliance, or a successful check-in. The result includes the Windows computer name plus local operational metadata such as agent service state, version, standard log path, and last-write time. Consequently, SensitiveDataIncluded is true. Protect exported health results according to your organization's handling requirements. The Intune Management Extension is installed only when an applicable Intune workload needs it. Not finding the extension does not by itself prove that the computer is not enrolled in Intune. .PARAMETER Agent Chooses Intune, ConfigurationManager, or All. CCM, SCCM, and ConfigMgr are accepted as familiar names for ConfigurationManager. .PARAMETER TimeoutSeconds Maximum time allowed for the local Configuration Manager interface check. This does not allow a network request. .EXAMPLE Get-EFManagementAgentHealth .EXAMPLE Get-EFManagementAgentHealth -Agent ConfigurationManager .OUTPUTS EndpointForge.ManagementAgentHealth. LocalStatus is LooksReady only when all required local evidence was collected and passed. NeedsAttention represents a known local issue or partially collected evidence. CouldNotCheck represents unavailable trustworthy evidence. SensitiveDataIncluded is true because the result contains computer-identifying and local operational metadata. .LINK Invoke-EFManagementAgentAction #> [CmdletBinding()] [OutputType('EndpointForge.ManagementAgentHealth')] param( [ValidateSet('All', 'Intune', 'ConfigurationManager', 'CCM', 'SCCM', 'ConfigMgr')] [string]$Agent = 'All', [ValidateRange(1, 30)] [int]$TimeoutSeconds = 10 ) $null = Test-EFWindows -Throw $agents = if ($Agent -eq 'All') { @('Intune', 'ConfigurationManager') } elseif ($Agent -eq 'Intune') { @('Intune') } else { @('ConfigurationManager') } $computerName = if ([string]::IsNullOrWhiteSpace($env:COMPUTERNAME)) { [Environment]::MachineName } else { $env:COMPUTERNAME } foreach ($agentName in $agents) { $definition = Get-EFManagementAgentDefinition -Agent $agentName $state = Get-EFManagementAgentState -Definition $definition -TimeoutSeconds $TimeoutSeconds $checks = [Collections.Generic.List[object]]::new() $findings = [Collections.Generic.List[string]]::new() $issueCount = 0 $agentDetectionUnavailable = -not [bool]$state.Installed -and -not [bool]$state.ServiceQuerySucceeded -and -not [bool]$state.ServiceRegistryReadable if ($agentDetectionUnavailable) { $localStatus = 'CouldNotCheck' $dataStatus = 'Failed' $issueCount++ $findings.Add('Windows did not provide trustworthy evidence showing whether the local management agent is installed.') $checks.Add([pscustomobject]@{ Name = 'Agent installed' Result = 'CouldNotCheck' Explanation = 'Windows did not provide trustworthy service or registry evidence for this agent.' }) $summary = "EndpointForge could not determine whether the $($definition.DisplayName) is installed." $nextStep = 'Open PowerShell with the permissions approved by your organization, or review the agent through Windows Services. Do not assume the agent is installed or absent.' } elseif (-not [bool]$state.Installed) { $localStatus = 'NotDetected' $dataStatus = 'Complete' $checks.Add([pscustomobject]@{ Name = 'Agent installed' Result = 'NotDetected' Explanation = "The $($definition.DisplayName) was not found." }) if ($agentName -eq 'Intune') { $summary = 'The Microsoft Intune Management Extension was not found. This alone does not prove the computer is not enrolled in Intune.' $nextStep = 'If your organization expects Win32 apps, PowerShell scripts, remediations, or other extension workloads, confirm assignment and device status in Intune. Otherwise, no action may be needed.' } else { $summary = 'The Microsoft Configuration Manager client was not found on this computer.' $nextStep = 'If your organization expects this computer to use Configuration Manager, confirm the approved client deployment process. Otherwise, no action may be needed.' } } elseif (-not [bool]$state.ServiceQuerySucceeded) { $localStatus = 'CouldNotCheck' $dataStatus = 'Failed' $issueCount++ $findings.Add('Windows did not provide a trustworthy state for the local management agent service.') $checks.Add([pscustomobject]@{ Name = 'Agent service' Result = 'CouldNotCheck' Explanation = 'Windows did not provide a trustworthy service state.' }) $summary = 'EndpointForge found local agent evidence but could not read a trustworthy service state.' $nextStep = 'Open PowerShell with the permissions approved by your organization, or review the agent through Windows Services. Do not assume the agent is healthy or broken.' } else { $serviceRunning = [string]$state.ServiceStatus -eq 'Running' $startupEvidenceAvailable = [bool]$state.ServiceRegistryReadable -and -not [string]::IsNullOrWhiteSpace([string]$state.StartupType) $startupUnexpected = $startupEvidenceAvailable -and [string]$state.StartupType -ne 'Automatic' $interfaceProblem = $agentName -eq 'ConfigurationManager' -and [string]$state.LocalInterfaceStatus -eq 'Unavailable' $interfaceUnknown = $agentName -eq 'ConfigurationManager' -and [string]$state.LocalInterfaceStatus -notin @('Available', 'Unavailable') $checks.Add([pscustomobject]@{ Name = 'Agent service' Result = if ($serviceRunning) { 'LooksReady' } else { 'NeedsAttention' } Explanation = if ($serviceRunning) { 'The local agent service is running.' } else { "The local agent service is $($state.ServiceStatus)." } }) if (-not $serviceRunning) { $issueCount++ $findings.Add("The local agent service is $($state.ServiceStatus), not Running.") } $checks.Add([pscustomobject]@{ Name = 'Service startup setting' Result = if (-not $startupEvidenceAvailable) { 'CouldNotCheck' } elseif ($startupUnexpected) { 'NeedsAttention' } else { 'LooksReady' } Explanation = if (-not $startupEvidenceAvailable) { 'Windows did not provide a trustworthy startup setting for the local agent service.' } elseif ($startupUnexpected) { "The local agent service startup setting is $($state.StartupType), not Automatic." } else { 'The local agent service startup setting is Automatic.' } }) if (-not $startupEvidenceAvailable) { $issueCount++ $findings.Add('The local agent service startup setting could not be checked.') } elseif ($startupUnexpected) { $issueCount++ $findings.Add("The local agent service startup setting is $($state.StartupType), not Automatic.") } if ($agentName -eq 'ConfigurationManager') { $checks.Add([pscustomobject]@{ Name = 'Local client interface' Result = if ($interfaceUnknown) { 'CouldNotCheck' } elseif ($interfaceProblem) { 'NeedsAttention' } else { 'LooksReady' } Explanation = if ($interfaceUnknown) { 'EndpointForge could not finish the time-limited local Configuration Manager interface check.' } elseif ($interfaceProblem) { 'The fixed local Configuration Manager interface root\ccm was not available.' } else { 'The fixed local Configuration Manager interface root\ccm is available.' } }) if ($interfaceProblem) { $issueCount++ $findings.Add('The local Configuration Manager client interface was not available.') } elseif ($interfaceUnknown) { $issueCount++ $findings.Add('The local Configuration Manager client interface could not be checked.') } } if ($interfaceUnknown) { $localStatus = 'CouldNotCheck' $dataStatus = 'Partial' $summary = 'The Configuration Manager service state was read, but the local client interface could not be checked.' $nextStep = 'Review the local Configuration Manager client and WMI health before requesting policy.' } elseif (-not $serviceRunning -or -not $startupEvidenceAvailable -or $startupUnexpected -or $interfaceProblem) { $localStatus = 'NeedsAttention' $dataStatus = if ($startupEvidenceAvailable) { 'Complete' } else { 'Partial' } $summary = if (-not $startupEvidenceAvailable -and $serviceRunning -and -not $interfaceProblem) { "The $($definition.DisplayName) is running, but EndpointForge could not verify every required local setting." } else { "The $($definition.DisplayName) has a local issue that needs attention." } $nextStep = 'Preview a supported agent action, or review the local Windows service and agent logs through your approved support process.' } else { $localStatus = 'LooksReady' $dataStatus = 'Complete' $summary = "The $($definition.DisplayName) looks ready from local evidence. This does not prove a successful management-service check-in." $nextStep = 'No local service action is indicated. Confirm current device status in your organization management console when needed.' } } [pscustomobject][ordered]@{ PSTypeName = 'EndpointForge.ManagementAgentHealth' ComputerName = $computerName Agent = $agentName DisplayName = [string]$definition.DisplayName CheckedAtUtc = [DateTime]::UtcNow Installed = [bool]$state.Installed LocalStatus = $localStatus DataStatus = $dataStatus IsReady = $localStatus -eq 'LooksReady' ExitCode = if ($localStatus -eq 'LooksReady') { 0 } elseif ($localStatus -eq 'CouldNotCheck') { 3 } else { 1 } Summary = $summary NextStep = $nextStep ServiceName = [string]$definition.ServiceName ServiceStatus = [string]$state.ServiceStatus StartupType = [string]$state.StartupType Version = $state.Version MainLogPath = [string]$definition.MainLogPath MainLogPresent = [bool]$state.MainLogPresent LastLocalActivityUtc = $state.LastLocalActivityUtc LocalInterfaceAvailable = $state.LocalInterfaceAvailable IssueCount = $issueCount Checks = @($checks) Findings = @($findings) AvailableActions = @($definition.AvailableActions) NetworkActivityPerformed = $false SensitiveDataIncluded = $true } } } |