如何从WinSCP会话对象中删除FileTransferred事件处理程序?

时间:2017-06-01 19:38:17

标签: powershell ftp winscp powershell-v5.0 winscp-net

我为WinSCP模块制作了一个小型PowerShell包装脚本,以满足我的需求。 Like in the example for synchronizing local and remote folders我使用文件传输事件来记录会话事件。

$fileTransferedEvent = {Receive-FileTransferredEvent $_}
$session.add_FileTransferred($fileTransferedEvent)

该示例在完成后处理会话。我的逻辑保持会话打开,直到我选择完成它,所以我可以在其他cmdlet调用中使用相同的会话。

如果其他cmdlet(或者甚至再次调用同一个cmdlet)也使用add_FileTransferred(),则会产生问题。事件再次添加,触发X次输出,其中X是调用方法的次数。

我找到了一个名为remove_FileTransferred()的合作伙伴方法,但我不知道如何使用它

Name                   MemberType Definition                                                           
----                   ---------- ----------                                                           
add_FileTransferred    Method     void add_FileTransferred(WinSCP.FileTransferredEventHandler value)   
remove_FileTransferred Method     void remove_FileTransferred(WinSCP.FileTransferredEventHandler value)

他们都接受相同的值,所以我想也许我可以传递一个处理程序的定义,但似乎不起作用,即$session.remove_FileTransferred($fileTransferedEvent)没有完成这项工作。也不是错误。

如何在Winscp.Session个对象上删除文件传输的事件处理程序?

1 个答案:

答案 0 :(得分:2)

这对我很有用:

$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()

我明白了:

Upload of C:\test.txt succeeded

如果我不调用remove_FileTransferred,我会按预期获得两次输出:

Upload of C:\test.txt succeeded
Upload of C:\test.txt succeeded

请参阅Event handlers in PowerShell

如果多次添加相同的事件处理程序,则每次引发事件时都会多次调用该处理程序。如果要取消事件订阅,则必须删除处理程序相同的时间。删除未添加(或不再添加)的处理程序是noop。所有这些都是一般规则,不限于Session.FileTransferred或WinSCP .NET程序集。

示例:

$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"

这会让你:

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

但是,可能不太明显的是,以下两个代码片段不相同:

$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)

第一个代码段添加了两个不同的事件处理程序,而后者添加了两个相同的处理程序。

在第一个代码段之后,您无法通过调用以下内容删除这两个注册:

$session.remove_FileTransferred($fileTransferedEvent)
$session.remove_FileTransferred($fileTransferedEvent)

第一个"删除"将删除最后/第二个添加的处理程序。第二个"删除"什么都不会,因为它试图删除已被取消的相同处理程序。由于您没有对第一个处理程序的任何引用,因此您无法再取消它。