1

I'm trying to get a simple script running which detects whenever a certain filetype is downloaded to my Downloads directory, then moves it to the correct place. I have not added the actual filetype filtering yet, because I'm stuck on the "detecting a file being downloaded at all" part.

If I create a file in Downloads myself, the script works. But if Chrome creates the file as it downloads it, it doesn't work. It prints "working," so it is detecting the file creation, but it isn't moving it.

Why might that be?

### Set folder and files to watch and misc flags
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "C:\Users\Aerovistae\Downloads"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $false
    $watcher.EnableRaisingEvents = $true  

### Define actions to be taken when an event is detected
    $action = { $path = $Event.SourceEventArgs.FullPath
                Write-Host "working!"
                Move-Item -Path $path -Destination "C:\Users\Aerovistae\Desktop"
              }    
### Decide which events to watch
    Register-ObjectEvent $watcher "Created" -Action $action
    while ($true) {sleep 5}
temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
  • Are you waiting until the download is complete? FileSystemWatcher is probably giving you the Create event but the file is still exclusively locked while it's download and most likely renamed. What other events do you have besides `Created` that you could hook into? – No Refunds No Returns Aug 30 '18 at 00:33
  • @NoRefundsNoReturns Correct, just confirmed this. I am doing some tests to find a workaround, maybe a "try again" type deal. – Drew Aug 30 '18 at 00:35
  • Hmm. Maybe `Renamed`? Chrome starts things off as something like `UnconfirmedDownload.02847028` before giving them their proper name at completion. – temporary_user_name Aug 30 '18 at 00:36
  • 1
    Here's an old answer but the link has evaporated. Looking for a current one: https://stackoverflow.com/questions/46730384/how-to-know-if-copying-is-finished-in-windows/46731056 – No Refunds No Returns Aug 30 '18 at 00:40
  • I got it sort of working, it kept copying the .tmp files but not the .pdf that I was using as a test. – Drew Aug 30 '18 at 01:14
  • Switching to `Renamed` worked for me in this case although it's not really the answer to this question, so I'll leave it open. [This](https://stackoverflow.com/questions/29394358/powershell-check-if-file-is-finished-writing) is a mildly helpful solution also. – temporary_user_name Aug 30 '18 at 02:53
  • Actually, it's not really working, my mistake. hmph. The `Renamed` event is giving me the original filename instead of the new one. – temporary_user_name Aug 30 '18 at 03:04

1 Answers1

1

Your code works... on linux anyway. Here's what I setup:

test.ps1:

$sourcepath = '/home/veefu/watched/sourcefolder'
$destpath = '/home/veefu/watched/destfolder'


$watcher = New-object System.io.filesystemwatcher
$watcher.path = $sourcepath
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true

$action = {
    $path = $event.SourceEventARgs.FullPath
    Move-Item -Path $path -Destination $destpath
}

Register-ObjectEvent $watcher 'Created' -action $action

Started with:

. ./test.ps1

To test, I downloaded and saved a .jpg file with chrome to the $sourcepath. The following errors were emitted to the listening job, but the .jpg file was moved in the end:

> get-job |Receive-Job

Move-Item : Cannot find path '/home/veefu/watched/sourcefolder/after night out.JPG.crdownload' because it does not exist. At /home/veefu/watched/test.ps1:14 char:5 + Move-Item -Path $path -Destination $destpath + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (/home/veefu/wa....JPG.crdownload:String) [Move-Item], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand Move-Item : Cannot find path '/home/veefu/watched/sourcefolder/after night out.JPG.crdownload' because it does not exist. At /home/veefu/watched/test.ps1:14 char:5 + Move-Item -Path $path -Destination $destpath + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (/home/veefu/wa....JPG.crdownload:String) [Move-Item], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand

It's possible that the events on Linux differ from those generated on Windows.

It's also possible that the file size I chose for testing leads to different results than the one you chose. Judging by the errors, the .jpg seemed to already be renamed by the time the listener tried to handle the event.

You may try reading the error events from the watching job to get a clue as to the problem with:

Get-Job | Receive-Job

Also, you don't need the while($true) {sleep 5} if you're running your script from a powershell console; The job responsible for listening should persist as long as your powershell process does.

For that matter, you may need to check how many jobs you have running and clean up any left-overs using Get-Job, Stop-Job and Remove-Job

veefu
  • 2,820
  • 1
  • 19
  • 29