PowerShell: Limitações do ScriptBlock no RegisterEventEvent

3

Estou tentando criar um script do PowerShell para gravar em um arquivo de texto se nenhum novo arquivo tiver sido gerado em uma pasta do Windows (C: \ Test) após um determinado período de tempo. Como base, estou usando o script mostrado aqui . Abaixo está meu script modificado.

Como você pode ver, adicionei uma instrução IF-ELSE que verifica se a última criação de arquivo ocorreu há mais de 10 segundos. Também modifiquei $action para atribuir o registro de data e hora atual a $lasttimefilecreated e redefinir $logflag . No entanto, parece que $ action não executa nenhuma dessas duas coisas. A linha Add-content "C:\FileCreated.txt" é executada com sucesso e um arquivo é criado, mas os valores de $lasttimefilecreated e $logflag permanecem inalterados e não são impressos no console. Existe alguma outra maneira de conseguir isso? Analisei o artigo da Microsoft sobre o objeto Register-ObjectEvent , mas não consegui entender por que o script bloco que eu estou atribuindo a $ action não funciona totalmente. Aprecie sua ajuda!

### 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}}
    
por skyfx 18.08.2016 / 21:36

2 respostas

2

Você está se deparando com duas surpresas diferentes do PowerShell.

Primeiro: escopo. Quando você altera uma variável dentro de seu manipulador de eventos, você está apenas definindo uma nova variável que existe somente dentro desse bloco. Como um caso de teste simples, digitar isso no console produz 1 :

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

Para especificar que você está atribuindo ao escopo global, anexe o global: ao nome da variável. Isso imprime 2 :

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

Segundo: redirecionamento de saída de evento. Quando você produz resultados de um manipulador de eventos, ele é salvo em um objeto de trabalho. Para imprimir no console, use Write-Host em vez de (o implícito) Write-Output . Por exemplo:

Write-Host $lasttimefilecreated

Você pode considerar usar um temporizador em vez de um loop, da seguinte forma:

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

O loop final impede que o script seja encerrado. Os timers continuariam a funcionar se parassem, mas parece um pouco estranho.

    
por 19.08.2016 / 00:39
0

se você executar a partir do ISE antes de salvar a primeira vez, ele executará o código que você digitou na janela de script, como se você o tivesse digitado na linha de comando e não possa usar o escopo "$ script:", mas depois de salvar, ele executará o arquivo .ps1 e o escopo "$ script:" se aplicará ao script (ele não alterará as variáveis em sua sessão ise, mas as alterará durante a execução do script e do ponto de vista dos scripts, considerando que o escopo global, o escopo no qual o script foi iniciado, se você usar o escopo "$ global:", ele afeta o script e também afeta as variáveis em sua sessão ise (o escopo global a partir do qual o script foi chamado) .Espero que apague a diferença, portanto, para um script, não importa qual desses escopos você usa, mas é importante para o console do qual um script é chamado.

    
por 01.03.2018 / 12:50