<# .SYNOPSIS Lanza un análisis de Microsoft Defender Antivirus en las computadoras que indiques. .DESCRIPTION Busca las computadoras por nombre en Intune y les manda la acción windowsDefenderScan. Por defecto es un análisis rápido; con -Completo revisa todos los archivos. Solo envía la orden: la computadora la ejecuta cuando se conecta con Intune. Usa -WhatIf para simular sin enviar. .PARAMETER Nombre Uno o varios nombres de dispositivo, tal como aparecen en Intune. .PARAMETER RutaEntradaCsv CSV con los dispositivos, con una columna llamada Dispositivo. .PARAMETER Completo Hace un análisis completo en lugar de uno rápido. .PARAMETER RutaCsv Ruta del CSV con el resultado por dispositivo. Si se omite, solo se muestra en pantalla. .EXAMPLE .\start-analisis-antivirus.ps1 -Nombre LAP-VENTAS-01,LAP-VENTAS-02 -WhatIf .EXAMPLE .\start-analisis-antivirus.ps1 -RutaEntradaCsv .\equipos.csv -Completo -RutaCsv .\resultado.csv .NOTES Permisos: DeviceManagementManagedDevices.Read.All, DeviceManagementManagedDevices.PrivilegedOperations.All Rol mínimo: Help Desk Operator de Intune Licencia: Microsoft Intune Plan 1 (incluido en Microsoft 365 Business Premium) Licencia del código: MIT. Se entrega TAL CUAL, sin garantía. Pruébalo primero en un tenant de pruebas. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'Nombre')] param( [Parameter(Mandatory, ParameterSetName = 'Nombre')] [string[]]$Nombre, [Parameter(Mandatory, ParameterSetName = 'Archivo')] [string]$RutaEntradaCsv, [switch]$Completo, [string]$RutaCsv ) $ErrorActionPreference = 'Stop' $permisos = @('DeviceManagementManagedDevices.Read.All', 'DeviceManagementManagedDevices.PrivilegedOperations.All') if ($RutaEntradaCsv) { $entrada = @(Import-Csv -Path $RutaEntradaCsv) if ($entrada -and $entrada[0].PSObject.Properties.Name -notcontains 'Dispositivo') { throw "El CSV $RutaEntradaCsv debe tener una columna llamada Dispositivo." } $Nombre = $entrada.Dispositivo } $buscados = @($Nombre | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() } | Sort-Object -Unique) if (-not $buscados) { throw 'No indicaste ningún dispositivo.' } if (-not (Get-Command Connect-MgGraph -ErrorAction SilentlyContinue)) { throw 'Falta el módulo. Instálalo con: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser' } Connect-MgGraph -Scopes $permisos -NoWelcome $uri = 'https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$select=id,deviceName,operatingSystem' $dispositivos = while ($uri) { $pagina = Invoke-MgGraphRequest -Method GET -Uri $uri $pagina.value $uri = $pagina.'@odata.nextLink' } $tipo = if ($Completo) { 'completo' } else { 'rápido' } $cuerpo = @{ quickScan = (-not $Completo) } | ConvertTo-Json $filas = foreach ($buscado in $buscados) { # Un nombre repetido suele ser un registro viejo: analizarlo de más no hace daño, así que se manda a todos. $encontrados = @($dispositivos | Where-Object { $_.deviceName -eq $buscado }) if (-not $encontrados) { [pscustomobject]@{ Dispositivo = $buscado; Id = $null; Analisis = $tipo; Resultado = 'No encontrado en Intune' } continue } foreach ($d in $encontrados) { $resultado = if ("$($d.operatingSystem)" -notlike 'Windows*') { "Omitido: es $($d.operatingSystem)" } elseif ($PSCmdlet.ShouldProcess($d.deviceName, "Iniciar análisis $tipo de Microsoft Defender Antivirus")) { try { $null = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/$($d.id)/windowsDefenderScan" -Body $cuerpo -ContentType 'application/json' 'Enviado' } catch { "Error: $($_.Exception.Message)" } } else { 'No enviado' } [pscustomobject]@{ Dispositivo = $d.deviceName; Id = $d.id; Analisis = $tipo; Resultado = $resultado } } } Write-Host "Análisis enviados: $(@($filas | Where-Object Resultado -EQ 'Enviado').Count) de $(@($filas).Count)" if ($RutaCsv) { # -WhatIf:$false para que la simulación también deje su reporte; solo cancela la acción en Intune. $filas | Export-Csv -Path $RutaCsv -NoTypeInformation -Encoding utf8BOM -WhatIf:$false Write-Host "CSV guardado en $RutaCsv" } else { $filas | Format-Table -AutoSize }