#powershell #timer
Вопрос:
Я разрабатываю сценарий Powershell с использованием системы.Windows.Формы для отслеживания и обработки содержимого папки. Для автоматической проверки содержимого папки я использовал систему.Windows.Формы.Таймер с интервалом 2000 мс. При каждом тике вызывается функция Timer_Tick, которая, в свою очередь, вызывает другую функцию.
При запуске скрипта функции немедленно вызываются десятки раз за секунду, а затем замедляются. Я добавил несколько Write-Host
заявлений, проясняющих этот вопрос. После запуска скрипта функции WaitForStart и Timer_Tick вызываются несколько раз в секунду. Я ожидал, что функции будут вызываться (приблизительно) каждые 2 секунды.
Printen van dossier naar hotfo
Form load
Timer Tick 17:03:369637
Wait for Start 17:03:369637
Timer Tick 17:03:369735
Wait for Start 17:03:369735
Timer Tick 17:03:369794
Wait for Start 17:03:369794
Timer Tick 17:03:369882
Wait for Start 17:03:369882
Timer Tick 17:03:369970
Wait for Start 17:03:369970
Timer Tick 17:03:370009
Wait for Start 17:03:370009
Timer Tick 17:03:370057
Wait for Start 17:03:370057
Timer Tick 17:03:370145
Wait for Start 17:03:370145
Timer Tick 17:03:370204
Wait for Start 17:03:370204
Timer Tick 17:03:370282
Wait for Start 17:03:370282
Timer Tick 17:03:370360
Wait for Start 17:03:370360
Timer Tick 17:03:370448
Wait for Start 17:03:370448
Timer Tick 17:03:370546
Wait for Start 17:03:370546
Timer Tick 17:03:370614
Wait for Start 17:03:370614
Timer Tick 17:03:370673
Wait for Start 17:03:370673
Timer Tick 17:03:370741
Wait for Start 17:03:370741
Timer Tick 17:03:370829
Wait for Start 17:03:370829
Timer Tick 17:03:370907
Сценарий powershell
Param (
# Define parameters below, each separated by a comma
[Parameter(Mandatory)]
[string]$Dossierfolder,
[Parameter(Mandatory)]
[string]$Hotfolder
)
Add-Type -AssemblyName System.Windows.Forms
$nl = "`r`n"
$font_small = 'Microsoft Sans Serif,12'
$font_large = 'Microsoft Sans Serif,18'
$LocalPrinterForm = New-Object system.Windows.Forms.Form
$LocalPrinterForm.ClientSize = '500,300'
$LocalPrinterForm.text = "LazyAdmin - PowerShell GUI Example"
$LocalPrinterForm.BackColor = "#ffffff"
$Heading = New-Object system.Windows.Forms.Label
$Heading.text = "OVD Hotfolder printer"
$Heading.AutoSize = $true
$Heading.width = 25
$Heading.height = 10
$Heading.location = New-Object System.Drawing.Point(20,20)
$Heading.Font = $font_large
$DossierFolderLabel = New-Object system.Windows.Forms.Label
$DossierFolderLabel.text = "Dossier folder :"
$DossierFolderLabel.AutoSize = $true
$DossierFolderLabel.width = 25
$DossierFolderLabel.height = 10
$DossierFolderLabel.location = New-Object System.Drawing.Point(20,50)
$DossierFolderLabel.Font = $font_small
$HotFolderLabel = New-Object system.Windows.Forms.Label
$HotFolderLabel.text = "Hot folder :"
$HotFolderLabel.AutoSize = $true
$HotFolderLabel.width = 25
$HotFolderLabel.height = 10
$HotFolderLabel.location = New-Object System.Drawing.Point(20,70)
$HotFolderLabel.Font = $font_small
$StatusLabel = New-Object system.Windows.Forms.Label
$StatusLabel.text = "STATUS :"
$StatusLabel.AutoSize = $true
$StatusLabel.width = 25
$StatusLabel.height = 10
$StatusLabel.location = New-Object System.Drawing.Point(20,100)
$StatusLabel.Font = $font_small
$ProgressIndicator = New-Object system.Windows.Forms.ProgressBar
$ProgressIndicator.Minimum = 1
$ProgressIndicator.Maximum = 25
$ProgressIndicator.Value = 12
$ProgressIndicator.Step = 1
$ProgressIndicator.width = 450
$ProgressIndicator.height = 20
$ProgressIndicator.location = New-Object System.Drawing.Point(20,140)
$Logging = New-Object system.Windows.Forms.TextBox
$Logging.MultiLine = $true
$Logging.width = 450
$Logging.height = 100
$Logging.ScrollBars = "vertical";
$Logging.location = New-Object System.Drawing.Point(20,160)
$LocalPrinterForm.controls.AddRange(@($Heading,$DossierFolderLabel,$HotFolderLabel,$StatusLabel,$ProgressIndicator, $Logging))
Write-Host "Printen van dossier naar hotfolder"
<# Start with only when hotfolder is empty #>
$hotfolderfiles = Get-ChildItem $Hotfolder -Filter *.pdf
$hotfoldernumfiles = $hotfolderfiles.Count
if ($hotfoldernumfiles -ne 0) {
[System.Windows.MessageBox]::Show('Hotfolder is niet, leeg hotfolder "'
$Hotfolder '" en start hotfolderprint opnieuw','Waarschuwing','Ok')
exit
}
<# Set timer #>
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 2000
<# Processing each interval #>
Function WaitForStart {
<# $HotFolderLabel.Text = Get-Date -Format "HH:mm:ss"#>
Write-Host "Wait for Start " $DossierFolderLabel.Text
$Logging.AppendText($HotFolderLabel.Text $nl )
}
<# Start Timer on Load #>
Function Form_Load {
$timer.Start()
Write-Host "Form load"
}
<# Interval Handling #>
Function Timer_Tick {
$DossierFolderLabel.Text = Get-Date -Format "HH:mm:ssffff"
Write-Host "Timer Tick" $DossierFolderLabel.Text
WaitForStart
}
$LocalPrinterForm.Add_Load({Form_Load})
$timer.add_tick({Timer_Tick})
[void]$LocalPrinterForm.ShowDialog()
Ответ №1:
Таймер не уничтожается при закрытии окна. Поэтому события по таймеру помещаются в очередь. Каждый раз при запуске приложения события, поставленные в очередь, обрабатываются, что приводит к буре событий. Затем после каждого запуска приложения запускается дополнительный таймер. Таким образом, с интервалом в 2000 секунд принимается по крайней мере одно событие каждые секунды.
Решение простое;
Добавьте a $timer.Dispose()
в качестве последней строки в сценарий в качестве уловки, когда сценарий будет убит. Чтобы распорядиться таймером, когда Форма закрыта контролируемым образом, добавьте функцию для обработки события закрытия формы
Function Form_Closing {
$timer.Stop();
Write-Host "Form unload"
}
И зарегистрируйте функцию для обработки Add_Closing
события.
$LocalPrinterForm.Add_Closing({Form_Closing})