powershell - 如何使用powershell判断一系列文件何时完成添加到网络
问题描述
所以我有一个powershell脚本,主要取自这里的一个类似问题,它可以检测何时将某种类型的文件添加到某个网络并在发生这种情况时发送电子邮件:
Function Watcher{
param ($folder, $filter, $to, $Subject)
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
IncludeSubdirectories = $true
EnableRaisingEvents = $true
}
$changeAction = [scriptblock]::Create('
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file $name was $changeType at $timeStamp"
$Body = "The file $name was $changeType at $timeStamp"
Email $to $Subject $Body
')
Register-ObjectEvent $Watcher -EventName "Created" -Action $changeAction
}
但是,我想修改它,使其对这个应用程序有用:现在有一个工具将数据(.datx 文件)添加到网络(每分钟几个文件),我想在那个时刻收到电子邮件通知数据已完成记录。我怎样才能最容易地修改它,以便在触发初始观察者时,它会等待查看它是否再次发生并重置,如果没有,则继续?或者创建一个全新的脚本是最好的?基本上,我怎样才能让观察者被上传到网络的单独 .datx 文件激活,但不让它由它们的流触发(最后一个除外)
解决方案
您可以使用以下批处理方法:
定义滑动时间窗口的长度,如果在其中创建新文件则重置;当事件到达该滑动窗口时继续收集事件。
- 为防止集合无限增长,请定义处理批次的最大批次大小,即使有更多事件未决。
一旦时间窗口过去而没有新的事件到达,处理手头的批次,即到目前为止收集的事件,然后开始一个新的批次。
警告:
该类
System.IO.FileSystemWatcher
可以报告重复事件。下面的代码消除了给定批次中的重复,但不是跨批次,这需要更多的努力 - 请参阅源代码注释。
实施说明:
不是使用
-Action
传递给的脚本块Register-ObjectEvent
来处理事件,而是在循环中同步处理它们- 有超时。Wait-Event
Wait-Event
使用 PowerShell 的事件队列,因此通常不会错过事件(尽管在大容量情况下可能发生在 .NET 级别);相比之下,FileSystemWatcher
的类似WaitForChanged
方法不会对事件进行排队,并且仅在方法等待时碰巧到达时报告单个事件。
try {
# Specify the target folder: the system's temp folder in this example.
$dir = (Get-Item -EA Ignore temp:).FullName; if (-not $dir) { $dir = $env:TEMP }
# Create and initialize the watcher.
# Note the [ordered] to ensure that .EnableRaisingEvents is set last.
$watcher = [System.IO.FileSystemWatcher] [ordered] @{
Filter = '*.datx'
Path = $dir
EnableRaisingEvents = $true
}
# To simulate file creation, create *.datx files in the folder printed
# mentioned in the following status message.
Write-Host "Watching $dir for creation of $($watcher.Filter) files..."
# Register for (subscribe to) creation events:
# Determine a unique event-source ID...
[string] $sourceId = New-Guid
# ... and register for the watcher's Created event with it.
Register-ObjectEvent $watcher -EventName Created -SourceIdentifier $sourceId
# Initialize the ordered hashtable that collects all file names for a single
# batch.
# Note: Since any given file creation can trigger *multiple* events, we
# use an ordered hashtable (dictionary) to ensure that each file is
# only reported once.
# However, *across batches* duplicates can still occur - see below.
$batch = [ordered] @{}
# Determine the sliding time window during which newly created files are
# considered part of a single batch.
# That is, once a file has been created, each additional file created
# within that time window relative to previous file becomes part of the
# same batch.
# When a time window elapses without a new file having been created, the
# batch is considered complete and processed - see max. batch-size exception
# below.
# IMPORTANT:
# * The granularity is *seconds*, so the time window must be at least 1 sec.
# * Seemingly independently of the length of this window, duplicate events
# are likely to occur across batches the less time has elapsed between
# the end of a batch and the start of a new one - see below.
$batchTimeWindowSecs = 5
# How many names to allow a batch to contain at most, even if more
# files keep getting created in the sliding time window.
$maxBatchSize = 100
while ($true) {
# Run indefinitely; use Ctrl-C to exit.
# Wait for events in a sliding time window of $batchTimeWindowSecs length.
# Note: Using Wait-Event in a loop (1 event per iteration) is *more*
# predictable than the multi-event collecting Get-Event in terms of
# avoiding duplicates, but duplicates do still occur.
$batch.Clear()
while ($evt = Wait-Event -SourceIdentifier $sourceId -Timeout $batchTimeWindowSecs) {
$evt | Remove-Event # By default, events linger in the queue; they must be removed manually.
# Add the new file's name to the batch (unless already present)
# IMPORTANT:
# * Duplicates can occur both in a single batch and across batches.
# * To truly weed out all duplicates, you'd have to create a session-level
# dictionary of the files' names and their creation timestamps.
# With high-volume file creation, this session-level dictionary could
# grow large; periodic removal of obsolete entries would help.
$batch[$evt.SourceArgs.Name] = $null # dummy value; it is the *keys* that matter.
Write-Host ✔ -NoNewline # status output: signal that a new file was created
# If the max. batch size has been reached, submit the batch now, even if further
# events are pending within the timeout window.
if ($batch.Count -ge $maxBatchSize) {
Write-Warning "Max. batch size of $maxBatchSize reached; force-submitting batch."
break
}
}
# Completed batch available?
if ($batch.Count) {
# Simulate processing the batch.
Write-Host "`nBatch complete: Sending email for the following $($batch.Count) files:`n$($batch.Keys -join "`n")" #`
# Start a new batch.
$batch.Clear()
}
else {
Write-Host . -NoNewline # status output: signal that no new files were created in the most recent time window.
}
}
}
finally {
# Clean up:
# Unregister the event subscription.
Unregister-Event -SourceIdentifier $sourceId
# Dispose of the watcher.
$watcher.Dispose()
}
首先创建一批 3 个文件的示例输出,然后是另一个 5 个文件:
Watching C:\Users\jdoe\AppData\Local\Temp for creation of *.datx files...
............✔✔✔
Batch complete: Sending email for the following 3 files:
1.datx
2.datx
3.datx
.✔✔✔✔✔
Batch complete: Sending email for the following 5 files:
4.datx
5.datx
6.datx
7.datx
8.datx
....................
推荐阅读
- python - 无法将 Infura 的 Optimism-mainnet 与 web3.py 连接
- android - Admob 新的 Adapter 类和 MediationBannerAd 接口没有 onDestroy 方法如何在使用 admob 中介时获取销毁回调
- github - 将存储库协作者添加为部署审阅者
- html - HTML CSS在隐藏表单中的td中居中paypal按钮
- android - 如何跳过 Android 中自定义构建变体的特定 gradle 任务?
- ssl-certificate - Api 管理中带有 webapi 的 Office-js 插件。获取失败
- python - 向量化二维 numpy 数组的函数
- css - 更改 Vuetify 表头的样式
- java - 在骆驼引导路线中使用 Spring-Boot @ControllerAdvice
- java - Spring batch JdbcPagingItemReaders 无法再次读取数据并立即以读取计数 0 完成