Public/Find-IntuneLapsDevice.ps1

function Find-IntuneLapsDevice {
    <#
    .SYNOPSIS
        Searches for Intune-managed devices by name.
    .DESCRIPTION
        Queries the Microsoft Graph API (/deviceManagement/managedDevices) using a
        server-side OData filter. Supports partial name matching with startsWith.
        Returns a structured list of matching devices suitable for piping to
        Get-IntuneLapsCredential.
    .PARAMETER DeviceName
        The device name (or partial name) to search for. Supports wildcards by using
        a prefix — "DESK" will match any device starting with "DESK".
    .PARAMETER ExactMatch
        When specified, requires an exact (case-insensitive) name match instead of
        a startsWith filter.
    .EXAMPLE
        Find-IntuneLapsDevice -DeviceName 'DESKTOP-'
    .EXAMPLE
        Find-IntuneLapsDevice -DeviceName 'WS001' -ExactMatch
    .EXAMPLE
        Find-IntuneLapsDevice -DeviceName 'DESK' | Get-IntuneLapsCredential
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]$DeviceName,

        [Parameter(Mandatory = $false)]
        [switch]$ExactMatch
    )

    begin {
        $ErrorActionPreference = 'Stop'

        # Verify we're connected
        try {
            $null = Get-MgContext -ErrorAction Stop
        }
        catch {
            throw 'Not connected. Run Connect-IntuneLaps before searching for devices.'
        }
    }

    process {
        try {
            # Build OData filter — server-side, Filter-Left principle
            [string]$Filter = ''
            if (-not [string]::IsNullOrWhiteSpace($DeviceName)) {
                if ($ExactMatch) {
                    $Filter = "deviceName eq '$DeviceName'"
                }
                else {
                    $Filter = "startsWith(deviceName,'$DeviceName')"
                }
            }

            [string]$SelectFields = 'id,azureADDeviceId,deviceName,operatingSystem,osVersion,lastSyncDateTime,managementState'
            if ($Filter) {
                Write-Verbose "Querying Graph API with filter: $Filter"
                [string]$NextUri = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$filter=$Filter&`$select=$SelectFields"
            }
            else {
                Write-Verbose 'Querying Graph API for all managed devices (no filter)'
                [string]$NextUri = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$select=$SelectFields"
            }

            # Paginate through all results via @odata.nextLink (Graph caps at 100 items per page)
            $AllDevices = [System.Collections.Generic.List[object]]::new()
            [int]$Page = 0
            do {
                $Page++
                Write-Progress -Activity 'Find-IntuneLapsDevice' `
                               -Status "Loading devices... ($($AllDevices.Count) loaded, page $Page)" `
                               -PercentComplete -1

                $Response = Invoke-MgGraphRequestWithRetry -Parameters @{ Method = 'GET'; Uri = $NextUri }
                if ($Response.value) {
                    foreach ($Device in $Response.value) { $AllDevices.Add($Device) }
                }
                $NextUri = $Response.'@odata.nextLink'
            } while ($NextUri)
            Write-Progress -Activity 'Find-IntuneLapsDevice' -Completed

            if ($AllDevices.Count -eq 0) {
                if ($DeviceName) {
                    Write-Warning "No Intune-managed devices found matching '$DeviceName'."
                } else {
                    Write-Warning 'No Intune-managed devices found in the tenant.'
                }
                return
            }

            foreach ($Device in $AllDevices) {
                [PSCustomObject]@{
                    DeviceId          = $Device.azureADDeviceId
                    IntuneDeviceId    = $Device.id
                    DeviceName        = $Device.deviceName
                    OperatingSystem   = $Device.operatingSystem
                    OsVersion         = $Device.osVersion
                    ManagementState   = $Device.managementState
                    LastSyncDateTime  = $Device.lastSyncDateTime
                }
            }
        }
        catch {
            Write-Error -Message "Failed to search for devices: $_"
        }
    }
}