在 ScriptBlock 中不可访问的函数
Function not accessible in a ScriptBlock
我有一个具有某些功能的脚本,然后在同一个脚本中使用这些功能的多个作业。当我开始一份新工作时,他们似乎无法在我工作的 [ScriptBlock]
中访问。
这是一个证明这一点的最小示例:
# A simple test function
function Test([string] $string)
{
Write-Output "I'm a $string"
}
# My test job
[ScriptBlock] $test =
{
Test "test function"
}
# Start the test job
Start-Job -ScriptBlock $test -Name "Test" | Out-Null
# Wait for jobs to complete and print their output
@(Get-Job).ForEach({
Wait-Job -Job $_ |Out-Null
Receive-Job -Job $_ | Write-Host
})
# Remove the completed jobs
Remove-Job -State Completed
我在 PowerShell ISE 中遇到的错误是:
The term 'Test' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Test:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
Start-Job
运行 个作业在单独的 PowerShell 进程中。因此,作业无权访问调用 PowerShell 会话的会话状态。您需要在每个作业中定义作业使用的函数。在不复制代码的情况下,一种简单的方法是使用 -InitializationScript
参数,其中可以定义所有常用函数。
$IS = {
function CommonFunction1 {
'Do something'
}
function CommonFunction2 {
'Do something else'
}
}
$SB1 = {
CommonFunction1
CommonFunction2
}
$SB2 = {
CommonFunction2
CommonFunction1
}
$Job1 = Start-Job -InitializationScript $IS -ScriptBlock $SB1
$Job2 = Start-Job -InitializationScript $IS -ScriptBlock $SB2
Receive-Job $Job1,$Job2 -Wait -AutoRemoveJob
只是扩展 PetSerAl 的答案,如果您想要更快的代码和更有条理的代码,您可以为此使用运行空间。看看这个问题:
因此,当您 运行 在不同 运行 空间中的某些内容时,您需要在这两个空间中导入函数。所以完成的结构看起来像:
Module: functions.ps1
- 您在此处存储函数以与两个范围共享。
Main script: script.ps1
- 它基本上是您的脚本,带有 运行 空格,但没有函数中的函数。ps1.
并且在脚本的开头。ps1,只需调用 Import-module .\functions.ps1
即可访问您的函数。请记住 运行scape 有不同的作用域,在它们的脚本块中,您必须再次调用 import-module 。完整示例:
#file functions.ps1
function add($inp) {
return $inp + 2
}
#file script.ps1
Import-module .\functions.ps1 #or you can use "dot call": . .\function.ps1
Import-module .\invoke-parallel.ps1 #it's extern module
$argument = 10 #it may be any object, even your custom class
$results = $argument | Invoke-Parallel -ScriptBlock {
import-module .\functions.ps1 #you may have to use here absolute path, because in a new runspace PSScriptRoot may be different/undefined
return (add $_) # $_ is simply passed object from "parent" scope, in fact, the relationship between scopes is not child-parent
}
echo $result # it's 12
echo (add 5) # it's 7
我有一个具有某些功能的脚本,然后在同一个脚本中使用这些功能的多个作业。当我开始一份新工作时,他们似乎无法在我工作的 [ScriptBlock]
中访问。
这是一个证明这一点的最小示例:
# A simple test function
function Test([string] $string)
{
Write-Output "I'm a $string"
}
# My test job
[ScriptBlock] $test =
{
Test "test function"
}
# Start the test job
Start-Job -ScriptBlock $test -Name "Test" | Out-Null
# Wait for jobs to complete and print their output
@(Get-Job).ForEach({
Wait-Job -Job $_ |Out-Null
Receive-Job -Job $_ | Write-Host
})
# Remove the completed jobs
Remove-Job -State Completed
我在 PowerShell ISE 中遇到的错误是:
The term 'Test' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Test:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
Start-Job
运行 个作业在单独的 PowerShell 进程中。因此,作业无权访问调用 PowerShell 会话的会话状态。您需要在每个作业中定义作业使用的函数。在不复制代码的情况下,一种简单的方法是使用 -InitializationScript
参数,其中可以定义所有常用函数。
$IS = {
function CommonFunction1 {
'Do something'
}
function CommonFunction2 {
'Do something else'
}
}
$SB1 = {
CommonFunction1
CommonFunction2
}
$SB2 = {
CommonFunction2
CommonFunction1
}
$Job1 = Start-Job -InitializationScript $IS -ScriptBlock $SB1
$Job2 = Start-Job -InitializationScript $IS -ScriptBlock $SB2
Receive-Job $Job1,$Job2 -Wait -AutoRemoveJob
只是扩展 PetSerAl 的答案,如果您想要更快的代码和更有条理的代码,您可以为此使用运行空间。看看这个问题:
因此,当您 运行 在不同 运行 空间中的某些内容时,您需要在这两个空间中导入函数。所以完成的结构看起来像:
Module: functions.ps1
- 您在此处存储函数以与两个范围共享。Main script: script.ps1
- 它基本上是您的脚本,带有 运行 空格,但没有函数中的函数。ps1.
并且在脚本的开头。ps1,只需调用 Import-module .\functions.ps1
即可访问您的函数。请记住 运行scape 有不同的作用域,在它们的脚本块中,您必须再次调用 import-module 。完整示例:
#file functions.ps1
function add($inp) {
return $inp + 2
}
#file script.ps1
Import-module .\functions.ps1 #or you can use "dot call": . .\function.ps1
Import-module .\invoke-parallel.ps1 #it's extern module
$argument = 10 #it may be any object, even your custom class
$results = $argument | Invoke-Parallel -ScriptBlock {
import-module .\functions.ps1 #you may have to use here absolute path, because in a new runspace PSScriptRoot may be different/undefined
return (add $_) # $_ is simply passed object from "parent" scope, in fact, the relationship between scopes is not child-parent
}
echo $result # it's 12
echo (add 5) # it's 7