3

Я пытаюсь создать сценарий PowerShell для записи в текстовый файл, если новый файл не был создан в папке Windows (C:\Test) по истечении определенного периода времени. В качестве основы я использую сценарий, показанный здесь. Ниже мой модифицированный скрипт.

Как вы можете видеть, я добавил оператор IF-ELSE, который проверяет, было ли последнее создание файла более 10 секунд назад. Я также изменил $action чтобы присвоить текущую метку времени $lasttimefilecreated и сбросить $logflag . Однако, похоже, что $ action не выполняет ни одну из этих двух вещей. Add-content "C:\FileCreated.txt" успешно выполняется, и файл создается, но значения $lasttimefilecreated и $logflag остаются неизменными и не выводятся на консоль. Есть ли другой способ сделать это? Я просмотрел статью Microsoft об объекте Register-ObjectEvent, но не смог понять, почему блок сценария, который я назначаю для $ action, не работает полностью. Ценю твою помощь!

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

### INITIALIZE VARIABLES
$lasttimefilecreated = $(Get-Date)
$logflag = 0
$action = { $lasttimefilecreated = $(Get-Date)
            "$lasttimefilecreated"
            $logflag = 0
            "$logflag"
            $path = $Event.SourceEventArgs.FullPath
            $changeType = $Event.SourceEventArgs.ChangeType
            $logline = "$(Get-Date), $changeType, $path"
            Add-content "C:\FileCreated.txt" -value $logline
          }

### DECIDE WHICH EVENTS SHOULD BE WATCHED + LOOP INDEFINITELY THROUGH IF-ELSE LOGIC  
$created = Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {
        if ((New-TimeSpan -Start $lasttimefilecreated –End $(Get-Date)).Seconds -gt 10 -and $logflag -eq 0) {
        $logflag = 1
        Add-content "C:\Log.txt" -value "$(Get-Date)"
        "Log.txt file created/modified at $(Get-Date)"
        }
        else {sleep 5}}

2 ответа2

2

Вы столкнулись с двумя различными сюрпризами PowerShell.

Первый: обзор. Когда вы изменяете переменную из вашего обработчика событий, вы устанавливаете только новую переменную, которая существует только внутри этого блока. В качестве простого тестового примера, набрав это на консоли, получим 1:

$a = 1; {$a = 2}.Invoke(); $a

Чтобы указать, что вы назначаете глобальную область видимости, добавьте global: к имени переменной. Это печатает 2:

$a = 1; {$global:a = 2}.Invoke(); $a

Второе: перенаправление вывода события. Когда вы создаете результаты из обработчика событий, он фактически сохраняется в объекте задания. Чтобы печатать на консоль, используйте Write-Host вместо (неявного) Write-Output . Например:

Write-Host $lasttimefilecreated

Вы можете рассмотреть возможность использования таймера вместо цикла, например так:

$timer = New-Object System.Timers.Timer
$timer.Interval = 5000
$timer.Enabled = $true
Register-ObjectEvent $timer 'Elapsed' -Action {
    If ($global:logflag -eq 0) {
        $global:logflag = 1
        Add-content "C:\Log.txt" -value "$(Get-Date)"
        Write-Host "Log.txt file created/modified at $(Get-Date)"
    }
}
$timer.AutoReset = $true
$timer.Start()
while ($true) {Start-Sleep -Seconds 5}

Последний цикл просто препятствует выходу скрипта. Таймеры продолжат работать, если остановятся, но выглядит немного странно.

0

если вы выполняете из ISE перед первым сохранением, он запустит код, который вы ввели в окне скрипта, как если бы вы ввели его в командной строке, и вы не можете использовать область действия «$ script:», но после сохранения вместо этого он выполнит файл .ps1, и в сценарии будет применена область «$ script:» (она не изменит переменные в сеансе ise, но изменит их в ходе выполнения сценария и сценариев). точка зрения, учитывая, что глобальная область, область, в которой был запущен сценарий, если вы используете область «$ global:», она влияет на сценарий, а также на переменные в сеансе ise (глобальная область, из которой был создан сценарий). называется). Я надеюсь, что это устранит разницу, поэтому для сценария не имеет значения, какую из этих областей вы используете, но важно для консоли, из которой вызывается сценарий.

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