Tools/Get-PowerAppsLicenseInventory.ps1

# Get-PowerAppsLicenseInventory.ps1
# Exports Power Apps / Power Platform license SKU and assignment info to CSV to help with quoting.

param(
    [string]$OutputPath = "PowerAppsLicenseInventory.csv"
)

# Prefer Microsoft.Entra.Beta if available; attempt to import so commands like Connect-Entra / Get-EntraSubscribedSku are present
try {
    if (-not (Get-Module -Name Microsoft.Entra.Beta -ListAvailable)) {
        # Not installed locally; do not auto-install here, only attempt import if present
        Write-Verbose "Microsoft.Entra.Beta module not found in module path."
    } else {
        Import-Module Microsoft.Entra.Beta -ErrorAction SilentlyContinue
        Write-Verbose "Imported Microsoft.Entra.Beta module"
    }
} catch {
    Write-Verbose "Failed to import Microsoft.Entra.Beta: $_"
}

try {
    if (Get-Command -Name Get-AdminPowerAppLicenses -ErrorAction SilentlyContinue) {
        Write-Host "Using Power Apps admin cmdlet Get-AdminPowerAppLicenses..."
        Get-AdminPowerAppLicenses -OutputFilePath $OutputPath -Force
        if (Test-Path $OutputPath) {
            Write-Host "Exported license inventory to $OutputPath"
            return
        } else {
            Write-Warning "Get-AdminPowerAppLicenses did not produce $OutputPath — continuing to Microsoft Graph fallback."
        }
    }
} catch {
    Write-Verbose "Power Apps admin cmdlets not available: $_"
}

try {
    # Try Entra PowerShell first if available (Connect-Entra / Get-EntraSubscribedSku)
    if (Get-Command -Name Get-EntraSubscribedSku -ErrorAction SilentlyContinue) {
        try {
            Write-Host "Using Entra PowerShell cmdlet Get-EntraSubscribedSku..."
            $skus = Get-EntraSubscribedSku
        } catch {
            # Try to connect and retry
            if (Get-Command -Name Connect-Entra -ErrorAction SilentlyContinue) {
                Write-Host "Connecting with Connect-Entra..."
                Connect-Entra | Out-Null
                $skus = Get-EntraSubscribedSku
            } else {
                Write-Error "Entra cmdlets found but failed to run and Connect-Entra is not available."
                return
            }
        }
    } else {
        if (-not (Get-Command -Name Connect-MgGraph -ErrorAction SilentlyContinue)) {
            Write-Host "Microsoft.Graph module not found. Please install: Install-Module Microsoft.Graph -Scope CurrentUser" -ForegroundColor Yellow
        }

        Write-Host "Connecting to Microsoft Graph to query subscribed SKUs..."
        Connect-MgGraph -Scopes "Directory.Read.All","User.Read.All" | Out-Null

        # Prefer stable cmdlet, fall back to beta-prefixed cmdlet if the tenant/environment uses beta modules
        if (Get-Command -Name Get-MgSubscribedSku -ErrorAction SilentlyContinue) {
            $skus = Get-MgSubscribedSku -All
        } elseif (Get-Command -Name Get-MgBetaSubscribedSku -ErrorAction SilentlyContinue) {
            Write-Host "Using Microsoft Graph Beta cmdlet Get-MgBetaSubscribedSku..."
            $skus = Get-MgBetaSubscribedSku -All
        } else {
            Write-Error "Neither Get-MgSubscribedSku nor Get-MgBetaSubscribedSku are available. Install Microsoft.Graph or Microsoft.Graph.Beta modules."
            return
        }
    }
    $rows = @()
    foreach ($s in $skus) {
        $rows += [PSCustomObject]@{
            SkuPartNumber = $s.SkuPartNumber
            SkuId = $s.SkuId
            ConsumedUnits = $s.ConsumedUnits
            PrepaidUnits = ($s.PrepaidUnits | ConvertTo-Json -Compress)
        }
    }

    $rows | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
    Write-Host "Exported subscribed SKUs to $OutputPath"
} catch {
    Write-Error "Failed to collect license inventory: $_"
}