Filesystemwatcher文件创建的事件未解压缩文件

问题描述 投票:0回答:2

我有一个简单的脚本,该脚本应监视指定文件夹中的新文件,并在到达时解压缩它们。很简单,但是我的脚本仅在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."
}
powershell
2个回答
0
投票

你为什么在这里有一段时间...

$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

0
投票

仅作记录,我发现了问题。它在某种程度上与Powershell中的变量作用域有关。如果不是使用脚本开头声明的变量来保存$ OutputPath的值,而是使用文字字符串,那么它将起作用。否则,它会抱怨该值在运行时为空(在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 $_
    }
}

我希望一开始就拥有我的所有变量,因此可以根据需要轻松更改它们,但至少此版本有效。

© www.soinside.com 2019 - 2024. All rights reserved.