Saltar al contenido

¿Cómo monitorear una carpeta y activar una acción de línea de comandos cuando se crea o edita un archivo?

Solución:

En el trabajo usamos Powershell para monitorear carpetas.
Se puede utilizar desde Windows Vista (.NET y PowerShell están preinstalados) sin herramientas adicionales.

Este script monitorea una carpeta determinada y escribe un archivo de registro. Puede reemplazar la acción y hacer lo que quiera, por ejemplo, llamar a una herramienta externa

Archivo de registro de ejemplo

11/23/2014 19:22:04, Created, D:sourceNew Text Document.txt
11/23/2014 19:22:09, Changed, D:sourceNew Text Document.txt
11/23/2014 19:22:09, Changed, D:sourceNew Text Document.txt
11/23/2014 19:22:14, Deleted, D:sourceNew Text Document.txt

StartMonitoring.ps1

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "D:source"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true  

### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
    $action = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), $changeType, $path"
                Add-content "D:log.txt" -value $logline
              }    
### DECIDE WHICH EVENTS SHOULD BE WATCHED 
    Register-ObjectEvent $watcher "Created" -Action $action
    Register-ObjectEvent $watcher "Changed" -Action $action
    Register-ObjectEvent $watcher "Deleted" -Action $action
    Register-ObjectEvent $watcher "Renamed" -Action $action
    while ($true) {sleep 5}

Cómo utilizar

  1. Crea un nuevo archivo de texto
  2. Copie y pegue el código anterior
  3. Cambie la siguiente configuración según sus propias necesidades:
    • carpeta para monitorear: $watcher.Path = "D:source"
    • filtro de archivos para incluir solo ciertos tipos de archivos: $watcher.Filter = "*.*"
    • incluir subdirectorios sí / no: $watcher.IncludeSubdirectories = $true
  4. Guárdelo y cámbiele el nombre a StartMonitoring.ps1
  5. Empiece a monitorear por Haga clic derecho »Ejecutar con PowerShell

Para detener la supervisión, basta con cerrar la ventana de PowerShell

Otras lecturas

  • Documentación para FileSystemWatcher de PowerShell
  • Documentación para el evento de registro de PowerShell
  • Inspiraciones para el guion

Parece estar en las líneas correctas; podría usar el programador de tareas para ejecutar un archivo .bat o .cmd de forma regular y ese archivo podría comenzar con una línea para verificar la existencia del archivo requerido; de hecho, yo comprobaría la inexistencia del archivo; por ejemplo:

@ECHO OFF
REM Example file
IF NOT EXIST C:SOMEWHERESUBFOLDERTHISFILE.THS EXIT 1
REM All this gets done if the file exists...
:
:
EXIT 0

También puede modificar este código y hacer que se ejecute en un bucle con, digamos, 1 minuto de retraso en el bucle y luego poner una referencia al archivo por lotes en la carpeta de inicio de Windows:

@ECHO OFF
REM Example file
:LOOP    
IF NOT EXIST C:SOMEWHERESUBFOLDERTHISFILE.THS GOTO SKIP01
REM All this gets done if the file exists...
:
:
:SKIP01
REM Crafty 1 minute delay...
PING 1.1.1.1 -n 10 -w 6000 >NUL
GOTO LOOP

Hay otras formas de lograr un retraso según la versión de Windows que se esté ejecutando y los kits de recursos adicionales que se hayan instalado, pero el comando PING prácticamente funciona en todas las circunstancias. En el comando PING anterior, se ejecutan 10 PINGS fantasmas con un retraso de 6000 ms (es decir, 6 segundos) entre ellos, puede jugar con estos valores para lograr el retraso que necesita entre los bucles de archivos por lotes.

Gracias a todos por las sugerencias.

Terminé escribiendo un VBScript que se basó aproximadamente en la idea de Linker3000 de sondear la carpeta y usar el Programador de tareas para que se ejecute al inicio. Terminé obteniendo la sintaxis básica de este recurso e hice los ajustes necesarios.

Todavía me gustaría optimizarlo en algún momento, teniendo las entrañas del script ejecutándose en un sistema impulsado por eventos, pero me he quedado sin tiempo para trabajar en él y, bueno, esto es lo suficientemente bueno.

Aquí está el guión, en caso de que alguien esté interesado (con el segmento de conversión irrelevante redactado para mayor claridad):

' FOLDER TO MONITOR
strFolder = "J:monitored-folder"

' FREQUENCY TO CHECK IT, IN SECONDS
nFrequency = 10

strComputer = "."
strQueryFolder = Replace(strFolder, "", "\\")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" &     strComputer & "rootcimv2") 
Set colMonitoredEvents = objWMIService.ExecNotificationQuery ("SELECT * FROM __InstanceCreationEvent WITHIN " & nFrequency & " WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent="Win32_Directory.Name=""" & strQueryFolder & """"") 

Do 
    Set objLatestEvent = colMonitoredEvents.NextEvent
    strNewFile = objLatestEvent.TargetInstance.PartComponent
    arrNewFile = Split(strNewFile, "=")
    strFilePath = arrNewFile(1)
    strFilePath = Replace(strFilePath, "\", "")
    strFilePath = Replace(strFilePath, Chr(34), "")
    strFileName = Replace(strFilePath, strFolder, "")
    strTempFilePath = WScript.CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2) & "TEMP.M4A"

    ' DO THE OPERATION STUFF
    ' ...
Loop

(Además, no quiero dejar esta pregunta oficialmente sin respuesta, y odio aceptar mi propia respuesta a la pregunta, ¡pero voté a favor de la respuesta de Linker3000 como agradecimiento!)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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