在 ScriptBlock 中使用带有变量的 Invoke-Command
Using Invoke-Command with Variables in ScriptBlock
PowerShell 新手,通过使用帮助信息编写随机脚本进行学习。我已经尝试了以下 3 种方法来将变量正确地放入 ScriptBlock(以及太多的小变化无法列出),列出的错误消息包含在 **:
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object EntryType -eq Warning | where TimeGenerated -ge $DaysAgo | Out-File $HOME$location$filename.txt}
调用命令:无法使用指定的命名参数解析参数集。
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object EntryType -eq Warning | where TimeGenerated -ge $Using:$DaysAgo | Out-File $Using:HOME$Using:location$Using:filename.txt}
调用命令:无法使用指定的命名参数解析参数集。
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
Write-Host "Processing..."
$DaysAgo = [datetime]::Now.AddDays(-$days)
$parameters = @{
ScriptBlock = { Param ($Arg1,$Arg2,$Arg3) Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object source -eq DCOM | where TimeGenerated -ge $Arg1 | Out-File "$HOME$Arg2$Arg3.txt"}}
JobName = "DCOM"
ArgumentList = ($DaysAgo,$location,$filename)
}
Invoke-Command @parameters
Invoke-Command:无法验证参数 'ScriptBlock' 的参数。参数为空。为参数提供有效值,然后再次尝试 运行 命令。
我只是想让用户输入他们想要查看事件日志的时间、保存位置以及名称。到目前为止,我已经能够完成所有工作,直到我点击 Invoke-Command 行并且无法完成它。与参数样式相比,我更喜欢 1 和 2 的单行样式,但是在使用 help_Invoke-Command-full 和谷歌搜索花费了太多时间之后,我放弃了我确信这是我的一个简单错误语法。
你可以在脚本块中使用$args
,看一个例子:
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {
Get-EventLog -logname system | Where-Object EntryType -eq Warning |
where TimeGenerated -ge $args[0] |
Out-File $HOME$location$filename.txt
} -ArgumentList $DaysAgo
像示例中那样在 Invoke-Command
末尾添加参数,第一个参数使用 $args[0]
,第二个参数使用 $args[1],依此类推...
这对我有用。计算机是 localhost 作为测试,在提升的提示下,系统日志无论如何都需要它。 3 级为警告。如果是用于同一台计算机,则根本不需要调用命令。
$location = 'foo'
$filename = 'myfile'
$date = get-date
$daysago = $date.adddays(-1)
invoke-command localhost { param($daysago, $location, $filename)
get-winevent @{logname = 'system'; level = 3; starttime = $daysago} |
out-file $home$location$filename.txt } -args $daysago,$location,$filename
为了使用Invoke-Command
的-AsJob
开关,你必须远程执行代码,这样例如通过使用 -ComputerName
或 -Session
参数定位不同的计算机。
在没有此类参数的情况下,您的命令将 运行 本地 ,但由于上述句法限制而失败。
如果你想运行在本地工作,直接使用Start-Job
:
$job = Start-Job -Name JobEventLog -ScriptBlock {
Get-EventLog -logname system |
Where-Object EntryType -eq Warning |
Where-Object TimeGenerated -ge $using:DaysAgo |
Out-File $HOME$using:location$using:filename.txt
}
注意:由于您的后台脚本块从调用者的范围引用变量,因此必须通过$using:
范围[=63=引用它们](正如您在上次基于 Invoke-Command
的尝试中所做的那样)。此要求也适用于 远程 执行的脚本块,例如通过 Invoke-Command -ComputerName
- 请参阅 了解背景信息。另一种方法是通过 -ArgumentList
(-Args
) 参数将 arguments 传递给脚本块,尽管 $using:
方法通常更简单。
Start-Job
returns 一个 工作信息对象 (System.Management.Automation.Job
), which you can use to monitor the progress of and obtain output from the background job, using the various *-Job
cmdlets, notably Wait-Job
and Receive-Job
- see the about_Jobs 概念性帮助主题。
通常,使用 Invoke-Command
进行 本地 代码执行,虽然在技术上得到支持,但很少需要 .
对于命令或脚本块的直接 同步 调用(不是作为作业),请使用 &
、call operator (not needed for single commands, as long as the command name isn't quoted or specified via a variable), or, for execution directly in the caller's scope, .
, the dot-sourcing operator(. { ... }
)。
你有几个选择。由于您在本地计算机上只有 运行,因此您可以使用 Start-Job
而不是 Invoke-Command
。
话虽如此,您 运行 遇到的问题有两个。首先,如果您是 运行 Invoke-Command
cmdlet,则需要指定 ComputerName 参数。即使它是一个可选参数,您也需要使用它来告诉 Powershell 您正在使用哪个参数集,否则它会变得混乱。
其次,您需要将参数传递到脚本块中。这是因为 Start-Job 和 Invoke-Command 是 PSRemoting 的一部分,实际上会在指定的计算机上查找环境变量,而不是您在脚本中声明的变量。
以下是对我有用的方法:
Invoke-Command -ComputerName $(hostname) -AsJob -JobName "TestJob" -ScriptBlock { Get-EventLog -logname system | Where-Object EntryType -eq Warning | Where-Object -property TimeGenerated -ge $args[0] | Out-File "$HOME$($args[1])$($args[2]).txt" } -ArgumentList $DaysAgo, $location, $filename
如果您想从网络上的其他设备获取此信息,Invoke-Command
选项非常有用。
这里是 Start-Job
版本:
Start-Job -Name "TestJob2" -ScriptBlock { Get-EventLog -logname system | Where-Object EntryType -eq Warning | Where-Object -property TimeGenerated -ge $args[0] | Out-File "$HOME$($args[1])$($args[2]).txt" } -ArgumentList $DaysAgo, $location, $filename
PowerShell 新手,通过使用帮助信息编写随机脚本进行学习。我已经尝试了以下 3 种方法来将变量正确地放入 ScriptBlock(以及太多的小变化无法列出),列出的错误消息包含在 **:
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object EntryType -eq Warning | where TimeGenerated -ge $DaysAgo | Out-File $HOME$location$filename.txt}
调用命令:无法使用指定的命名参数解析参数集。
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object EntryType -eq Warning | where TimeGenerated -ge $Using:$DaysAgo | Out-File $Using:HOME$Using:location$Using:filename.txt}
调用命令:无法使用指定的命名参数解析参数集。
do
{
try {
[ValidateRange(1,7)][int]$days = Read-Host "Let's pull up some Warning event logs. How many days back would you like to go back? (1-7)"
} catch {}
} until ($?)
do
{
try {
[ValidateSet('desktop','documents',IgnoreCase)]$location = Read-Host "Would you like me to save the log on your Desktop or in your Documents?"
} catch {}
} until ($?)
$filename = Read-Host "What would you like to name the file?"
Write-Host "Processing..."
$DaysAgo = [datetime]::Now.AddDays(-$days)
$parameters = @{
ScriptBlock = { Param ($Arg1,$Arg2,$Arg3) Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {Get-EventLog -logname system | Where-Object source -eq DCOM | where TimeGenerated -ge $Arg1 | Out-File "$HOME$Arg2$Arg3.txt"}}
JobName = "DCOM"
ArgumentList = ($DaysAgo,$location,$filename)
}
Invoke-Command @parameters
Invoke-Command:无法验证参数 'ScriptBlock' 的参数。参数为空。为参数提供有效值,然后再次尝试 运行 命令。
我只是想让用户输入他们想要查看事件日志的时间、保存位置以及名称。到目前为止,我已经能够完成所有工作,直到我点击 Invoke-Command 行并且无法完成它。与参数样式相比,我更喜欢 1 和 2 的单行样式,但是在使用 help_Invoke-Command-full 和谷歌搜索花费了太多时间之后,我放弃了我确信这是我的一个简单错误语法。
你可以在脚本块中使用$args
,看一个例子:
$DaysAgo = [datetime]::Now.AddDays(-$days)
Invoke-Command -AsJob -Jobname JobEventLog -ScriptBlock {
Get-EventLog -logname system | Where-Object EntryType -eq Warning |
where TimeGenerated -ge $args[0] |
Out-File $HOME$location$filename.txt
} -ArgumentList $DaysAgo
像示例中那样在 Invoke-Command
末尾添加参数,第一个参数使用 $args[0]
,第二个参数使用 $args[1],依此类推...
这对我有用。计算机是 localhost 作为测试,在提升的提示下,系统日志无论如何都需要它。 3 级为警告。如果是用于同一台计算机,则根本不需要调用命令。
$location = 'foo'
$filename = 'myfile'
$date = get-date
$daysago = $date.adddays(-1)
invoke-command localhost { param($daysago, $location, $filename)
get-winevent @{logname = 'system'; level = 3; starttime = $daysago} |
out-file $home$location$filename.txt } -args $daysago,$location,$filename
为了使用Invoke-Command
的-AsJob
开关,你必须远程执行代码,这样例如通过使用 -ComputerName
或 -Session
参数定位不同的计算机。
在没有此类参数的情况下,您的命令将 运行 本地 ,但由于上述句法限制而失败。
如果你想运行在本地工作,直接使用Start-Job
:
$job = Start-Job -Name JobEventLog -ScriptBlock {
Get-EventLog -logname system |
Where-Object EntryType -eq Warning |
Where-Object TimeGenerated -ge $using:DaysAgo |
Out-File $HOME$using:location$using:filename.txt
}
注意:由于您的后台脚本块从调用者的范围引用变量,因此必须通过$using:
范围[=63=引用它们](正如您在上次基于 Invoke-Command
的尝试中所做的那样)。此要求也适用于 远程 执行的脚本块,例如通过 Invoke-Command -ComputerName
- 请参阅 -ArgumentList
(-Args
) 参数将 arguments 传递给脚本块,尽管 $using:
方法通常更简单。
Start-Job
returns 一个 工作信息对象 (System.Management.Automation.Job
), which you can use to monitor the progress of and obtain output from the background job, using the various *-Job
cmdlets, notably Wait-Job
and Receive-Job
- see the about_Jobs 概念性帮助主题。
通常,使用 Invoke-Command
进行 本地 代码执行,虽然在技术上得到支持,但很少需要 .
对于命令或脚本块的直接 同步 调用(不是作为作业),请使用 &
、call operator (not needed for single commands, as long as the command name isn't quoted or specified via a variable), or, for execution directly in the caller's scope, .
, the dot-sourcing operator(. { ... }
)。
你有几个选择。由于您在本地计算机上只有 运行,因此您可以使用 Start-Job
而不是 Invoke-Command
。
话虽如此,您 运行 遇到的问题有两个。首先,如果您是 运行 Invoke-Command
cmdlet,则需要指定 ComputerName 参数。即使它是一个可选参数,您也需要使用它来告诉 Powershell 您正在使用哪个参数集,否则它会变得混乱。
其次,您需要将参数传递到脚本块中。这是因为 Start-Job 和 Invoke-Command 是 PSRemoting 的一部分,实际上会在指定的计算机上查找环境变量,而不是您在脚本中声明的变量。
以下是对我有用的方法:
Invoke-Command -ComputerName $(hostname) -AsJob -JobName "TestJob" -ScriptBlock { Get-EventLog -logname system | Where-Object EntryType -eq Warning | Where-Object -property TimeGenerated -ge $args[0] | Out-File "$HOME$($args[1])$($args[2]).txt" } -ArgumentList $DaysAgo, $location, $filename
如果您想从网络上的其他设备获取此信息,Invoke-Command
选项非常有用。
这里是 Start-Job
版本:
Start-Job -Name "TestJob2" -ScriptBlock { Get-EventLog -logname system | Where-Object EntryType -eq Warning | Where-Object -property TimeGenerated -ge $args[0] | Out-File "$HOME$($args[1])$($args[2]).txt" } -ArgumentList $DaysAgo, $location, $filename