[英]Filesystemwatcher file created event not decompressing files
我有一个简单的脚本,它应该监视指定文件夹中的新文件并在到达时解压缩它们。 很简单,但我的脚本只能在 Powershell ISE 的调试器下工作。 在调试器之外,在创建文件时,它只打印“找到新文件 xxx”和“完成”,没有解压缩,也没有删除,也没有错误。 我在这里错过了什么吗?
# Folder you to monitor
$PathToMonitor = "C:\tmp1".
$OutputPath = "C:\tmp"
$Filter = "*.zip" # Filter for zip files.
$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path = $PathToMonitor
$FileSystemWatcher.IncludeSubdirectories = $false
$FileSystemWatcher.Filter = $Filter
# make sure the watcher emits events
$FileSystemWatcher.EnableRaisingEvents = $true
# define the code that should execute when a file change is detected
$Action = {
$details = $event.SourceEventArgs
$FullPath = $details.FullPath
$OldName = $details.OldName
$Timestamp = $event.TimeGenerated
try
{
Write-Host "New file " + $FullPath + " found"
$TarProgram = "tar.exe"
$TarArgs = 'xvf "' + $FullPath + '" -C ' + $OutputPath
Start-Process $TarProgram $TarArgs -Wait -WindowStyle hidden
Remove-Item -Path $FullPath -Force
Write-Host "Done"
}
catch [System.SystemException]
{
Write-Host $_.ScriptStackTrace
}
}
# add event handlers
$handlers = . {
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Created -Action $Action -SourceIdentifier FSCreateFtpGe
}
Write-Host "Watching for changes to $PathToMonitor"
try
{
do
{
Wait-Event -Timeout 10
} while ($true)
}
catch [System.SystemException]
{
Write-Host $_.ScriptStackTrace
}
finally
{
# this gets executed when user presses CTRL+C
# remove the event handlers
Write-Host "Cleaning up"
Unregister-Event -SourceIdentifier FSCreateFtpGe
# remove background jobs
$handlers | Remove-Job
# remove filesystemwatcher
$FileSystemWatcher.EnableRaisingEvents = $false
$FileSystemWatcher.Dispose()
"Event Handler disabled."
}
你怎么来月经了...
$PathToMonitor = "C:\tmp1".
...这是无效的语法,脚本无论如何都会失败。 然而,这可能只是您在此处发布的一种类型。
您为什么使用 tar 与 PowerShell 内置存档 cmdlet?
如果 tar.exe 不在您的 PowerShell 或系统路径中,您必须完全限定该路径才能使用它。
$TarProgram = 'C:\ProgramFiles\tar.exe'
因此,您的代码应该可以在任何 PowerShell 主机(ISE [进入/退出调试模式])/powershell.exe/VSCode 等中运行。 正如我刚刚测试过的那样。 再一次,cmdlet 在那里。 以下示例在新的 Windows 终端中运行。
#region Begin Script
# Folder you to monitor
$PathToMonitor = 'D:\tmp1'
$OutputPath = 'D:\tmp'
$Filter = '*.zip' # Filter for zip files.
$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path = $PathToMonitor
$FileSystemWatcher.IncludeSubdirectories = $false
$FileSystemWatcher.Filter = $Filter
# make sure the watcher emits events
$FileSystemWatcher.EnableRaisingEvents = $true
# define the code that should execute when a file change is detected
$Action = {
$details = $event.SourceEventArgs
$FullPath = $details.FullPath
$OldName = $details.OldName
$Timestamp = $event.TimeGenerated
try
{
"New file $FullPath found"
Expand-Archive -Path $FullPath -DestinationPath 'D:\tmp'
# Start-Process $TarProgram $TarArgs -Wait -WindowStyle hidden
Remove-Item -Path $FullPath -Force
'Done'
}
catch [System.SystemException]
{$PSItem.ScriptStackTrace}
}
# add event handlers
$handlers = . {
$RegisterObjectEventSplat = @{
InputObject = $FileSystemWatcher
EventName = 'Created'
Action = $Action
SourceIdentifier = 'FSCreateFtpGe'
}
Register-ObjectEvent @RegisterObjectEventSplat
}
"Watching for changes to $PathToMonitor"
try
{
do { Wait-Event -Timeout 10 }
while ($true)
}
catch [System.SystemException]
{$_.ScriptStackTrace}
finally
{
<#
this gets executed when user presses CTRL+C
remove the event handlers
#>
'Cleaning up'
Unregister-Event -SourceIdentifier FSCreateFtpGe
# remove background jobs
$handlers |
Remove-Job
# remove filesystemwatcher
$FileSystemWatcher.EnableRaisingEvents = $false
$FileSystemWatcher.Dispose()
'Event Handler disabled.'
}
#endregion End Script
# Results
Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -Property Caption, Version
Caption Version
$PSVersionTable
Name Value
---- -----
PSVersion 5.1.18362.752
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752}
BuildVersion 10.0.18362.752
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
Get-ChildItem -Path 'D:\tmp' -Verbose
(Get-ChildItem -Path 'D:\tmp').Count
0
Get-ChildItem -Path 'D:\tmp1' -Verbose
(Get-ChildItem -Path 'D:\tmp1').Count
0
.\FSWCopyUnzip.ps1
Watching for changes to D:\tmp1
New file D:\tmp1\book1.zip found
Done
Cleaning up
Get-ChildItem -Path 'D:\tmp' -Verbose
Directory: D:\tmp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 13-Mar-20 12:19 70 abc.txt
-a---- 13-Mar-20 22:27 71 book1.txt
-a---- 06-Apr-20 21:51 2979 Data.zip
-a---- 04-Mar-20 01:04 72 FileWithLines.txt
Get-ChildItem -Path 'D:\tmp1' -Verbose
(Get-ChildItem -Path 'D:\tmp1').Count
0
只是为了记录,我发现了问题。 它在某种程度上与 Powershell 中的变量范围有关。 如果不是使用在脚本开头声明的变量来保存 $OutputPath 的值,而是使用文字字符串,那么它可以工作。 否则,它会在运行时抱怨该值为 null (在 Powershell ISE 中它显示一个值)
所以,动作块现在看起来像这样:
$Action = {
$details = $event.SourceEventArgs
$FullPath = $details.FullPath
$OldName = $details.OldName
$Timestamp = $event.TimeGenerated
try
{
Expand-Archive -LiteralPath $FullPath -DestinationPath "C:\Temp"
Remove-Item -LiteralPath "$FullPath" -Force
}
catch [System.SystemException]
{
Write-Host $_
}
}
我希望一开始就拥有我的所有变量,因此如果需要可以轻松更改它们,但至少这个版本有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.