powershell - 在 PowerShell 作业中使用本地函数
问题描述
我正在编写自定义 cmdlet 来执行任务。其中一个 cmdlet 依赖于其他 cmdlet,并且需要很长时间,因此我想在作业中执行该任务。好吧,你猜怎么着,因为其他 cmdlet 在该 Job 的范围内不可用。为什么?其他语言,如 C++、Java、C# 允许您在同一范围内使用变量、对象、函数,为什么在 PowerShell 中不可用?为什么会如此脱钩?我觉得这让开发人员更难了。也许我不明白这个话题,但我想做这样的事情:
function Write-Yes {
Write-Host "yes"
}
function Write-No {
Write-Host "no"
}
function Write-Random {
$result = @($true, $false) | Get-Random
if ($result) {
Write-Yes
}
else {
Write-No
}
}
Start-Job -ScriptBlock { Write-Random }
这是不可能的。你必须做一些技巧,比如提供函数的脚本块作为参数,并使用调用运算符或类似的东西来调用它。甚至,使用 Import-Module 重新导入您正在使用的同一文件。这感觉过于复杂。我看到的唯一能够执行此类操作的模块是 PoshRSJob,它允许您命名将在作业中使用的 cmdlet,它会为您动态创建它们,并进行一些词法解析,再一次,过于复杂的事情。
为什么事情会像现在这样,有什么办法可以以优雅的方式做我在示例中尝试的事情吗?
解决方案
Start-Job 非常有限且缓慢。恕我直言,它的实施非常糟糕,我从不使用它。您可以将运行空间用于快速和轻量级的“后台作业”,并从当前会话中导入函数和变量。
例子:
function Write-Yes { "yes" }
function Write-No { "no" }
function Write-Random {
if ($true, $false | Get-Random) {
Write-Yes
}
else {
Write-No
}
}
# setup session and import functions
$session = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
"Write-Yes", "Write-No", "Write-Random" | foreach {
$session.Commands.Add((
New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry $_, (Get-Content "Function:\$_")
))
}
# setup separate powershell instance
$job = [Powershell]::Create($session)
[void]$job.AddScript({ Write-Random })
# start async
$asyncResult = $job.BeginInvoke()
# do stuff ...
# wait for completion
$job.EndInvoke($asyncResult)
$job.Dispose()
但总的来说,Powershell 不是为复杂的并行处理而设计的。通常,最好将所有内容放在脚本文件中并作为任务或后台作业等运行。
推荐阅读
- ios - Swift 检索用户表自定义列
- git - 为什么从特定的 GitHub 存储库合并到本地 Git 存储库会导致本地存储库中未提交的更改?
- mysql - mysql更新json属性和一个查询中的另一列
- java - Jmeter:在 CSV 行中执行计算并在测试中使用计算值
- c++ - Maya 和 Cuda 11 类型重新声明错误
- python - 在这种情况下,切换到警报的命令不起作用
- reactjs - React.cloneElement 克隆已经克隆的元素以添加新的道具
- drake - 将 OMPL 与 Drake 一起使用
- javascript - JS 将数据从“宽”转为“长”
- r - 如何从R中另一个数据框的变量自动制作一个新的数据框?