我試圖理解并弄清楚如何將變數傳遞到腳本塊中。在我下面的示例腳本中,當一個新檔案被放入監控檔案夾時,它會執行 $action 腳本塊。但是 $test1 變數只是顯示為空白。我可以讓它作業的唯一方法是使它成為一個全域變數,但我真的不想這樣做。
我已經研究了一些,但比開始時更困惑。任何人都可以幫助我或指出正確的方向來理解這一點嗎?
$PathToMonitor = "\\path\to\folder"
$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path = $PathToMonitor
$FileSystemWatcher.Filter = "*.*"
$FileSystemWatcher.IncludeSubdirectories = $false
$FileSystemWatcher.EnableRaisingEvents = $true
$test1 = "Test variable"
$Action = {
Write-Host "$test1"
}
$handlers = . {
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Created -Action $Action -SourceIdentifier FSCreateConsumer
}
try {
do {
Wait-Event -Timeout 5
} while ($true)
}
finally {
Unregister-Event -SourceIdentifier FSCreateConsumer
$handlers | Remove-Job
$FileSystemWatcher.EnableRaisingEvents = $false
$FileSystemWatcher.Dispose()
}
uj5u.com熱心網友回復:
隱藏在Register-ObjectEvent的檔案中,在-Action引數描述中的下面是這個小花絮:
Action 引數的值可以包括 $Event、$EventSubscriber、$Sender、$EventArgs 和 $Args 自動變數。這些變數向 Action 腳本塊提供有關事件的資訊。有關詳細資訊,請參閱 about_Automatic_Variables。
這意味著 PowerShell 會自動創建一些您可以在事件處理程式腳本塊中使用的變數,并在觸發事件時填充它們 - 例如:
$Action = {
write-host ($Sender | format-list * | out-string)
write-host ($EventArgs | format-list * | out-string)
}
當您在監視檔案夾中創建檔案時,您將看到如下輸出:
NotifyFilter : FileName, DirectoryName, LastWrite
Filters : {*}
EnableRaisingEvents : True
Filter : *
IncludeSubdirectories : False
InternalBufferSize : 8192
Path : c:\temp\scratch
Site :
SynchronizingObject :
Container :
ChangeType : Created
FullPath : c:\temp\scratch\New Text Document (3).txt
Name : New Text Document (3).txt
如果這些包含您想要的資訊,那么您實際上不需要自己將任何引數傳遞到腳本塊中:-)。
更新
如果您仍然需要將您自己的變數傳遞到事件中,您可以使用-MessageData引數 ofRegister-ObjectEvent以便能夠$Event.MessageData在您的事件腳本塊中訪問它- 例如:
$Action = {
write-host ($EventArgs | format-list * | out-string)
write-host "messagedata before = "
write-host ($Event.MessageData | ConvertTo-Json)
$Event.MessageData.Add($EventArgs.FullPath, $true)
write-host "messagedata after = "
write-host ($Event.MessageData | ConvertTo-Json)
}
$messageData = @{ };
$handlers = . {
# note the -MessageData parameter
Register-ObjectEvent `
-InputObject $FileSystemWatcher `
-EventName Created `
-Action $Action `
-MessageData $messageData `
-SourceIdentifier FSCreateConsumer
}
當事件觸發時,它將輸出如下內容:
ChangeType : Created
FullPath : c:\temp\scratch\New Text Document (16).txt
Name : New Text Document (16).txt
messagedata before =
{}
messagedata after =
{
"c:\\temp\\scratch\\New Text Document (16).txt": true
}
$messageData從技術上講它仍然是一個全域變數,但您$Action不再需要了解它,因為它從$Event.
請注意,如果您想保留更改,則需要使用可變資料結構 - 您不能只為 分配一個新值$Event.MessageData,并且它可能還需要是執行緒安全的。
uj5u.com熱心網友回復:
事件操作塊在后臺執行緒上運行,并且$test1在調度時無法決議。
一個解決辦法是明確地讀取和寫入到一個全球范圍的變數(如Write-Host $global:test1),但更好的方法是,以確保$Action塊“記住”的值,$test1供以后-這是我們可以完成一個閉合。
為此,我們需要稍微重新組織代碼,因此首先將$test1字串文字替換為同步哈希表:
$test1 = [hashtable]::Synchronized(@{
Value = "Test variable"
})
這將允許我們做兩件事:
- 我們可以在不改變存盤在 中的物件的身份的情況下修改字串值
$test1, - 字串值可以被多個后臺執行緒修改而不會發生任何競爭條件
現在我們只需要從$Action塊中創建閉包:
$Action = {
Write-Host $test1.Value
}.GetNewClosure()
這會將$test1(對我們剛剛在上面一行中創建的同步哈希表的參考)的值系結到$Action塊,因此它將“記住”$test1決議為哈希表而不是嘗試(并失敗)在運行時決議它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/372251.html
上一篇:如何在本地地址中沒有0的情況下在powershell中顯示netstat命令?
下一篇:添加成員提供具有多個標題的輸出
