Public/Get-UserDevices.ps1

function Get-UserDevices {
    <#
    .SYNOPSIS
        Retrieves Intune/Entra device information for a user.
    .DESCRIPTION
        Queries Microsoft Graph (Intune) for all devices associated with a user,
        returning device name, OS, compliance state, last check-in, hardware
        details, enrollment date, management state, and encryption status.
    .PARAMETER Identity
        User Principal Name (UPN) of the target user.
    .OUTPUTS
        Array of PSCustomObjects, one per device.
    .EXAMPLE
        Get-UserDevices -Identity "john.smith@contoso.com"
    .EXAMPLE
        Get-UserDevices -Identity "jsmith@contoso.com" | Format-Table DeviceName, OS, ComplianceState
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string]$Identity
    )

    process {
        # Verify Graph connection
        try {
            $context = Get-MgContext -ErrorAction Stop
            if (-not $context) {
                throw "Not connected to Microsoft Graph. Run Connect-MgGraph first."
            }
        }
        catch {
            throw "Microsoft Graph is not available: $($_.Exception.Message). Run Connect-MgGraph -Scopes 'DeviceManagementManagedDevices.Read.All' first."
        }

        Write-Verbose "Querying Intune managed devices for user: $Identity"

        # ------------------------------------------------------------------
        # Resolve user ID from UPN
        # ------------------------------------------------------------------
        try {
            $mgUser = Get-MgUser -UserId $Identity -Property 'Id' -ErrorAction Stop
            $userId = $mgUser.Id
        }
        catch {
            throw "Could not find user '$Identity' in Entra ID: $($_.Exception.Message)"
        }

        # ------------------------------------------------------------------
        # Get managed devices
        # ------------------------------------------------------------------
        $devices = @()
        try {
            $managedDevices = Get-MgUserManagedDevice -UserId $userId -All -ErrorAction Stop
        }
        catch {
            Write-Warning "Could not retrieve managed devices: $($_.Exception.Message)"
            $managedDevices = @()
        }

        foreach ($device in $managedDevices) {
            # Determine encryption status
            $encryptionStatus = 'Unknown'
            if ($device.IsEncrypted -eq $true) {
                $encryptionStatus = 'Encrypted'
            }
            elseif ($device.IsEncrypted -eq $false) {
                $encryptionStatus = 'Not Encrypted'
            }

            # Compliance state friendly name
            $compliance = switch ($device.ComplianceState) {
                'compliant'    { 'Compliant' }
                'noncompliant' { 'NonCompliant' }
                'conflict'     { 'Conflict' }
                'error'        { 'Error' }
                'inGracePeriod'{ 'In Grace Period' }
                'configManager'{ 'ConfigManager Managed' }
                'unknown'      { 'Unknown' }
                default        { $device.ComplianceState }
            }

            $devices += [PSCustomObject]@{
                DeviceName      = $device.DeviceName
                OS              = $device.OperatingSystem
                OSVersion       = $device.OsVersion
                ComplianceState = $compliance
                LastCheckIn     = $device.LastSyncDateTime
                Manufacturer    = $device.Manufacturer
                Model           = $device.Model
                SerialNumber    = $device.SerialNumber
                EnrollmentDate  = $device.EnrolledDateTime
                IsManaged       = $device.IsManaged
                EncryptionStatus = $encryptionStatus
            }
        }

        # ------------------------------------------------------------------
        # Also check Entra ID registered/joined devices (non-Intune)
        # ------------------------------------------------------------------
        try {
            $entraDevices = Get-MgUserRegisteredDevice -UserId $userId -All -ErrorAction Stop
            $existingDeviceNames = $devices | ForEach-Object { $_.DeviceName }

            foreach ($eDev in $entraDevices) {
                $props = $eDev.AdditionalProperties
                $deviceName = $props['displayName']

                # Skip if already captured via Intune
                if ($deviceName -and $existingDeviceNames -contains $deviceName) { continue }

                $devices += [PSCustomObject]@{
                    DeviceName      = $deviceName
                    OS              = $props['operatingSystem']
                    OSVersion       = $props['operatingSystemVersion']
                    ComplianceState = if ($props['isCompliant'] -eq $true) { 'Compliant' } elseif ($props['isCompliant'] -eq $false) { 'NonCompliant' } else { 'Unknown' }
                    LastCheckIn     = if ($props['approximateLastSignInDateTime']) { [datetime]$props['approximateLastSignInDateTime'] } else { $null }
                    Manufacturer    = $props['manufacturer']
                    Model           = $props['model']
                    SerialNumber    = $null
                    EnrollmentDate  = if ($props['registrationDateTime']) { [datetime]$props['registrationDateTime'] } else { $null }
                    IsManaged       = $props['isManaged']
                    EncryptionStatus = 'Unknown'
                }
            }
        }
        catch {
            Write-Verbose "Could not retrieve Entra registered devices: $($_.Exception.Message)"
        }

        if ($devices.Count -eq 0) {
            Write-Verbose "No devices found for user $Identity"
        }
        else {
            Write-Verbose "Found $($devices.Count) device(s) for $Identity"
        }

        $devices
    }
}