Operación avanzada del Programador de tareas y control de desencadenadores

Descripción general

Este artículo explica técnicas avanzadas de automatización con el Programador de tareas de Windows.
Se cubren desencadenadores condicionales, ejecución basada en registros de eventos, registro y control de tareas con PowerShell y un enfoque operativo con criterios de seguridad.

Convención de variables

Variable Ejemplo Nota
<<TASK_NAME>> Daily-Backup Nombre de la tarea
<<SCRIPT_PATH>> C:\Scripts\backup.ps1 Ruta del script
<<EVENT_ID>> 4625 ID de evento objetivo
<<USERNAME>> Administrator Usuario que ejecuta la tarea
<<TASK_PATH>> \MyCompany\Maintenance Carpeta de registro de la tarea (opcional)

Paso 1: Registro de la tarea y configuración básica

Para registrar tareas con PowerShell, combina principalmente estos tres cmdlets:

Cmdlet Rol principal
New-ScheduledTaskAction Define el programa o script a ejecutar
New-ScheduledTaskTrigger Define el momento de ejecución (hora/evento)
Register-ScheduledTask Registra la tarea completa (Action + Trigger + Settings)

① Opciones de New-ScheduledTaskAction

Opción Descripción Ejemplo
-Execute Ejecutable "powershell.exe"
-Argument Argumentos de línea de comandos "-NoProfile -NonInteractive -ExecutionPolicy Bypass -File <<SCRIPT_PATH>>"
-WorkingDirectory Directorio de trabajo "C:\Scripts"
-Id Identificador de la acción (si hay varias) "Action1"

💡 Para varias acciones, crea múltiples objetos New-ScheduledTaskAction y pásalos como matriz.


② Opciones de New-ScheduledTaskTrigger

Opción Descripción Ejemplo
-Daily Ejecución diaria junto con -At 3:00AM
-Weekly Ejecución semanal -DaysOfWeek Monday,Wednesday
-Once Una sola vez -At (Get-Date).AddHours(1)
-AtStartup Al iniciar el sistema
-AtLogOn Al iniciar sesión
-RepetitionInterval Intervalo de repetición (New-TimeSpan -Minutes 30)
-RepetitionDuration Duración total de la repetición (New-TimeSpan -Days 1)
-RandomDelay Retardo aleatorio (New-TimeSpan -Minutes 5)
-StartBoundary / -EndBoundary Periodo de validez "2025-01-01T00:00:00"

⚠️ -RepetitionInterval y -RepetitionDuration solo aplican a algunos tipos de desencadenador (p. ej., Daily/Once).


③ New-ScheduledTaskSettingsSet (opcional)

Opción Descripción Ejemplo
-AllowStartIfOnBatteries Permitir ejecución con batería $false
-DontStopIfGoingOnBatteries Continuar si pasa a batería $false
-StartWhenAvailable Iniciar cuando sea posible $true
-Hidden Ocultar la tarea $true
-RunOnlyIfNetworkAvailable Requiere red disponible $true
-ExecutionTimeLimit Tiempo máximo de ejecución (New-TimeSpan -Hours 2)
-MultipleInstances Política de instancias múltiples (IgnoreNew/Parallel/Queue) "IgnoreNew"
-RestartCount / -RestartInterval Reintentos e intervalo 3, (New-TimeSpan -Minutes 5)

💡 New-ScheduledTaskSettingsSet genera el objeto de configuración que se pasa a -Settings, centralizando energía, red y reintentos.


④ Opciones de Register-ScheduledTask

Opción Descripción Ejemplo
-TaskName Nombre de la tarea "Daily-Backup"
-TaskPath Carpeta de la tarea "\MyCompany\Maintenance"
-Action Acción(es) definida(s) $action
-Trigger Desencadenador(es) definido(s) $trigger
-Settings Configuraciones adicionales $settings
-Description Descripción administrativa "Daily maintenance backup task"
-User Cuenta de ejecución "SYSTEM" o "Administrator"
-RunLevel Nivel de privilegios Highest
-Force Sobrescribe si ya existe

💡 La tarea completa resulta de combinar Action, Trigger y Settings.


⑤ Ejemplo de configuración

# Acción
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
  -Argument "-NoProfile -ExecutionPolicy Bypass -File <<SCRIPT_PATH>>"

# Desencadenador (diariamente a las 03:00)
$trigger = New-ScheduledTaskTrigger -Daily -At 3:00AM

# Registro
Register-ScheduledTask -TaskName "<<TASK_NAME>>" `
  -TaskPath "<<TASK_PATH>>\Daily" `
  -Action $action -Trigger $trigger `
  -User "<<USERNAME>>" -Description "Tarea programada diaria a las 03:00"

⑥ Puntos de atención

  • Usa -ExecutionPolicy Bypass solo internamente; valora firmar scripts.
  • Prioriza SYSTEM o una cuenta de servicio dedicada.
  • El mínimo -RepetitionInterval es 1 minuto; el límite por defecto de -RepetitionDuration es 1 día.
  • Para sobrescribir, especifica -Force.
  • -RunLevel Highest solo para rutinas que requieran privilegios de administrador.

Paso 2: Ejecución activada por eventos (con plantilla XML)

New-ScheduledTaskTrigger de PowerShell aún no acepta desencadenadores por evento (p. ej., -OnEvent).
Para usar eventos, importa una definición XML.

Registro:

$xml = @'
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Author><<USERNAME>></Author>
    <Description>Ejecutar script cuando ocurra la EventID <<EVENT_ID>></Description>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription><![CDATA[
        <QueryList>
          <Query Id="0" Path="Security">
            <Select Path="Security">*[System[(EventID=<<EVENT_ID>>)]]</Select>
          </Query>
        </QueryList>
      ]]></Subscription>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>SYSTEM</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
      <Arguments>-NoProfile -ExecutionPolicy Bypass -File "<<SCRIPT_PATH>>"</Arguments>
    </Exec>
  </Actions>
</Task>
'@

Register-ScheduledTask -TaskName "<<TASK_NAME>>" -TaskPath "<<TASK_PATH>>\OnEvent" -Xml $xml -User "SYSTEM"

Paso 3: Combinación de desencadenadores y condiciones de ejecución

Define las “condiciones” de la tarea (energía, red, inactividad) con New-ScheduledTaskSettingsSet.

$settings = New-ScheduledTaskSettingsSet `
  -AllowStartIfOnBatteries:$false `
  -DontStopIfGoingOnBatteries:$false `
  -StartWhenAvailable:$true `
  -Hidden:$false `
  -RunOnlyIfNetworkAvailable:$true `
  -ExecutionTimeLimit (New-TimeSpan -Hours 2)

Register-ScheduledTask -TaskName "<<TASK_NAME>>_Cond" `
  -TaskPath "<<TASK_PATH>>\Conditional" `
  -Action $action -Trigger $trigger -Settings $settings `
  -User "<<USERNAME>>" -Description "Tarea condicional (requiere red / alimentación AC)"

Ejemplos de condiciones

Condición Parámetro Descripción
Solo con alimentación AC -AllowStartIfOnBatteries:$false No se ejecuta con batería
Red obligatoria -RunOnlyIfNetworkAvailable:$true Omite si no hay conectividad
Ejecutar solo en idle XML o COM Soporte nativo limitado en PowerShell
Tiempo máximo de ejecución -ExecutionTimeLimit Evita procesos descontrolados
Reintentos Edición vía XML o trigger de repetición Algunas limitaciones en PowerShell puro

Paso 4: Control de tareas existentes

Gestiona y supervisa tareas operativas desde PowerShell.

# Listado de tareas
Get-ScheduledTask | Where-Object TaskPath -like "<<TASK_PATH>>*"

# Habilitar / deshabilitar
Enable-ScheduledTask -TaskName "<<TASK_NAME>>"
Disable-ScheduledTask -TaskName "<<TASK_NAME>>"

# Estado de ejecución
Get-ScheduledTaskInfo -TaskName "<<TASK_NAME>>" |
  Select-Object TaskName, NextRunTime, LastRunTime, LastTaskResult

Habilitar el registro operacional (Operational)

El canal Microsoft-Windows-TaskScheduler/Operational puede estar deshabilitado por defecto.
Habilítalo para troubleshooting e historial detallado.

wevtutil sl Microsoft-Windows-TaskScheduler/Operational /e:true

Paso 5: Solución de problemas y verificación de logs

Procedimiento cuando la tarea no se comporta como se espera.

# Último resultado de ejecución
Get-ScheduledTaskInfo -TaskName "<<TASK_NAME>>"

# Consultar el log operacional del Programador de tareas
Get-WinEvent -LogName "Microsoft-Windows-TaskScheduler/Operational" -MaxEvents 50 |
  Where-Object { $_.Message -match "<<TASK_NAME>>" } |
  Select-Object TimeCreated, Id, Message | Format-Table -AutoSize

Causas frecuentes y medidas

Causa Acción
Falta de privilegios Revisar permisos / usar cuenta de servicio
ExecutionPolicy bloquea Script firmado o -ExecutionPolicy Bypass
Falta TaskPath/descripción Definir -TaskPath y -Description para una gestión clara
Desencadenador por evento no funciona Validar XML y filtro del evento
Condiciones en conflicto Revisar lógica de triggers y condiciones

Paso 6: Ajustes recomendados

  • Usa SYSTEM o cuenta de servicio dedicada siguiendo el principio de mínimo privilegio.
  • Añade logging y manejo de excepciones a los scripts; registra éxito/fallo.
  • Versiona las definiciones de tareas como plantillas XML (p. ej., GitHub).
  • Supervisa periódicamente con Get-ScheduledTaskInfo y genera alertas ante anomalías.
  • Elimina tareas obsoletas con Unregister-ScheduledTask y mantén limpia la biblioteca.

Conclusión

El Programador de tareas de Windows va más allá de las ejecuciones cronometradas.
Con desencadenadores por eventos, ejecución condicional e integración con PowerShell, se convierte en una plataforma de automatización potente.
Al estandarizar el registro, la gestión y la monitorización mediante código, obtienes reproducibilidad, gobernanza y seguridad operativa.