电源外壳。无法从 {} 获取变量
PowerShell. Can't get variable from {}
在下面的代码中有一个名为“$action”= {...} 的参数。括号内有一些变量($path、$logPath 等) 如何从大括号“{}”外的此参数访问变量?我需要一个 while 循环的函数("RunFunctions")的结果。或者,如果这是一些愚蠢的问题,请您指点我在哪里可以找到有关此 {} 表示法的一些信息?谢谢
try {
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Testers\ResetOptimisation\tracking"
$watcher.Filter = "user_name*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$logPath = "C:\Testers\ResetOptimisation\output\log.txt"
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content $logPath -value $logline
$terminateFlag = RunFunctions $path $changeType $logPath
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {
Write-Host $teminateFlag
if ($teminateFlag -eq 1) {
Exit
}
Start-Sleep 3
}
}
catch {
Write-Host $_
}
{ ... }
是一个 脚本块 (字面量)- 一段可重复使用的 PowerShell 代码,您可以按需执行(就像其他语言中的函数指针或委托) ).
通过将存储在变量 $action
中的这样一个块传递给 Register-ObjectEvent -Action
,PowerShell 会在感兴趣的事件触发时调用它,并在 动态模块中执行此操作,其作用域完全独立于调用者的作用域。
因此,您的调用代码看不到块内创建的变量,因为它们是该块的本地变量。
有关 PowerShell 范围的详细信息,请参阅 的底部部分。
虽然 PowerShell 通常 允许您在 其他 范围内创建和修改变量,但如果您采取显式操作,这就是 不是 Register-ObjectEvent -Action
的选项,因为动态模块的作用域根本无法访问调用者的作用域,只能访问global 作用域。
# !! This works, but is ill-advised.
$global:terminateFlag = RunFunctions $path $changeType $logPath
但是,最好避免使用全局范围,因为全局变量甚至在脚本退出后仍然存在(它们是 session-global ).
更好的解决方案是:
使动作脚本块输出调用者的值。
让调用者使用
的事件作业通过 Receive-Job
接收输出
Register-ObjectEvent -Action
returns.
这是一个演示该技术的简化、独立的示例:
它设置一个观察器,附加一个事件处理程序,并创建一个触发观察器事件的文件。
try {
# Specify the target folder: the system's temp folder in this example.
$dir = (Get-Item -EA Ignore temp:).FullName; if (-not $dir) { $dir = $env:TEMP }
# Create and initialize the watcher.
$watcher = [System.IO.FileSystemWatcher] @{
Filter = '*.tmp'
Path = $dir
}
# Define the action script block (event handler).
$action = {
# Print the event data to the host.
Write-Host "Event raised:`n$($EventArgs | Format-List | Out-String)"
$terminateFlag = $true
# *Return* a value that indicates whether watching should be stopped.
# This value is later retrieved via Receive-Job.
return $terminateFlag
}
# Subscribe to the watcher's Created events, which returns an event job.
# This indefinitely running job receives the output from the -Action script
# block whenever the latter is called after an event fires.
$eventJob = Register-ObjectEvent $watcher Created -Action $action
# Start watching:
# Note: Not strictly necessary, because, curiously,
# Register-ObjectEvent has aleady done this for us.
$watcher.EnableRaisingEvents = $true
# Using an aux. background job, create a sample file that will trigger the
# watcher, after a delay.
$tempFile = Join-Path $dir "$PID.tmp"
$auxJob = Start-Job { Start-Sleep 3; 'hi' > $using:tempFile }
Write-Host "Watching $dir for creation of $($watcher.Filter) files..."
# Wait in a loop until the action block is run in response to an event and
# produces $true as output to signal the intent to terminate, via Receive-Job.
while ($true -ne (Receive-Job $eventJob)) {
write-host . -NoNewline
Start-Sleep -Milliseconds 500 # sleep a little
}
}
finally {
# Clean up.
# Dispose of the watcher.
$watcher.Dispose()
# Remove the event job (and with it the event subscription).
$eventJob | Remove-Job -Force
# Clean up the helper job.
Remove-Job -ea Ignore -Force $auxJob
# Remove the temp. file
Remove-Item -ea Ignore $tempFile
}
在这段代码中,我的脚本块 "$action" 能够覆盖我初始化的全局参数 "terminateFlag"主要脚本。非常感谢@mklement0 和他提供的 link
try {
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Testers\ResetOptimisation\tracking"
$watcher.Filter = "user_name*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$global:terminateFlag = 0
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$logPath = "C:\Testers\ResetOptimisation\output\log.txt"
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content $logPath -value $logline
$global:terminateFlag = RunFunctions $path $changeType $logPath
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {
Write-Host "waiting for file..."
if ($terminateFlag -eq 1) {
Exit
}
Start-Sleep 10
}
}
catch {
Write-Host $_
}
在下面的代码中有一个名为“$action”= {...} 的参数。括号内有一些变量($path、$logPath 等) 如何从大括号“{}”外的此参数访问变量?我需要一个 while 循环的函数("RunFunctions")的结果。或者,如果这是一些愚蠢的问题,请您指点我在哪里可以找到有关此 {} 表示法的一些信息?谢谢
try {
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Testers\ResetOptimisation\tracking"
$watcher.Filter = "user_name*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$logPath = "C:\Testers\ResetOptimisation\output\log.txt"
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content $logPath -value $logline
$terminateFlag = RunFunctions $path $changeType $logPath
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {
Write-Host $teminateFlag
if ($teminateFlag -eq 1) {
Exit
}
Start-Sleep 3
}
}
catch {
Write-Host $_
}
{ ... }
是一个 脚本块 (字面量)- 一段可重复使用的 PowerShell 代码,您可以按需执行(就像其他语言中的函数指针或委托) ).
通过将存储在变量 $action
中的这样一个块传递给 Register-ObjectEvent -Action
,PowerShell 会在感兴趣的事件触发时调用它,并在 动态模块中执行此操作,其作用域完全独立于调用者的作用域。
因此,您的调用代码看不到块内创建的变量,因为它们是该块的本地变量。
有关 PowerShell 范围的详细信息,请参阅
虽然 PowerShell 通常 允许您在 其他 范围内创建和修改变量,但如果您采取显式操作,这就是 不是 Register-ObjectEvent -Action
的选项,因为动态模块的作用域根本无法访问调用者的作用域,只能访问global 作用域。
# !! This works, but is ill-advised.
$global:terminateFlag = RunFunctions $path $changeType $logPath
但是,最好避免使用全局范围,因为全局变量甚至在脚本退出后仍然存在(它们是 session-global ).
更好的解决方案是:
使动作脚本块输出调用者的值。
让调用者使用
的事件作业通过Receive-Job
接收输出Register-ObjectEvent -Action
returns.
这是一个演示该技术的简化、独立的示例:
它设置一个观察器,附加一个事件处理程序,并创建一个触发观察器事件的文件。
try {
# Specify the target folder: the system's temp folder in this example.
$dir = (Get-Item -EA Ignore temp:).FullName; if (-not $dir) { $dir = $env:TEMP }
# Create and initialize the watcher.
$watcher = [System.IO.FileSystemWatcher] @{
Filter = '*.tmp'
Path = $dir
}
# Define the action script block (event handler).
$action = {
# Print the event data to the host.
Write-Host "Event raised:`n$($EventArgs | Format-List | Out-String)"
$terminateFlag = $true
# *Return* a value that indicates whether watching should be stopped.
# This value is later retrieved via Receive-Job.
return $terminateFlag
}
# Subscribe to the watcher's Created events, which returns an event job.
# This indefinitely running job receives the output from the -Action script
# block whenever the latter is called after an event fires.
$eventJob = Register-ObjectEvent $watcher Created -Action $action
# Start watching:
# Note: Not strictly necessary, because, curiously,
# Register-ObjectEvent has aleady done this for us.
$watcher.EnableRaisingEvents = $true
# Using an aux. background job, create a sample file that will trigger the
# watcher, after a delay.
$tempFile = Join-Path $dir "$PID.tmp"
$auxJob = Start-Job { Start-Sleep 3; 'hi' > $using:tempFile }
Write-Host "Watching $dir for creation of $($watcher.Filter) files..."
# Wait in a loop until the action block is run in response to an event and
# produces $true as output to signal the intent to terminate, via Receive-Job.
while ($true -ne (Receive-Job $eventJob)) {
write-host . -NoNewline
Start-Sleep -Milliseconds 500 # sleep a little
}
}
finally {
# Clean up.
# Dispose of the watcher.
$watcher.Dispose()
# Remove the event job (and with it the event subscription).
$eventJob | Remove-Job -Force
# Clean up the helper job.
Remove-Job -ea Ignore -Force $auxJob
# Remove the temp. file
Remove-Item -ea Ignore $tempFile
}
在这段代码中,我的脚本块 "$action" 能够覆盖我初始化的全局参数 "terminateFlag"主要脚本。非常感谢@mklement0 和他提供的 link
try {
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Testers\ResetOptimisation\tracking"
$watcher.Filter = "user_name*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$global:terminateFlag = 0
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$logPath = "C:\Testers\ResetOptimisation\output\log.txt"
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content $logPath -value $logline
$global:terminateFlag = RunFunctions $path $changeType $logPath
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {
Write-Host "waiting for file..."
if ($terminateFlag -eq 1) {
Exit
}
Start-Sleep 10
}
}
catch {
Write-Host $_
}