1

Я пытаюсь проследить за моей папкой загрузки и вызвать действие командной строки, когда загрузка завершена. Это очень похоже на другой вопрос:как отслеживать папку и запускать действие командной строки при создании или редактировании файла?

Я реализовал сценарий PowerShell, описанный в ответе с наибольшим количеством голосов, но когда я запускаю его, я обнаруживаю, что вывод вводит в заблуждение.

### 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}

Следует отметить, что данные загрузки создаются Chrome, что может объяснять или не объяснять, что происходит. Как я могу сказать, серия событий выглядит следующим образом:

  1. Файл с намеченным именем файла создан.
  2. Ранее созданный файл будет немедленно удален.
  3. Создается файл с предполагаемым именем файла и добавленной .crdownload.
  4. Этот файл регистрирует от двух до трех изменений (из протестированных мною файлов, если он был размером в несколько КБ, он показал два, а для файлов от 100 МБ до 10 ГБ было зарегистрировано три).
  5. Этот файл переименовывается, удаляя .crdownload.
  6. Этот файл затем регистрирует дополнительные два-три изменения (я не смог найти рифму или причину того, как много произошло).
  7. Это сделано, больше ничего не регистрируется без ручного вмешательства.

Так вот и все. Я в растерянности относительно того, как я могу сказать, что файл действительно "готов", за исключением, возможно, наблюдения за событием переименования и последующего ожидания произвольного числа секунд (иногда последнее записанное изменение занимало около 5 секунд, чтобы происходит - я только что понял, что это, вероятно, из-за сна 5 в сценарии), возможно, 10.

Кто-нибудь может объяснить, что здесь происходит? Есть какие-нибудь предложения или альтернативы? Я не обязан PowerShell, просто мне показалось, что File System Watcher хорошо подходит для этой задачи. Я бы предпочел что-то с минимальными накладными расходами при сохранении автоматизации.

FWIW, выдержка из моих тестов (вряд ли обширная; обратите внимание - я действительно настроил журнал, чтобы показывать миллисекунды):

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

2 ответа2

0

Дайте этому шанс. Я изменил оригинал, чтобы включить дополнительную логику. Не уверен, насколько пуленепробиваемым это будет. Дайте мне знать, как это работает.

# 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
}
  • Это будет слушать Renamed случае , когда расширение файла не "crdownload", чтобы помочь нам получить фактический путь / файл / расширение , а не временную информацию файла. Когда совпадение найдено, оно сохраняется в массиве, что позволяет нам работать с несколькими файлами одновременно.
  • Если массив содержит одно или несколько имен файлов, каждый файл проверяется, чтобы убедиться, что он в данный момент заблокирован или свободен. Если он бесплатный, он перемещается в $destination . Вы можете изменить желаемое действие с Move-Item на любое другое.
  • После успешного перемещения файла он удаляется из массива.

Знайте, что ожидаемые вами события Changed ожидаются (а также происходят для меня при загрузке из Chrome):

Обычные операции файловой системы могут вызывать более одного события. Например, когда файл перемещается из одного каталога в другой, могут возникнуть несколько событий OnChanged и некоторые события OnCreated и OnDeleted. Перемещение файла - это сложная операция, которая состоит из нескольких простых операций, поэтому вызывает несколько событий. Аналогично, некоторые приложения (например, антивирусное программное обеспечение) могут вызывать дополнительные события файловой системы, которые обнаруживаются FileSystemWatcher.

Вы можете удалить добавленные строки Write-Host . Вы также можете добавить следующее в прерывание для корректного завершения зарегистрированных событий:

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

Вдохновение

Проверка, если файл заблокирован.

0

Посмотрите, будет ли один из них лучше для вас.

Использование FileSystemWatcher из PowerShell

Powershell FileSystemWatcher

Или вы можете переключаться и использовать BITS для загрузки и выполнять действия по завершению BITS.

Смотрите это обсуждение:Как запустить скрипт на завершении загрузки BITS

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .