Saltar al contenido
Microsoft scripts

Scripts de Defender

Lanzar análisis de antivirus en computadoras

Manda un análisis rápido o completo de Microsoft Defender Antivirus a las computadoras que indiques por nombre o en un CSV, sin ir una por una en Intune.

Antes de correrloEnviado significa que Intune recibió la orden, no que el análisis terminó: la computadora lo ejecuta cuando se conecta. El análisis completo con -Completo puede hacer lenta la computadora, así que evítalo en horario de trabajo. El permiso PrivilegedOperations.All también autoriza otras acciones sobre dispositivos: no reutilices esa sesión para otra cosa.

Ejemplo en México

Distribuidora de refacciones en Toluca, 50 personas

Un vendedor abrió un adjunto sospechoso y TI quiere revisar de inmediato las laptops de todo el equipo de ventas.

.\start-analisis-antivirus.ps1 -RutaEntradaCsv .\equipos.csv -RutaCsv .\resultado.csv

Envía los análisis a todo el equipo y deja un CSV con a qué computadoras les llegó la orden.

Cómo implementarlo

  1. Prepara un CSV con una columna llamada Dispositivo o ten a la mano los nombres.
  2. Corre el script con -WhatIf e inicia sesión con una cuenta con el rol Help Desk Operator de Intune.
  3. Si la lista está bien, córrelo sin -WhatIf y confirma.
  4. Revisa la columna Resultado y repite los que digan Error o No encontrado en Intune.
Ver el código completo de start-analisis-antivirus.ps1
<#
.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
}

Relacionados