对ScriptBlock中的变量使用Invoke命令



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

调用命令:无法验证参数"ScriptBlock"上的参数。参数为null。请为参数提供一个有效值,然后尝试再次运行该命令

我只是想让用户输入他们想查看事件日志的时间、保存位置和名称。到目前为止,我已经能够完成所有操作,直到我点击了Invoke命令行,但还没能完成。我更喜欢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:作用域引用这些变量(正如您在上一次基于Invoke-Command的尝试中所做的那样(。此要求也适用于远程执行的脚本块,例如通过Invoke-Command -ComputerName执行-有关背景信息,请参阅此答案。另一种选择是通过-ArgumentList(-Args(参数将参数传递到脚本块,尽管$using:方法通常更简单。

Start-Job返回作业信息对象(System.Management.Automation.Job(,您可以使用该对象监视后台作业的进度并从后台作业获取输出,使用各种*-Jobcmdlet,尤其是Wait-JobReceive-Job-请参阅about_Jobs概念帮助主题。

通常,使用Invoke-Command执行本地代码,虽然在技术上得到支持,但很少有必要
对于命令或脚本块的直接、同步调用(不是作为作业(,请使用&调用运算符(对于单个命令不需要,只要命令名没有引用或通过变量指定(,或者对于直接在调用方的作用域中执行,请使用点源运算符(. { ... }(.

您有几个选项。由于您只在本地计算机上运行此程序,因此可以使用Start-Job而不是Invoke-Command

话虽如此,你遇到的问题是两倍的。首先,如果您正在运行Invoke-Commandcmdlet,则需要指定ComputerName参数。即使它是一个可选参数,您也需要使用它来告诉Powershell您正在使用哪个参数集,否则它会被混淆。

其次,您需要将参数传递到脚本块中。这是因为启动作业和调用命令是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

相关内容

  • 没有找到相关文章

最新更新