How do I Start a job of a function i just defined?
How do I Start a job of a function i just defined?
function FOO { write-host "HEY" }
Start-Job -ScriptBlock { FOO } |
Receive-Job -Wait -AutoRemoveJob
Result:
Receive-Job: The term 'FOO' is not recognized as the name of cmdlet,
function ,script file or operable program.
What do I do? Thanks.
@Shay가 지적했듯이,FOO
작업에 대한 정의가 필요합니다.이를 위한 또 다른 방법은-InitializationScript
세션을 준비하기 위한 매개 변수.
For your example:
$functions = {
function FOO { write-host "HEY" }
}
Start-Job -InitializationScript $functions -ScriptBlock {FOO}|
Wait-Job| Receive-Job
This can be useful if you want to use the same functions for different jobs.
@Rynant의 제안은InitializationScript
훌륭합니다
I thought the purpose of (script) blocks is so that you can pass them around. So depending on how you are doing it, I would say go for:
$FOO = {write-host "HEY"}
Start-Job -ScriptBlock $FOO | wait-job |Receive-Job
Of course you can parameterize script blocks as well:
$foo = {param($bar) write-host $bar}
Start-Job -ScriptBlock $foo -ArgumentList "HEY" | wait-job | receive-job
It worked for me as:
Start-Job -ScriptBlock ${Function:FOO}
An improvement to @Rynant's answer:
You can define the function as normal in the main body of your script:
Function FOO
{
Write-Host "HEY"
}
and then recycle this definition within a scriptblock:
$export_functions = [scriptblock]::Create(@"
Function Foo { $function:FOO }
"@)
(실질적인 기능체를 가지고 있다면 좀 더 의미 있는 makes을) 다음으로 전달합니다.Start-Job
위와 같이:
Start-Job -ScriptBlock {FOO} -InitializationScript $export_functions| Wait-Job | Receive-Job
I like this way, as it is easier to debug jobs by running them locally under the debugger.
The function needs to be inside the scriptblock:
Start-Job -ScriptBlock { function FOO { write-host "HEY" } ; FOO } | Wait-Job | Receive-Job
As long as the function passed to the InitializationScript param on Start-Job isn't large Rynant's answer will work, but if the function is large you may run into the below error.
[localhost] There is an error launching the background process. Error reported: The filename or extension is too long"
Capturing the function's definition and then using Invoke-Expression on it in the ScriptBlock is a better alternative.
function Get-Foo {
param
(
[string]$output
)
Write-Output $output
}
$getFooFunc = $(Get-Command Get-Foo).Definition
Start-Job -ScriptBlock {
Invoke-Expression "function Get-Foo {$using:getFooFunc}"
Get-Foo -output "bar"
}
Get-Job | Receive-Job
PS C:\Users\rohopkin> Get-Job | Receive-Job
bar
A slightly different take. A function is just a scriptblock assigned to a variable. Oh, it has to be a threadjob. It can't be foreach-object -parallel.
$func = { 'hi' } # or
function hi { 'hi' }; $func = $function:hi
start-threadjob { & $using:func } | receive-job -auto -wait
hi
@Ben Power의 수락된 답변 아래 코멘트 또한 저의 관심사였습니다. 그래서 구글에서 함수 정의를 구하는 방법을 검색해보니Get-Command
- 이것은 기능체만 얻을 수 있습니다.그러나 이 기능은 점으로 표시된 파일과 같이 다른 곳에서 오는 경우에도 사용할 수 있습니다.그래서 저는 다음과 같이 생각해냈습니다. (이름 짓기 규칙을 유지합니다. :) 이 아이디어는 새로운 줄로 구분된 함수 정의를 다시 만드는 것입니다.
Filter Greeting {param ([string]$Greeting) return $Greeting}
Filter FullName {param ([string]$FirstName, [string]$LastName) return $FirstName + " " + $LastName}
$ScriptText = ""
$ScriptText += "Filter Greeting {" + (Get-Command Greeting).Definition + "}`n"
$ScriptText += "Filter FullName {" + (Get-Command FullName).Definition + "}`n"
$Job = Start-Job `
-InitializationScript $([ScriptBlock]::Create($ScriptText)) `
-ScriptBlock {(Greeting -Greeting "Hello") + " " + (FullName -FirstName "PowerShell" -LastName "Programmer")}
$Result = $Job | Wait-Job | Receive-Job
$Result
$Job | Remove-Job
There's good information in the existing answers, but let me attempt a systematic summary:
PowerShell의 백그라운드 작업은[1] 프로세스를 종료하지 않은 실행 공간(숨겨진 하위 프로세스)에서 실행되므로 호출자와 상태를 공유하지 않습니다.
따라서 세션 중인 호출자에 의해 생성된 정의는 백그라운드 작업에 표시되지 않으므로 작업의 컨텍스트에서 다시 생성해야 합니다.[2]
함수 정의를 다시 만드는 가장 간단한 방법은 네임스페이스 변수 표기법(예:
$function:FOO
- 아래와 같이 를 사용하여 이 답변을 참조합니다.
자체적인 예로 다음과 같습니다.
function FOO { "HEY" }
Start-Job -ScriptBlock {
# Redefine function FOO in the context of this job.
$function:FOO = "$using:function:FOO"
# Now FOO can be invoked.
FOO
} | Receive-Job -Wait -AutoRemoveJob
위 출력 문자열HEY
, 뜻대로
참고:
할당 대상
$function:FOO
함수를 은연중에 만듭니다.FOO
(요구에 따라) 그리고 할당된 값을 함수 본문으로 만듭니다. 할당된 값은 인스턴스(instance) 또는 a일 수 있습니다.[string]
, 소스 코드 텍스트입니다.참조
$function:FOO
기존의 것을 검색합니다.FOO
신체를 a로 기능시키다[scriptblock]
사례.가림막을 치고 있습니다.$using:
범위()$using:function:FOO
)의 본문을 검색합니다.FOO
호출자의 범위에서 기능합니다.참고:
때문에
$using:
,$using:function:FOO
가 아닙니다.[scriptblock]
예를 들면, 그러나 a[string]
의 경우에는Start-Job
, 의 놀라운 방식 때문에.[scriptblock]
교차 프로세스 직렬화를 수행할 때 인스턴스는 역직렬화됩니다. 동작은 설계에 의한 것으로 선언되었습니다. 자세한 내용은 GitHub issue #11698을 참조하십시오.이와 같이.
"..."
주위에$using:function:FOO
을 위해 불필요한Start-Job
, 하지만 그렇지는 않습니다.Start-ThreadJob
, 여기서는 직렬화가 수반되지 않으며 상태 손상을 방지하기 위해 문자열에서 본문을 재생성해야 합니다(자세한 내용은 GitHub issue #16461 참조).그 사실은
Start-ThreadJob
허용한다$using:function:FOO
참조는 아마도 과 함께 사용되는 스크립트 블록에서 명시적으로 허용되지 않은 것을 고려할 때 감독일 것입니다.ForEach-Object -Parallel
(PowerShell v7+) - GitHub 이슈 #12378 참조.따라서, 와 함께
ForEach-Object -Parallel
호출자 측에서 함수 본문을 먼저 문자열화하는 도우미 변수가 필요합니다. 이 답변을 참조하십시오.
[1] 이 답변은 에 의해 생성된 하위 프로세스 기반 작업에만 적용되는 것이 아니라 에 의해 생성된 일반적으로 선호되는 스레드 기반 작업과 에 의해 생성된 PowerShell(Core) 7+에서 사용할 수 있는 스레드 기반 병렬화에도 유사하게 적용됩니다. -Parallel
, 또한 PowerShell 원격 via - 즉, PowerShell이 다른 실행 공간에서 Out-of-run space를 실행하는 모든 시나리오에 적용됩니다.
[2] 스크립트 파일을 통해 이러한 정의를 제공하는 것이 대안입니다.*.ps1
또는 도트 소스().
를 가져오거나 가져와야 하는 모듈입니다.
언급URL : https://stackoverflow.com/questions/7162090/how-do-i-start-a-job-of-a-function-i-just-defined
'programing' 카테고리의 다른 글
PHP에서 연산자 오버로드가 가능합니까? (0) | 2023.11.01 |
---|---|
부모에서 자식으로 각진 상태로 이벤트 전달JS 구성요소 (0) | 2023.11.01 |
앱 설치 실패:장치에 쓸 수 없습니다. (0) | 2023.11.01 |
외부 API 통합을 위한 Best Wordpress 플러그인 (0) | 2023.11.01 |
보기 삭제 버튼 텍스트를 변경하는 방법 (0) | 2023.11.01 |