Search code examples
powershellwhile-loopfile-watcher

While inside of onCreated gets stuck on a array in PowerShell but works fine in ISE


Wrote a script that monitors a folder for new files. When onCreated is called it increments to the next drive letter in my list, then checks that drive for free space. If the free space is under my requirement it increments again. My full script works great in ISE.

Here is a simplified version that I still can't get to work. When ran in PowerShell and it gets stuck on $DriveVar and only outputs "marker1". If you run in ISE the marker2 line correctly rotates through the drive letters for each file you copy into the folder.

$filter = '*.*'
$Watchfolder = "C:\Script\watch"
$LocationArray = "L","J","K","Q","S"
$LocationCount = [int]$LocationArray.Count
$LastUsed = [int]0

$Watcher = New-Object IO.FileSystemWatcher $Watchfolder, $filter -Property @{
    NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' }

$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
    $Freespace = [long]-1
    while ($Freespace -le 0) {
        $LastUsed++
        if ($LastUsed -ge $LocationCount) {
            $LastUsed = 0 }
        Write-Host "marker1"

        $DriveVar = $LocationArray[$LastUsed]
        Write-Host "marker2 $DriveVar"
        $Freespace = 5
    }
}

Output in PowerShell:

marker1

Output in ISE:

marker1
marker2 J
marker1
marker2 K
marker1
marker2 Q

I tried calling a function for $DriveVar and some other things (all working in ISE) and I can't seem to make it work. And if I use the while loop on its own (without the onCreated) it works fine in Powershell.


Solution

  • Looks like this is a matter of scope. I did a little testing on my end using your code and got the same results. I was able to fix things by scoping the variables to $global:, and then got the desired results. Try this out:

    $filter = '*.*'
    $Watchfolder = "C:\Script\watch"
    $global:LocationArray = "L","J","K","Q","S"
    $global:LocationCount = [int]$LocationArray.Count
    $global:LastUsed = [int]0
    
    $Watcher = New-Object IO.FileSystemWatcher $Watchfolder, $filter -Property @{
        NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' }
    
    $onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
        $Freespace = [long]-1
        while ($Freespace -le 0) {
            $global:LastUsed++
            if ($global:LastUsed -ge $global:LocationCount) {
                $global:LastUsed = 0 }
            Write-Host "marker1"
    
            $DriveVar = $global:LocationArray[$global:LastUsed]
            Write-Host "marker2 $DriveVar"
            $Freespace = 5
        }
    }
    

    I found this by just trying to Write-Host $LocationArray after your Write-Host "marker1" line, and it just spit out a blank line.