0

I am trying to implement a FileSystemWatcher that contains an if statement that evaluates and argument passed to it, but it doesn't seem to be evaluating. Am I making a mistake? Here is the code:

Function Auto-Watcher
{
    param ($folder, $filter, $Program)

    $watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
        IncludeSubdirectories = $true
        EnableRaisingEvents = $true
    }

    Write-Host "Watching $folder for creation or moving of $filter files..."

    $changeAction = {
        $path = $Event.SourceEventArgs.FullPath
        $name = $Event.SourceEventArgs.Name
        $changeType = $Event.SourceEventArgs.ChangeType
        $timeStamp = $Event.TimeGenerated

        if ($Program -match "Report1") {
            Write-Host $Path "Ready for Report1 Generation"
            else {
                if ($Program -match "Report2") {
                    Write-Host Split-Path $Path "Ready for Report2 Generation"
                    else {
                        write-output "Error, not capable of matching identical strings"
                    }
                }
            }
        }

        Write-Host "The file $name was $changeType at $timeStamp"
    }
    Register-ObjectEvent $Watcher -EventName "Created" -Action $changeAction
}

I added in a Write-Output statement before the if statements that confirmed that $Program -match "Report1" was returning $true, but nothing in the if statements seems to be evaluated. What can I do?

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
Andy
  • 207
  • 4
  • 18
  • You're calling the `Auto-Watcher` function somewhere, right? Even so, it still might be problematic that the lifetime/scope of `$watcher` is that function. Does `Write-Host "The file $name was $changeType at $timeStamp"` get executed? – Lance U. Matthews Feb 06 '20 at 01:16
  • Yes and yes it does. – Andy Feb 06 '20 at 01:33
  • 3
    Your `if`/`else` structure is incorrect inside of `$changeAction`. Both `else` blocks seem to be _inside_ what should be their associated `if` block. That is, you have `if (...) { else { } }` when it should be `if (...) { } else { }`. – Lance U. Matthews Feb 06 '20 at 01:41
  • @Bacon I'm surprised it doesnt throw error on else without an if. All of these if else statements are like that. – Jawad Feb 06 '20 at 01:57
  • @Jawad It does at the command line. Running `if ($true) { else { } }` throws `else : The term 'else' is not recognized as the name of a cmdlet, function, script file, or operable program.` In the question, though, it'd be up to the code inside `FileSystemWatcher` that raises the `Created` event to handle that exception, although I'm not altogether sure how that gets propagated when a .NET event calls a PowerShell `ScriptBlock` event handler. – Lance U. Matthews Feb 06 '20 at 02:07
  • Another problem with your code: only a `$Program` variable defined in the _global_ scope will be seen inside your `-Action` script block. As shown, the function-local `$Program` parameter variable would _not_ be seen. To robustly pass values to your `-Action` script block, use `Register-ObjectEvent`'s `-MessageData` parameter; inside the action script block, use `$Event.MessageData` to access the value. – mklement0 Feb 06 '20 at 04:14

1 Answers1

3

Your if/else structure is incorrect inside of $changeAction. Both else blocks are inside what should be their associated if block. That is, you have this...

if ($condition) {
    else {
    }
}

...when it should be this...

if ($condition) {
    # $true branch
} else {
    # $false branch
}

Try defining the if structure within $changeAction like this...

if ($Program -match "Report1") {
    Write-Host $Path "Ready for Report1 Generation"
} elseif ($Program -match "Report2") {
    Write-Host (Split-Path $Path) "Ready for Report2 Generation"
} else {
    Write-Output "Error, not capable of matching identical strings"
}

...and see if that works. Note that I added () around the call to Split-Path $Path so that is evaluated and the result passed to Write-Host.

You could also rewrite the above using a switch statement...

switch -Regex ($Program) {
    "Report1" {
        Write-Host $Path "Ready for Report1 Generation"
        break
    }
    "Report2" {
        Write-Host (Split-Path $Path) "Ready for Report2 Generation"
        break
    }
    Default {
        Write-Output "Error, not capable of matching identical strings"
        break
    }
}

I added the -Regex parameter to make it equivalent to your use of the -match operator in the if conditions. Note that if your intent was to perform an exact string comparison in the if statements you could use, for example, if ($Program -eq "Report1") { to perform a case-insensitive comparison. If your intent was to perform a substring comparison you could use if ($Program -like "*Report1*") { instead of the -match operator.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68