【问题标题】:Powershell Job Always Shows CompletePowershell 作业总是显示完成
【发布时间】:2015-01-10 13:30:47
【问题描述】:

我大约 3 天前才开始使用 powershell,我一直在尝试制作一个脚本来访问远程计算机的注册表并查找某个键并将输出放入文件中。

我已经能够让它工作,但我注意到如果它无法到达注册表,大约需要 15 秒才能出错并继续执行脚本,所以我把它放进去:

$Server = "test.contesto.net"

$Job = Start-Job ScriptBlock{[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$Server)

Start-Sleep 2

If ($Job.State -EQ "Completed"){
write-host "made it"
}
Else {
write-host "failed"
}

我将永远“成功”。即使我知道我无法访问该服务器注册表。奇怪的是,如果我像这样手动将所有内容输入到 powershell 提示符中:

$Job = Start-Job ScriptBlock {[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine","test.contesto.net") 

然后看看那个作业的状态

$Job.State

在失败所需的整整 15 秒内,我得到“正在运行”。我试图在ScriptBlock {} 中添加Get-Variable,但这也不起作用。它仍然显示已完成。因此,我认为这与由于语法或其他原因导致作业出错有关,因此无论如何,作业每次都会完成

【问题讨论】:

  • 这不需要作为一项工作来完成,至少你描述的部分是这样。那么为什么要增加这一层复杂性呢?
  • 我想添加这层复杂性的原因是因为我不想等待默认的 15 秒:[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine ","test.contesto.net") 命令完成。相反,我只想等待不到一秒或 1 秒。我不确定有什么其他方法可以做到这一点。如果你有任何关于如何实现这一点的想法,我很想得到一些其他的想法。我将在多台机器上运行它,我不需要 15 秒就知道它会失败。

标签: powershell remote-registry


【解决方案1】:

问题是您需要将$server 作为参数传递给脚本块,然后通过名为$args 的自动变量引用它:

$server = "test.contesto.net"
$Job = Start-Job -ScriptBlock {
    $server = $args[0]
    [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$server) 
} -ArgumentList @($server)

后台作业在与当前脚本完全不同的上下文中运行,因此不会看到本地定义的变量。

因此,在您的情况下,作业立即失败,因为$server 等于 $null。 通过适当地传递 $server,作业将尝试检索远程密钥,然后超时。

【讨论】:

  • 我认为您也可以使用$using:server 来解析这样的脚本块中使用的局部变量。我不能说这适用于 Jobs,但我知道它适用于 Invoke-command、工作流和 DSC 脚本资源。但是您可以通过这种方式避免 -argument 列表,并且代码看起来更干净。
  • 谢谢!这正是它的本来面目。我觉得很愚蠢,这么简单的答案。我认为这将是我做错的一些语法事情。 "$using:server" 很棒!我一定会用的。
猜你喜欢
  • 1970-01-01
  • 2017-01-20
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多