Powershell - прослушивание файла, что-то делать, если файл существует [дубликат]

Короткий ответ: вам нужно выполнить обратный вызов следующим образом:

function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
}

$.ajax({
    url: "...",
    success: callback
});
11
задан IGRACH 4 April 2015 в 16:34
поделиться

7 ответов

Вот еще один вариант.

Мне просто нужно было написать свой собственный, чтобы смотреть и запускать тесты в контейнере Docker. Решение Jan намного более изящно, но FileSystemWatcher в настоящее время разбит на контейнеры Docker. Мой подход похож на Василия, но гораздо более ленивый, доверяя времени записи файловой системы.

Вот функция, которая мне нужна, которая запускает командный блок каждый раз, когда файл изменяется.

function watch($command, $file) {
    $this_time = (get-item $file).LastWriteTime
    $last_time = $this_time
    while($true) {
        if ($last_time -ne $this_time) {
            $last_time = $this_time
            invoke-command $command
        }
        sleep 1
        $this_time = (get-item $file).LastWriteTime
    }
}

Вот один, который ждет, пока файл не изменится, запустит блок, а затем выйдет.

function waitfor($command, $file) {
    $this_time = (get-item $file).LastWriteTime
    $last_time = $this_time
    while($last_time -eq $this_time) {
        sleep 1
        $this_time = (get-item $file).LastWriteTime
    }
    invoke-command $command
}
0
ответ дан bjtucker 31 August 2018 в 20:18
поделиться

Вы можете использовать System.IO.FileSystemWatcher для контроля файла.

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

См. также в этой статье

4
ответ дан bytecode77 31 August 2018 в 20:18
поделиться

Вот решение, на котором я закончил, основываясь на нескольких предыдущих ответах здесь. Я специально хотел:

  1. Мой код для кода, а не строка
  2. Мой код для запуска в потоке ввода-вывода, чтобы я мог видеть вывод консоли
  3. Мой код, который будет вызываться каждый раз, когда произошли изменения, а не один раз

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

Function RunMyStuff {
    # this is the bit we want to happen when the file changes
    Clear-Host # remove previous console output
    & 'C:\Program Files\erl7.3\bin\erlc.exe' 'program.erl' # compile some erlang
    erl -noshell -s program start -s init stop # run the compiled erlang program:start()
}

Function Watch {    
    $global:FileChanged = $false # dirty... any better suggestions?
    $folder = "M:\dev\Erlang"
    $filter = "*.erl"
    $watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ 
        IncludeSubdirectories = $false 
        EnableRaisingEvents = $true
    }

    Register-ObjectEvent $Watcher "Changed" -Action {$global:FileChanged = $true} > $null

    while ($true){
        while ($global:FileChanged -eq $false){
            # We need this to block the IO thread until there is something to run 
            # so the script doesn't finish. If we call the action directly from 
            # the event it won't be able to write to the console
            Start-Sleep -Milliseconds 100
        }

        # a file has changed, run our stuff on the I/O thread so we can see the output
        RunMyStuff

        # reset and go again
        $global:FileChanged = $false
    }
}

RunMyStuff # run the action at the start so I can see the current output
Watch

Вы могли бы передать папку / фильтр / действие в часы, если хотите что-то более общее. Надеюсь, это полезная отправная точка для кого-то еще.

3
ответ дан Ed' 31 August 2018 в 20:18
поделиться

Я добавлю еще один ответ, потому что мой предыдущий пропустил требования.

Требования

  • Напишите функцию WAIT для изменения определенного файла
  • Когда обнаружено изменение, функция выполнит предопределенную команду и вернется к главному скрипту
  • Путь файла и команда передаются функции как параметры

Уже есть ответ с использованием хэшей файлов. Я хочу выполнить свой предыдущий ответ и показать, как это можно выполнить с помощью FileSystemWatcher.

$File = "C:\temp\log.txt"
$Action = 'Write-Output "The watched file was changed"'
$global:FileChanged = $false

function Wait-FileChange {
    param(
        [string]$File,
        [string]$Action
    )
    $FilePath = Split-Path $File -Parent
    $FileName = Split-Path $File -Leaf
    $ScriptBlock = [scriptblock]::Create($Action)

    $Watcher = New-Object IO.FileSystemWatcher $FilePath, $FileName -Property @{ 
        IncludeSubdirectories = $false
        EnableRaisingEvents = $true
    }
    $onChange = Register-ObjectEvent $Watcher Changed -Action {$global:FileChanged = $true}

    while ($global:FileChanged -eq $false){
        Start-Sleep -Milliseconds 100
    }

    & $ScriptBlock 
    Unregister-Event -SubscriptionId $onChange.Id
}

Wait-FileChange -File $File -Action $Action
6
ответ дан Jan Chrbolka 31 August 2018 в 20:18
поделиться

Вот пример, который я нашел в своих отрывках. Надеюсь, что это немного более полно.

Сначала вам нужно создать наблюдателя файловой системы, а затем вы подписаться на событие, которое генерирует наблюдатель. Этот пример прослушивает события «Создать», но может быть легко изменен, чтобы следить за «Изменить».

$folder = "C:\Users\LOCAL_~1\AppData\Local\Temp\3"
$filter = "*.LOG"
$Watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ 
    IncludeSubdirectories = $false
    NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
   $path = $Event.SourceEventArgs.FullPath
   $name = $Event.SourceEventArgs.Name
   $changeType = $Event.SourceEventArgs.ChangeType
   $timeStamp = $Event.TimeGenerated
   Write-Host "The file '$name' was $changeType at $timeStamp"
   Write-Host $path
   #Move-Item $path -Destination $destination -Force -Verbose
}

Я попытаюсь сузить это до ваших требований.

Если вы запустите это как часть своего скрипта «profile.ps1», вы должны прочитать «Сила профилей» , в которой объясняются различные доступные скрипты профилей и многое другое.

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

Что это значит, это зарегистрировать фрагмент кода, который будет выполняться каждый раз при срабатывании события. Этот код будет выполнен в контексте текущего хоста PowerShell (или оболочки), пока сеанс остается открытым. Он может взаимодействовать с хостом, но не знает исходного скрипта, который зарегистрировал код. Возможно, исходный скрипт уже завершен, к моменту запуска вашего кода.

Вот код:

Function Register-Watcher {
    param ($folder)
    $filter = "*.*" #all files
    $watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ 
        IncludeSubdirectories = $false
        EnableRaisingEvents = $true
    }

    $changeAction = [scriptblock]::Create('
        # This is the code which will be executed every time a file change is detected
        $path = $Event.SourceEventArgs.FullPath
        $name = $Event.SourceEventArgs.Name
        $changeType = $Event.SourceEventArgs.ChangeType
        $timeStamp = $Event.TimeGenerated
        Write-Host "The file $name was $changeType at $timeStamp"
    ')

    Register-ObjectEvent $Watcher "Changed" -Action $changeAction
}

 Register-Watcher "c:\temp"

После запуска этого кода измените любой файл в поле «C : \ temp "(или любой другой каталог, который вы указали). Вы увидите событие, запускающее выполнение вашего кода.

Кроме того, действительные события FileSystemWatcher, которые вы можете зарегистрировать, - «Изменены», «Созданы», «Удалены» и «Переименованы».

23
ответ дан Matt 31 August 2018 в 20:18
поделиться
  1. Вычислить хэш списка файлов
  2. Сохранить его в словаре
  3. Проверить каждый хэш на интервале
  4. Выполнить действие при хеше
  5. [hr>
    function watch($f, $command, $interval) {
        $sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
        $hashfunction = '[System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file)))'
        $files = @{}
        foreach ($file in $f) {
            $hash = iex $hashfunction
            $files[$file.Name] = $hash
            echo "$hash`t$($file.FullName)"
        }
        while ($true) {
            sleep $interval
            foreach ($file in $f) {
                $hash = iex $hashfunction
                if ($files[$file.Name] -ne $hash) {
                    iex $command
                }
            }
        }
    }
    

    Пример использования:

    $c = 'send-mailmessage -to "admin@whatever.com" -from "watch@whatever.com" -subject "$($file.Name) has been altered!"'
    $f = ls C:\MyFolder\aFile.jpg
    
    watch $f $c 60
    
3
ответ дан Vasili Syrakis 31 August 2018 в 20:18
поделиться

У меня была аналогичная проблема. Сначала я хотел использовать события Windows и зарегистрироваться, но это было бы менее отказоустойчиво, как решение под ним. Моим решением был сценарий опроса (интервалы в 3 секунды). Скрипт имеет минимальный след в системе и очень быстро замечает изменения. Во время цикла мой скрипт может делать больше вещей (на самом деле я проверяю 3 разных папки).

Мой сценарий опроса запускается через диспетчер задач. Расписание запускается каждые 5 минут с остановкой флага, когда он уже работает. Таким образом, он перезапустится после перезагрузки или после сбоя. Использование диспетчера задач для опроса каждые 3 секунды является слишком частым для диспетчера задач. Когда вы добавляете задачу в планировщик, убедитесь, что вы не используете сетевые диски (которые вызывают дополнительные настройки) и предоставляют свои пользовательские пакетные привилегии.

Я даю сценарию чистый старт, отключив его за несколько минут до полуночи. Менеджер задач запускает скрипт каждое утро (функция init моего скрипта выйдет 1 минуту около полуночи).

2
ответ дан Walter A 31 August 2018 в 20:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: