簡體   English   中英

Powershell - 如何將變量傳遞到腳本塊

[英]Powershell - How to pass variable into scriptblock

我試圖理解並弄清楚如何將變量傳遞到腳本塊中。 在我下面的示例腳本中,當一個新文件被拖放到受監視的文件夾中時,它會執行 $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()
}

您可以通過與ScriptBlocks類似的方式將變量傳遞給function

$scriptBlock = {
    param($i)

    "hello $i"
}

& $scriptBlock -i world! # => hello world! // no access to $i
. $scriptBlock -i world! # => hello world! // $i ('world!') exists in this scope
  • 使用$args自動變量:
$scriptBlock = {
    '{0} {1}!' -f $args[0], $args[1]
}

& $scriptBlock hello world # => hello world! // using $args automatic variable

事件操作塊在后台線程上運行,並且在分派時無法解析$test1

一種解決方法是顯式讀取和寫入全局范圍的變量(例如Write-Host $global:test1 ),但更好的解決方案是確保$Action塊“記住” $test1的值以備后用 - 某事我們可以通過閉包來完成。

為此,我們需要稍微重新組織代碼,因此首先將$test1字符串文字替換為同步哈希表:

$test1 = [hashtable]::Synchronized(@{
  Value = "Test variable"
})

這將允許我們做兩件事:

  • 我們可以在不更改$test1中存儲的 object 的身份的情況下修改字符串值,
  • 字符串值可以被多個后台線程修改而不會發生任何競爭條件

現在我們只需要從$Action塊創建閉包:

$Action = {
    Write-Host $test1.Value
}.GetNewClosure()

這會將$test1的值(我們剛剛在上一行創建的同步哈希表的引用)綁定到$Action塊,因此它將“記住” $test1解析為哈希表而不是嘗試(並失敗)在運行時解決它。

隱藏在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)
}

當您在監視文件夾中創建文件時,您會看到一些 output 如下所示:


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

如果這些包含您所追求的信息,那么您實際上不需要自己將任何參數傳遞給腳本塊:-)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM