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

82

Necesito configurar algún tipo de script en mi máquina Vista, para que cada vez que se agregue un archivo a una carpeta en particular, se active automáticamente un proceso en segundo plano que opera en el archivo. (El proceso en segundo plano es solo una utilidad de línea de comandos que toma el nombre del archivo como argumento, junto con algunas otras opciones predefinidas).

Me gustaría hacer esto usando las características nativas de Windows, si es posible, por razones de rendimiento y mantenimiento. He investigado el uso del Programador de tareas, pero después de examinar el sistema de activación durante un tiempo, no he podido darle mucho sentido, y ni siquiera estoy seguro de si es capaz de hacer lo que necesito.

Agradecería cualquier sugerencia. ¡Gracias!

bigmattyh
fuente
Parece que necesitas algo como inotify de Linux, pero para Windows. Jnotify podría ayudar, pero dado que es Java podría ser demasiado pesado.
Keith
1
También me preguntaba sobre esto ... encontré la [página de MSDN] ( msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx) .
Keith
2
El enlace anterior tiene) después de aspx: msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx
Dom

Respuestas:

92

En el trabajo usamos Powershell para monitorear carpetas.
Se puede usar 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

23/11/2014 19:22:04, creado, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, modificado, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, modificado, D: \ source \ New Text Document.txt
23/11/2014 19:22:14, eliminado, D: \ source \ New 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 las siguientes configuraciones a sus propias necesidades:
    • carpeta para monitorear: $watcher.Path = "D:\source"
    • filtro de archivo para incluir solo ciertos tipos de archivos: $watcher.Filter = "*.*"
    • incluir subdirectorios sí / no: $watcher.IncludeSubdirectories = $true
  4. Guardar y renombrarlo a StartMonitoring.ps1
  5. Comience a monitorear haciendo clic derecho »Ejecutar con PowerShell

Para detener la supervisión, es suficiente cerrar la ventana de PowerShell

Otras lecturas

nixda
fuente
Funciona bien, pero ¿cuál es la función del script de detención? Recibo errores: "Evento de registro: no se puede vincular el argumento al parámetro 'SourceIdentifier' porque es nulo". pastebin.com/ugLB3a69
Jan Stanstrup
@ JanStanstrup Probablemente confundí a más personas con el segundo script. Lo borraré Es suficiente simplemente cerrar la StartWatching.ps1ventana para detener el monitoreo. El segundo script sólo funciona si se incluye en su primera secuencia de comandos para guardar las variables $created, $changed, $deletedo$renamed
nixda
Gracias por la respuesta. ¿Alguien puede sugerir si podríamos usar cmd prompt ya que quiero cargar los archivos a github cuando se cambian
M__
5

Parece que está en la línea correcta: 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:\SOMEWHERE\SUBFOLDER\THISFILE.THS EXIT 1
REM All this gets done if the file exists...
:
:
EXIT 0

También puede modificar este código y ejecutarlo en un bucle con, por ejemplo, 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:\SOMEWHERE\SUBFOLDER\THISFILE.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 de acuerdo con la versión de Windows en ejecución y los kits de recursos adicionales que se han instalado, pero el comando PING funciona prácticamente 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 archivo por lotes.

Linker3000
fuente
buena idea ... por cierto, C: \> ping 1.1.1.1 -n 10 -w 6000 por alguna razón tomó 1 minuto y 10 segundos en mi computadora. pero -n 1 -w 60000 tomó 1 minuto exactamente.
barlop
@barlop - los diez segundos discrepancia se debe a la -n 10frente -n 1.
@Randolph Potter ¿No son 10 lotes de 6 segundos, 60 segundos? y -n 10 que use, debería significar 10 veces.
barlop
Probablemente tengas razón. Lo retiro y culpo a mi cabello rubio.
Terminé usando este bucle para un lote de monitoreo IF NOT EXIST C:\NO_SUCH_FILE_EVER.foo. Hackish, pero funciona. Gracias por la idea
Snekse 01 de
3

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 agallas del script ejecutadas en un sistema controlado por eventos, pero me he quedado sin tiempo para trabajar en ello, y, bueno, esto es lo suficientemente bueno.

Aquí está el script, 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 & "\root\cimv2") 
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é por la respuesta de Linker3000 como agradecimiento!)

bigmattyh
fuente
2

Puede mirar DropIt (gratis). El programa es apropiado para procesar archivos entrantes de manera automatizada. Puede mover, copiar, eliminar y pasar parámetros a otros programas de línea de comandos para convertir imágenes, dividir archivos PDF, etc.

Dom
fuente
2

Si la acción es solo para copiar archivos modificados, puede usar robocopy / MON

No sé si robocopy utiliza FileSystemWatcher o si trabaja para sondear los cambios

weberjn
fuente
1

O puede usar Watch 4 Folder . Aparentemente es Freeware, portátil y compatible con Windows 7. No lo he probado, pero lo encontré a través de una búsqueda en la web y pensé en pasarlo.

También me gusta el script VBS, también presentado en el sitio.

Chris
fuente
Desafortunadamente, solo la versión paga es portátil
nixda
Estaba pensando en usar este software. ¿Confía en que supervisará un recurso compartido de red con archivos importantes de muchos usuarios?
Paul Matthews
La versión gratuita de Watch4Folder tiene solo una entrada de "muestra" que se puede configurar.
PeterCo
0

Utilizamos la herramienta comercial (es decir, no gratuita) Folder Poll de http://www.myassays.com/folder-poll para hacer justamente esto. Es una aplicación de Windows que incluye una aplicación de administrador fácil de usar para permitir una configuración fácil. Además, hay una opción de configuración XML. El sondeo de la carpeta real se ejecuta como un servicio de Windows (por lo que se inicia automáticamente en cada reinicio). Cuando se detecta un nuevo archivo en una carpeta encuestada, se puede iniciar automáticamente una aplicación (puede especificar sus propios argumentos de línea de comandos personalizados). También puede hacer otras cosas como copiar / mover archivos. Además, la actividad se puede registrar en un archivo de registro y hay otras operaciones avanzadas.

Señor cocinero
fuente