I made a small PowerShell wrapping script for the WinSCP module that suites my needs. Like in the example for synchronizing local and remote folders mine uses a file transferred event to log session events.
$fileTransferedEvent = {Receive-FileTransferredEvent $_}
$session.add_FileTransferred($fileTransferedEvent)
The example disposes the session when it is done. My logic keeps the session open until I choose to be done with it so I can use the same session in other cmdlet call.
This creates an issue if a other cmdlets (or even calling the same one again) also use add_FileTransferred()
. The event gets added again which triggers X times the output where X is how many times the method is called.
I found a partner method called remove_FileTransferred()
but I do not know how to use it
Name MemberType Definition
---- ---------- ----------
add_FileTransferred Method void add_FileTransferred(WinSCP.FileTransferredEventHandler value)
remove_FileTransferred Method void remove_FileTransferred(WinSCP.FileTransferredEventHandler value)
They both accept the same values so I thought maybe I could pass it a definition of the the handler but that does not seem to work i.e. $session.remove_FileTransferred($fileTransferedEvent)
did not do the job. Nor does it error either.
How can I remove file transferred event handlers on Winscp.Session
objects?
This works for me perfectly:
$fileTransferedEvent = { Write-Host "Upload of $($_.FileName) succeeded" }
$session.add_FileTransferred($fileTransferedEvent)
$session.PutFiles("C:\test.txt", "/").Check()
$session.remove_FileTransferred($fileTransferedEvent)
$session.PutFiles("C:\test.txt", "/").Check()
I get:
Upload of C:\test.txt succeeded
While if I do not call remove_FileTransferred
, I get the output twice, as expected:
Upload of C:\test.txt succeeded
Upload of C:\test.txt succeeded
Refer to Event handlers in PowerShell.
If you add the same event handler multiple times, the handler will be called that many times each time the event is raised. If you want to cancel an event subscription, you have to remove the handler the same number of time. Removing handler, which is not (or no longer) added is noop. All these are general rules, not limited to Session.FileTransferred
or WinSCP .NET assembly.
Example:
$fileTransferedEvent = { Write-Host "Upload of $($_.FileName) succeeded" }
$session.add_FileTransferred($fileTransferedEvent)
$session.add_FileTransferred($fileTransferedEvent)
Write-Host "two handlers:"
$session.PutFiles("C:\test.txt", "/").Check()
$session.remove_FileTransferred($fileTransferedEvent)
Write-Host "one handler:"
$session.PutFiles("C:\test.txt", "/").Check()
$session.remove_FileTransferred($fileTransferedEvent)
Write-Host "zero handlers:"
$session.PutFiles("C:\test.txt", "/").Check()
Write-Host "done"
This will get you:
two handlers:
Upload of C:\test.txt succeeded
Upload of C:\test.txt succeeded
one handler:
Upload of C:\test.txt succeeded
zero handlers:
done
Though, what may not be obvious is, that the following two code snippets are not identical:
$fileTransferedEvent = { Write-Host "Upload of $($_.FileName) succeeded" }
$session.add_FileTransferred($fileTransferedEvent)
$fileTransferedEvent = { Write-Host "Upload of $($_.FileName) succeeded" }
$session.add_FileTransferred($fileTransferedEvent)
$fileTransferedEvent = { Write-Host "Upload of $($_.FileName) succeeded" }
$session.add_FileTransferred($fileTransferedEvent)
$session.add_FileTransferred($fileTransferedEvent)
The first snippet adds two distinct event handlers, while the latter adds two identical handlers.
After the first snippet, you cannot remove the two registrations by calling this:
$session.remove_FileTransferred($fileTransferedEvent)
$session.remove_FileTransferred($fileTransferedEvent)
The first "remove" will remove the last/second added handler. The second "remove" will do nothing, as it tries to remove the same handler, which was already cancelled. As you do not have any reference to the first handler, you cannot cancel it anymore.