Private/Read-ResourceIdList.ps1

function Read-ResourceIdList {
    <#
    .SYNOPSIS
        Reads a list of VM resource IDs from a file -- either a CSV with a 'ResourceId' column
        (e.g. the export of select-vms-from-cost.kql) or a plain text file with one ID per line.

    .DESCRIPTION
        Returns distinct, well-formed VM resource IDs. Lines that aren't a
        '/subscriptions/.../providers/Microsoft.Compute/virtualMachines/...' path are ignored,
        so headers, comments (#) and stray text are harmless.

    .PARAMETER Path
        Path to the CSV or text file.

    .OUTPUTS
        [string[]] distinct VM resource IDs (original casing preserved).
    #>

    [CmdletBinding()]
    [OutputType([string[]])]
    param(
        [Parameter(Mandatory)] [string] $Path
    )

    if (-not (Test-Path -Path $Path -PathType Leaf)) {
        throw "ResourceId file not found: $Path"
    }

    $candidates = [System.Collections.Generic.List[string]]::new()

    # Prefer a CSV with a ResourceId column.
    $csv = $null
    try { $csv = Import-Csv -Path $Path -ErrorAction Stop } catch { $csv = $null }
    $col = $null
    if ($csv -and $csv.Count -gt 0) {
        $col = $csv[0].PSObject.Properties.Name | Where-Object { $_ -ieq 'ResourceId' } | Select-Object -First 1
    }
    if ($col) {
        foreach ($row in $csv) { $candidates.Add([string]$row.$col) }
    }
    else {
        # Fall back to one ID per line.
        foreach ($line in (Get-Content -Path $Path)) { $candidates.Add([string]$line) }
    }

    $vmIdPattern = '^/subscriptions/[^/]+/resourcegroups/[^/]+/providers/microsoft\.compute/virtualmachines/[^/]+$'
    $seen  = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
    $clean = [System.Collections.Generic.List[string]]::new()
    foreach ($c in $candidates) {
        if (-not $c) { continue }
        $id = $c.Trim().Trim('"')
        if ($id -match $vmIdPattern -and $seen.Add($id)) {
            $clean.Add($id)
        }
    }
    return $clean.ToArray()
}