Bridger Winter Bridger Winter - 3 months ago 9
PowerShell Question

$Event.SourceEventArgs.<attribute> is returning a null or empty object. [Beginner][Solved]

I have a

FileSystemWatcher
program that whenever an event is raised it sends an email notifying me of where the change happened.

However,
$Event.SourceEventArgs.FullPath
returns empty, and the other attributes returns
$null
.

Relevant code:

Function Watch{
$global:FileChanged = $false
$folder = "\\foo\boo\here\is\folder"
$filter = "*this is the filter*"
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{

IncludeSubdirectories = $true
EnableRaisingEvents = $true
}
# Start-Sleep -Seconds 1

Register-ObjectEvent $watcher "Changed" -Action {$global:FileChanged = $true} > $null
# Register-ObjectEvent $watcher "Created" -Action {$global:FileChanged = $true} > $null
# Register-ObjectEvent $watcher "Deleted" -Action {$global:FileChanged = $true} > $null
# $watcher.EnableRaisingEvents = $true

while($true){

while($global:FileChanged -eq $false){
Start-Sleep -Milliseconds 250

}
$global:FileChanged = $false
$paths = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.FileName
$changetype = $Event.SourceEventArgs.ChangeType
$TimeChanged = $Event.TimeGenerated
RunScript $paths, $name, $changetype, $TimeChanged
}
}
Function RunScript
{
param($paths, $name, $changetype, $TimeChanged)

Write-Host "This should work $paths $name $changetype $TimeChanged"
$From = "email"
$ToAddress = "email"
$MessageSubject = "Form Submitted by $paths"
$MessageBody = "File Path: $Event.SourceEventArgs.FullPath
Name: $name
Change Type?: $changetype
Time Changed: $timechanged"
$SendingServer = "999.999.999.9.9"
$SMTPMessage = New-Object System.Net.Mail.MailMessage $From, $ToAddress,
$MessageSubject, $MessageBody
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)
}

Watcher


EDIT: Please view Chris' answer for the solution to this error future viewers.

Answer

Updated example. Note: I haven't tested this at all so be aware there are likely bugs. I've added some comments and a couple of different approaches for other sections of the code.

Function Watch {
    $folder = "\\foo\boo\here\is\folder"
    $filter = "*this is the filter*"
    $watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
        IncludeSubdirectories = $true
        EnableRaisingEvents = $true
    }
    # Start-Sleep -Seconds 1

    Register-ObjectEvent $watcher "Changed" > $null
    # Register-ObjectEvent $watcher "Created" > $null
    # Register-ObjectEvent $watcher "Deleted" > $null
    # $watcher.EnableRaisingEvents = $true

    while($true){
        Wait-Event | Get-Event | ForEach-Object {
            # $paths = $_.SourceEventArgs.FullPath 
            # $name = $_.SourceEventArgs.FileName
            # $changetype = $_.SourceEventArgs.ChangeType
            # $TimeChanged = $_.TimeGenerated
            # If you comma-delimit this list you pass all of the arguments into "RunScript".
            # Either name the parameters or make them positional.
            # Positional:
            #   RunScript $paths $name $changetype $TimeChanged
            # Named:
            #   RunScript -Paths $paths -Name $name -ChangeType $changetype -TimeChanged $TimeChanged
            # Or use Splatting:
            $params = @{
                Paths       = $_.SourceEventArgs.FullPath
                Name        = $_.SourceEventArgs.FileName
                ChangeType  = $_.SourceEventArgs.ChangeType
                TimeChanged = $_.TimeGenerated
            }
            RunScript @params

        }
    }
}

Function RunScript {
    param($paths, $name, $changetype, $TimeChanged)

    Write-Host "This should work $paths $name $changetype $TimeChanged"
    # $From = "email"
    # $ToAddress = "email"
    # $MessageSubject = "Form Submitted by $paths"
    # $MessageBody = "File Path: $Event.SourceEventArgs.FullPath
    # Name: $name 
    # Change Type?: $changetype 
    # Time Changed: $timechanged"
    # $SendingServer = "999.999.999.9.9"
    # $SMTPMessage = New-Object System.Net.Mail.MailMessage $From, $ToAddress,
    # $MessageSubject, $MessageBody
    # $SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
    # $SMTPClient.Send($SMTPMessage)

    # Is there a reason you're not using Send-MailMessage?
    # Splatting again :)
    # The body of the email isn't going to be very pretty, but it's a start.
    $params = @{
        From = "email"
        To   = "email"
        Subject = "Form Submitted by $paths"
        Body = "File Path: $paths
        Name: $name 
        Change Type?: $changetype 
        Time Changed: $timechanged"
        "
        SmtpServer = "999.999.999.9.9"
    }
    Send-MailMessage @params


}

Now you get a caveat. The FileSystemWatcher is useful, but because of how Windows works you may well receive two event notifications for a single change (that's a deep Windows problem as opposed to a code problem). Try it and see.

Chris

Edit: Forgot to remove the action parameter. It's gone now.