Skip to content

Menu
  • Inicio
  • Sobre mi
  • Home
  • 2026
  • marzo
  • 25
  • Informe Graph Intune
Intune

Informe Graph Intune

Brian Boza Carocamarzo 25, 2026marzo 25, 2026

Share

Facebook
Twitter
Pinterest
LinkedIn
0 0
Read Time:5 Minute, 8 Second

Cuando comencé a trabajar con Microsoft Office 365, mi principal herramienta era PowerShell. Con el tiempo, y hasta hoy, la gestión ha evolucionado hacia el uso de Microsoft Graph.

Actualmente, gestiono entornos donde varios clientes comparten la administración de Intune, lo que genera la necesidad de obtener información detallada de ciertos dispositivos. Tras una investigación, desarrollé el siguiente script.

Este script en PowerShell automatiza la generación de informes sobre configuraciones aplicadas en dispositivos gestionados con Intune. Parte de un archivo TXT que contiene los nombres de los equipos. A partir de esta lista, se conecta a Microsoft Graph para localizar los dispositivos en el entorno de Intune, registrando también aquellos que no se encuentran.

Para cada equipo identificado, el script lanza una consulta que genera un “export job” en Intune. Este proceso crea un archivo comprimido con el estado de las políticas aplicadas. El script espera a que finalice la tarea, descarga el archivo, lo descomprime y extrae la información en formato CSV.

Posteriormente, los datos se normalizan para mejorar su legibilidad. Por ejemplo, estados como “failed” se muestran como “Error”, y ciertos tipos técnicos se traducen a términos más claros como “Endpoint Security” o “Settings Catalog”.

Durante la ejecución, se incluye una barra de progreso que permite visualizar el avance, especialmente útil cuando se procesan múltiples equipos.

Finalmente, toda la información se consolida en una tabla y se exporta a un archivo CSV en la ruta especificada. El resultado es un informe claro que permite identificar rápidamente qué políticas están aplicadas a cada dispositivo y su estado.

Como ejecutar el SCRIPT:

Reporte-IntuneDeviceConfigV01.ps1 -ComputerListFile C:\Temp\IntuneReport\Equipos.txt -OutputFolder "C:\Temp\IntuneReport

Código: Reporte-IntuneDeviceConfigV01.ps1

param(
    [string]$ComputerListFile = "C:\Temp\equipos.txt",
    [string]$OutputFolder = "C:\Temp\IntuneReport"
)

# =========================
# Configuración general
# =========================
$ErrorActionPreference = "Stop"

function Ensure-Folder {
    param([string]$Path)

    if (-not (Test-Path -Path $Path)) {
        New-Item -ItemType Directory -Path $Path -Force | Out-Null
    }
}

function Wait-ExportJob {
    param(
        [Parameter(Mandatory = $true)]
        [string]$JobId
    )

    do {
        Start-Sleep -Seconds 3
        $job = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('$JobId')"
        Write-Host "Estado del export job: $($job.status)" -ForegroundColor DarkCyan
    }
    while ($job.status -in @("notStarted","inProgress"))

    return $job
}

function Get-DeviceConfigurationStatusesForDevice {
    param(
        [Parameter(Mandatory = $true)]
        [string]$IntuneDeviceId
    )

    $body = @{
        reportName = "DeviceConfigurationPolicyStatusesV3"
        format     = "csv"
        filter     = "(IntuneDeviceId eq '$IntuneDeviceId')"
    } | ConvertTo-Json -Depth 5

    $job = Invoke-MgGraphRequest `
        -Method POST `
        -Uri "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs" `
        -Body $body `
        -ContentType "application/json"

    $completedJob = Wait-ExportJob -JobId $job.id

    if (-not $completedJob.url) {
        throw "El export job finalizó sin URL de descarga."
    }

    $tempZip = Join-Path $env:TEMP ("IntuneReport_" + [guid]::NewGuid().ToString() + ".zip")
    $tempDir = Join-Path $env:TEMP ("IntuneReport_" + [guid]::NewGuid().ToString())

    Invoke-WebRequest -Uri $completedJob.url -OutFile $tempZip
    Expand-Archive -Path $tempZip -DestinationPath $tempDir -Force

    $csvFile = Get-ChildItem -Path $tempDir -Filter *.csv | Select-Object -First 1
    if (-not $csvFile) {
        throw "No se encontró el CSV dentro del ZIP exportado."
    }

    $rows = Import-Csv -Path $csvFile.FullName

    Remove-Item $tempZip -Force -ErrorAction SilentlyContinue
    Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue

    return $rows
}

function Normalize-State {
    param([string]$State)

    if ([string]::IsNullOrWhiteSpace($State)) {
        return ""
    }

    switch -Regex ($State.ToLower()) {
        "success|succeeded" { "Succeeded"; break }
        "error|failed|fail" { "Error"; break }
        "conflict"          { "Conflict"; break }
        "pending"           { "Pending"; break }
        "notapplicable"     { "NotApplicable"; break }
        default             { $State }
    }
}

function Normalize-PolicyType {
    param([string]$Type)

    if ([string]::IsNullOrWhiteSpace($Type)) {
        return ""
    }

    switch -Regex ($Type.ToLower()) {
        "endpoint" { "Endpoint Security"; break }
        "settings" { "Settings Catalog"; break }
        "catalog"  { "Settings Catalog"; break }
        "device"   { "Device configuration"; break }
        "admin"    { "Administrative Templates"; break }
        default    { $Type }
    }
}

# =========================
# Inicio
# =========================

Ensure-Folder -Path $OutputFolder
$csvPath = Join-Path $OutputFolder "Intune_DeviceConfigurationStatuses.csv"

if (-not (Test-Path -Path $ComputerListFile)) {
    throw "No se encontró el archivo TXT: $ComputerListFile"
}

# Leer nombres de equipos desde TXT
$ComputerNameFilter = Get-Content -Path $ComputerListFile |
    ForEach-Object { $_.Trim() } |
    Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
    Select-Object -Unique

if (-not $ComputerNameFilter -or $ComputerNameFilter.Count -eq 0) {
    throw "El archivo TXT no contiene nombres de equipos válidos."
}

Write-Host ""
Write-Host "Conectando a Microsoft Graph..." -ForegroundColor Cyan

Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All","DeviceManagementConfiguration.Read.All" | Out-Null

Write-Host "Consultando dispositivos administrados..." -ForegroundColor Cyan

$devicesUri = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$select=id,deviceName,userDisplayName,userPrincipalName"
$devicesResponse = Invoke-MgGraphRequest -Method GET -Uri $devicesUri

$devices = @()
$devices += $devicesResponse.value

while ($devicesResponse.'@odata.nextLink') {
    $devicesResponse = Invoke-MgGraphRequest -Method GET -Uri $devicesResponse.'@odata.nextLink'
    $devices += $devicesResponse.value
}

# Filtrar solo los equipos del TXT
$devices = $devices | Where-Object { $_.deviceName -in $ComputerNameFilter }

if (-not $devices -or $devices.Count -eq 0) {
    Write-Warning "No se encontraron dispositivos en Intune que coincidan con los nombres del TXT."
    return
}

Write-Host ("Total de equipos a procesar: {0}" -f $devices.Count) -ForegroundColor Yellow

$results = New-Object System.Collections.Generic.List[object]
$index = 0

foreach ($device in $devices) {
    $index++
    $percent = [math]::Round(($index / $devices.Count) * 100, 0)

    Write-Progress -Activity "Consultando configuraciones aplicadas" `
                   -Status "Procesando $($device.deviceName) ($index de $($devices.Count))" `
                   -PercentComplete $percent

    try {
        $reportRows = Get-DeviceConfigurationStatusesForDevice -IntuneDeviceId $device.id

        if ($reportRows -and $reportRows.Count -gt 0) {
            foreach ($row in $reportRows) {
                $results.Add([PSCustomObject]@{
                    "Nombre del equipo" = $row.DeviceName
                    "Policy"            = $row.PolicyName
                    "Logged in user"    = $row.UPN
                    "Policy type"       = Normalize-PolicyType -Type $row.UnifiedPolicyType
                    "State"             = Normalize-State -State $row.PolicyStatus
                })
            }
        }
        else {
            $results.Add([PSCustomObject]@{
                "Nombre del equipo" = $device.deviceName
                "Policy"            = "(Sin configuraciones reportadas)"
                "Logged in user"    = $device.userPrincipalName
                "Policy type"       = ""
                "State"             = ""
            })
        }
    }
    catch {
        $results.Add([PSCustomObject]@{
            "Nombre del equipo" = $device.deviceName
            "Policy"            = "(Error consultando reporte)"
            "Logged in user"    = $device.userPrincipalName
            "Policy type"       = ""
            "State"             = $_.Exception.Message
        })
    }
}

# Agregar equipos del TXT que no existan en Intune
$foundDeviceNames = @($devices.deviceName | ForEach-Object { $_.Trim() })
$notFoundDevices = $ComputerNameFilter | Where-Object { $_.Trim() -notin $foundDeviceNames }

foreach ($missingDevice in $notFoundDevices) {
    $results.Add([PSCustomObject]@{
        "Nombre del equipo" = $missingDevice
        "Policy"            = "(Equipo no encontrado en Intune)"
        "Logged in user"    = ""
        "Policy type"       = ""
        "State"             = ""
    })
}

Write-Progress -Activity "Consultando configuraciones aplicadas" -Completed

$results = $results | Sort-Object "Nombre del equipo","Policy"

Write-Host ""
Write-Host "Resultado:" -ForegroundColor Green
$results | Format-Table -AutoSize

$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

Write-Host ""
Write-Host "Reporte exportado en: $csvPath" -ForegroundColor Green

Si este artículo te ha resultado útil, puedes dejar tu comentario. Para cualquier duda, puedes contactarme a través del correo electrónico disponible en mi perfil.

About Post Author

Brian Boza Caroca

Con una trayectoria de más de 9 años, me he consolidado como un aporte en implementar soluciones de seguridad IT y gestionar ambientes híbridos. Mi experiencia como Especialista Microsoft me ha permitido profundizar en tecnologías de vanguardia y adaptarme a los desafíos emergentes en el campo de la seguridad informática.
brian.boza@hotmail.com
Happy
Happy
0 0 %
Sad
Sad
0 0 %
Excited
Excited
0 0 %
Sleepy
Sleepy
0 0 %
Angry
Angry
0 0 %
Surprise
Surprise
0 0 %

Navegación de entradas

Previous

Previous post:

Error de inscripción en Entra ID: dispositivo previamente registrado

Previous post Error de inscripción en Entra ID: dispositivo previamente registrado

Average Rating

5 Star
0%
4 Star
0%
3 Star
0%
2 Star
0%
1 Star
0%
(Add your review)

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Categorías

  • Azure
  • Exchange Online
  • Intune
  • Microsoft EDGE
  • Microsoft graph
  • Microsoft Teams
  • OneDrive
  • Onpremise
  • PowerBI
  • SCCM
  • Seguridad

Entradas recientes

  • Informe Graph Intune

Acceso

  • Acceder
  • Feed de entradas
  • Feed de comentarios
  • WordPress.org
LinkedIn
LinkedIn
Tweets by BozaCaroca

Close
Menu
  • Inicio
  • Sobre mi

Related Post

Error de inscripción en Entra ID: dispositivo previamente registrado

febrero 24, 2026febrero 24, 2026

Bloqueo de extensiones en Google Chrome

agosto 25, 2022enero 31, 2024

Empaquetar aplicación de Windows (Win32)

marzo 2, 2022enero 31, 2024

Restringir la copia de datos en un dispositivo USB‎.

octubre 13, 2021enero 31, 2024

‎¿Cómo probar la conectividad de Intune en una red corporativa?

octubre 9, 2021enero 31, 2024

¿Cómo empaquetar LAPS en INTUNE?

octubre 6, 2021enero 31, 2024