Usa PowerShell e System.IO.FileSystemWatcher per rilevare quando un download in una cartella specifica è completo


1

Sto tentando di monitorare la mia cartella di download e di attivare un'azione della riga di comando al termine del download. Questo è molto simile ad un'altra domanda, Come monitorare una cartella e attivare un'azione della riga di comando quando un file viene creato o modificato?

Ho implementato lo script di PowerShell descritto in risposta più votata , ma quando lo eseguo, trovo che l'output sia confuso.

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "Z:\UnprocessedDownloads"
    $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 -f o), $changeType, $path"
                Add-content "Z:\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}

Devo notare che i download in questione sono stati creati da Chrome, che può o non può spiegare cosa sta succedendo. Come meglio posso dire, la serie di eventi è la seguente:

  1. Viene creato un file con il nome file desiderato.
  2. Il file precedentemente creato viene prontamente cancellato.
  3. Un file con il nome file desiderato e .crdownload aggiunto, viene creato.
  4. Questo file registra tra due e tre modifiche (dei file che ho provato, se erano pochi KB ne mostrava due, ma i file da 100 MB a 10 GB ne registravano tre).
  5. Questo file viene rinominato, rimuovendo il file .crdownload .
  6. Questo file registra quindi altre due o tre modifiche (non sono riuscito a trovare alcuna rima o ragione per quante ne sono state verificate).
  7. È fatto, nient'altro si registra senza l'intervento manuale.

Quindi, questo è quello. Sono in perdita su come posso dire che un file è veramente "fatto", a corto di forse guardare un evento di rinomina, e successivamente aspettare un numero arbitrario di secondi (a volte, l'ultima modifica registrata impiegava circa 5 secondi a si verificano - ho appena capito che questo è probabilmente dovuto al sonno 5 nella sceneggiatura), forse 10.

Qualcuno può spiegare cosa sta succedendo qui? Ci sono suggerimenti o alternative? Non sono grato a PowerShell, mi è sembrato giusto e il File System Watcher sarebbe stato adatto al compito. Preferirei qualcosa con il minimo sovraccarico possibile, pur mantenendo l'automazione.

FWIW, un estratto dai miei test (difficilmente esauriente, nota: ho aggiustato il registro per mostrare i millisecondi):

2019-01-02T22:03:03.6712039-05:00, Created, Z:\Unprocessed\test (1).jpg
2019-01-02T22:03:03.7242040-05:00, Deleted, Z:\Unprocessed\test (1).jpg
2019-01-02T22:03:03.7252054-05:00, Created, Z:\Unprocessed\test (1).jpg.crdownload
2019-01-02T22:03:03.7252054-05:00, Changed, Z:\Unprocessed\test (1).jpg.crdownload
2019-01-02T22:03:08.7265875-05:00, Changed, Z:\Unprocessed\test (1).jpg.crdownload
2019-01-02T22:03:08.7305994-05:00, Renamed, Z:\Unprocessed\test (1).jpg
2019-01-02T22:03:08.7315887-05:00, Changed, Z:\Unprocessed\test (1).jpg
2019-01-02T22:03:08.7315887-05:00, Changed, Z:\Unprocessed\test (1).jpg
2019-01-02T22:03:13.7348367-05:00, Changed, Z:\Unprocessed\test (1).jpg
2019-01-02T22:09:28.7729475-05:00, Deleted, Z:\Unprocessed\10GB.bin
2019-01-02T22:09:33.7742846-05:00, Created, Z:\Unprocessed\1GB.bin
2019-01-02T22:09:33.7762852-05:00, Deleted, Z:\Unprocessed\1GB.bin
2019-01-02T22:09:33.7772866-05:00, Created, Z:\Unprocessed\1GB.bin.crdownload
2019-01-02T22:09:33.7782853-05:00, Changed, Z:\Unprocessed\1GB.bin.crdownload
2019-01-02T22:09:33.7792825-05:00, Changed, Z:\Unprocessed\1GB.bin.crdownload
2019-01-02T22:10:28.7850646-05:00, Changed, Z:\Unprocessed\1GB.bin.crdownload
2019-01-02T22:10:28.7860648-05:00, Renamed, Z:\Unprocessed\1GB.bin
2019-01-02T22:10:28.7870652-05:00, Changed, Z:\Unprocessed\1GB.bin
2019-01-02T22:10:28.7870652-05:00, Changed, Z:\Unprocessed\1GB.bin
2019-01-02T22:10:28.7880654-05:00, Changed, Z:\Unprocessed\1GB.bin
2019-01-02T22:11:13.7928495-05:00, Created, Z:\Unprocessed\test (2).jpg
2019-01-02T22:11:13.7938482-05:00, Deleted, Z:\Unprocessed\test (2).jpg
2019-01-02T22:11:13.7938482-05:00, Created, Z:\Unprocessed\test (2).jpg.crdownload
2019-01-02T22:11:13.7948490-05:00, Changed, Z:\Unprocessed\test (2).jpg.crdownload
2019-01-02T22:11:18.7972830-05:00, Changed, Z:\Unprocessed\test (2).jpg.crdownload
2019-01-02T22:11:18.7982945-05:00, Renamed, Z:\Unprocessed\test (2).jpg
2019-01-02T22:11:18.7992839-05:00, Changed, Z:\Unprocessed\test (2).jpg
2019-01-02T22:11:18.8002947-05:00, Changed, Z:\Unprocessed\test (2).jpg
2019-01-02T22:11:23.8011169-05:00, Changed, Z:\Unprocessed\test (2).jpg

Nonostante questo codice, quando il download di un file dovrebbe essere solo uno naturalmente, ma mentre il download è in esecuzione, viene creato uno stub fino a quando non viene completato, proprio come un file .tmp viene creato quando apri Word e doe per andare via fino a quando salva e chiudi Word. Se pensi che le altre cose siano un effetto collaterale di Chrome (il che significa che hai Chrome come predefinito), prova un altro browser impostandolo come predefinito. Mi sembra che qualcosa stia influenzando il download e tu stia ricominciando da capo, quindi i file extra.
postanote

Grazie per il feedback; Mi sono reso conto che il .crdownload era un file temporaneo. Non ci sono file extra, solo modifiche extra. Sono sconcertato dal "file falso" all'inizio, e poi tutte le modifiche dopo la rinomina, mi aspetto che il rinominare sia l'ultimo passo.
Malcalevak

Mi aspetterei di rinominare, se necessario, dopo che il download del file è stato completato, o nominato prima dell'inizio del download. Non ha senso rinominare part way thru. Vedi le altre opzioni che ho suggerito di provare a vedere se sono migliori per te.
postanote

Mi aspetto che anche il cambio di nome sia completato, ecco perché sono confuso dalle modifiche in corso in seguito. Perché / cosa sta cambiando a quel punto? E sarei meno confuso se il file creato originariamente, con il nome file finale, fosse rinominato in append .crdownload , ma eliminarlo e creare un nuovo file non ha senso per me!
Malcalevak

Risposte:


0

Vedi se uno di questi funziona meglio per te.

Utilizzo di FileSystemWatcher da PowerShell

Powershell FileSystemWatcher

Oppure puoi cambiare e utilizzare BITS per i download e agire sul completamento di BITS.

Vedi questa discussione: Come eseguire script sul completamento del download BITS


Apprezzo i suggerimenti. Sto tecnicamente usando FileSystemWatcher da PowerShell, ma forse posso carpire informazioni da quelle pagine, o vedere un comportamento diverso quando li provo. Ho dovuto usare BITS di Google, ma sembra che coinvolgerlo potrebbe complicare eccessivamente il processo di download.
Malcalevak

0

Dai un colpo. Ho modificato l'originale per includere la logica aggiuntiva. Non sono sicuro di quale sarà la prova a prova di proiettile. Fammi sapere come regge.

# create an array that tracks each file
$global:files = @()
# where we will move the file once it is free
$destination = "C:\destination"

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\source"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true  

$action = {
    $path = $Event.SourceEventArgs.FullPath
    $changeType = $Event.SourceEventArgs.ChangeType
    $logline = "$(Get-Date -f o), $changeType, $path"
    Add-content "C:\log.txt" -value $logline
    Write-Host $logline

    if($changeType -eq "Renamed" -and $path.Split(".")[-1] -ne "crdownload") {
        Write-Host -ForegroundColor Green "Found the file we need! $path"
        Add-content "C:\log.txt" -value "Found the file we need! $path"
        $global:files += $path
    }
}    

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) {

    # if there are any files to process, check if they are locked
    if($global:files) {

        $global:files | % {

            $file = $_
            # assume the file is locked
            $fileFree = $false

            Write-Host -ForegroundColor Yellow "Checking if the file is locked... ($file)"
            Add-content "C:\log.txt" -value "Checking if the file is locked... ($_)"

            # true  = file is free
            # false = file is locked
            try {
                [IO.File]::OpenWrite($file).close();Write-Host -ForegroundColor Green "File is free! ($file)"
                Add-content "C:\log.txt" -value "File is free! ($file)"
                $fileFree = $true
            }
            catch {
                Write-Host -ForegroundColor Red "File is Locked ($file)"
                Add-content "C:\log.txt" -value "File is Locked ($file)"
            }

            if($fileFree) {

                # do what we want with the file, since it is free
                Move-Item $file $destination
                Write-Host -ForegroundColor Green "Moving file ($file)"
                Add-content "C:\log.txt" -value "Moving file ($file)"

                # make sure we don't progress until the file has finished moving
                while(Test-Path $file) {
                    Sleep 1
                }

                # remove the current file from the array
                Write-Host -ForegroundColor Green "Done processing this file. ($file)"
                Add-content "C:\log.txt" -value "Done processing this file. ($file)"
                $global:files = $global:files | ? { $_ -ne $file }
            }

        }
    }

    sleep 2
}
  • Questo ascolterà per a Renamed evento in cui l'estensione del file non è "crdownload", aiutandoci a ottenere il percorso / file / estensione effettivo e non le informazioni del file temporaneo. Quando viene trovata una corrispondenza, questa viene archiviata in una matrice, consentendoci di lavorare con più file contemporaneamente.
  • Una volta che la matrice contiene uno o più nomi di file, ciascun file viene controllato per vedere se è attualmente bloccato o se è gratuito. Se è gratuito, viene spostato in $destination. È possibile modificare l'azione desiderata da a Move-Item a qualsiasi cosa tu voglia.
  • Una volta che un file è stato spostato correttamente, viene rimosso dall'array.

Sappi che il multiplo Changed gli eventi che stai vedendo devono essere previsto (e si verifica anche per me durante il download da Chrome):

Le operazioni comuni del file system possono generare più di un evento. Per   esempio, quando un file viene spostato da una directory a un'altra, diversi   OnChanged e alcuni eventi OnCreated e OnDeleted potrebbero essere generati.   Lo spostamento di un file è un'operazione complessa costituita da più elementi semplici   operazioni, sollevando quindi più eventi. Allo stesso modo, alcuni   le applicazioni (ad esempio il software antivirus) potrebbero causare ulteriori problemi   eventi del file system rilevati da FileSystemWatcher.

Si consiglia di rimuovere il aggiunto Write-Host Linee. Si può anche voler aggiungere il seguente in un arresto di terminazione per terminare con garbo gli eventi registrati:

Get-EventSubscriber | ? { $_.EventName -in "Created","Changed","Deleted","Renamed" } | Unregister-Event

Ispirazione .

Verifica se un file è bloccato .


Grazie per questo! Apprezzo in particolare l'estratto su come le operazioni comuni del file system possono generare più di un evento come sospettavo che tutto fosse tecnicamente "atteso", ma vedere la documentazione a riguardo è sicuramente rassicurante. Stavo anche speculando che il mio software antivirus potrebbe essere stato responsabile dell'evento "Changed" a volte ritardato. Mentre ho trovato una soluzione praticabile, sembra che potrebbe essere più elegante, insieme alla gestione di più file, quindi cercherò di adattarlo alle mie esigenze di conseguenza e tornare a te (e dare credito).
Malcalevak
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.