Search code examples
powershellpowershell-3.0filesystemwatcher

Filewatcher to unzip and process when event (.zip) is detected


I want to create a filewatcher and do the below flow using PowerShell:

Watch for file in folderA (.zip) → move the file to folderB as (.zip) → unzip the moved file in folderC (with same name) → and trigger a batch file → do the same for more incoming .zip files.

I checked a related question to this in StackOverflow but I need some more help.

My PowerShell script is as below (I am using PowerShell ISE):

while ($true) {
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "D:\LocalData\Desktop\folderA"
    $watcher.Filter = "*.zip*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true
    $tempfolder = "D:\LocalData\Desktop\folderA\folderB"
    $outpath = "D:\LocalData\Desktop\folderA\folderB\folderC"

    #Function to Unzip the moved item
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    function Unzip {
        Param([string]$path, [string]$outpath)
        [System.IO.Compression.ZipFile]::ExtractToDirectory($path, $outpath)
    }

    $action = {
        $path = $Event.SourceEventArgs.FullPath
        $changeType = $Event.SourceEventArgs.ChangeType
        $name = $Event.SourceEventArgs.Name
        Move-Item $path $tempfolder

        Unzip $path $outpath -Force # this line is not being read, it goes to the function block, and slips down to the action block

        $logline = "$(Get-Date), $changeType, $path" # no log is generated
        Add-Content -Path "d:\LocalData\folderA\Watcherlog.log" $logline
        Start-Process -Path "d:\LocalData\process.bat"
    }
    Register-ObjectEvent $watcher "Created" -Action $action
    Start-Sleep 2
}
Unregister-Event -SourceIdentifier FileCreated

Solution

  • There's your error:

    $action = {
        ...
        Move-Item $path $tempfolder
    
        Unzip $path $outpath -Force
        ...
    }
    

    You move the file to a different location, yet try to unzip it from the original location after it was already moved.

    Change your scriptblock to something like this, and it should work as you expect:

    $action = {
        $path = $Event.SourceEventArgs.FullPath
        $changeType = $Event.SourceEventArgs.ChangeType
    
        Unzip $path $outpath -Force
        Remove-Item $path
    
        "$(Get-Date), $changeType, $path" | Add-Content -Path "d:\LocalData\folderA\Watcherlog.log"
        Start-Process -FilePath "d:\LocalData\process.bat" -Wait
    }