2012-10-02 3 views
7

일부 데이터를 열거하고 모든 경우에 스크립트 블록을 실행하는 PowerShell 함수를 만들려고합니다. 지금 내가 가지고함으로써매개 변수가있는 스크립트 블록이있는 PowerShell 함수

(이것은 실제 코드가 아니라 내 문제를 설명) :

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    process 
    { 
     $digits = 0..10 
     $digits | % { 
      $Action.Invoke($_); 
     } 
    } 
} 

내 모듈에이 기능을 넣어. 그러나 전화를 걸면 아무런 결과가 표시되지 않습니다.

Invoke-TenTimes { $_ } 

출력 내용이 비어 있습니다 (아무 것도 표시되지 않음). 내가

Invoke-TenTimes { $_ -eq $null } 

를 호출 할 경우

내가 10 true를 얻을. 사실 $_이 null이라는 것을 알았습니다.

$_을 채우는 적절한 방법은 무엇입니까?

은 무엇 나를 미치게되어, 나는이 기능과 같은 PS1 파일, 작동에 전화를 넣어 (하지만 필요에 따라 스크립트 블록을 전달하려는) 경우이다 :

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    process 
    { 
     $digits = 0..10 
     $digits | % { 
      $Action.Invoke($_); 
     } 
    } 
} 


Invoke-TenTimes { $_ } 

답변

2

이 범위 지정 문제는 그것이 실행되는 경우와는 다른 범위에 속하는 스크립트 블록 전달에있다. scriptblock이 전달 된 컨텍스트에서 변수를 참조 할 필요가 없다면 단순히 스크립트 블록을 복제하여 실행중인 범위에 스크립트 블록을 강제로 적용 할 수 있습니다.

$action = [scriptblock]::Create($action) 

재미있는 것은 ACCIDENT로 첫 번째로만 작업 한 것입니다. 스크립트 블록이 속한 곳의 부모 범위에서 $ _을 (를) 얻었습니다.

그러나 원래 버전을, 다음이

"gotcha" | % { 
Invoke-TenTimes { $_ } 
} 

를 실행하고, 당신이 잡았다 10 배를 얻을 수 있습니다 볼 수 있습니다 $ 때문에 _ 발신자의 범위에 포함되지 널 (null)이지만, 무언가이다.

+0

감사! 이게 내 문제를 해결했고, 이제 $ _와 함께 스크립트 블록을 사용할 수있게되었습니다. :) –

3

문제는 이는 모듈에만 해당됩니다. 아마도 이것도 버그 일 것입니다. 이 질문에 봐 주시기 바랍니다 :

Strange behavior with Powershell scriptblock variable scope and modules, any suggestions? 특정 사건에 대한,이 같은 함수를 호출

Invoke-TenTimes { $args[0] } 

를 예상대로 작동합니다 이런 식으로.

+0

내 문제가 해결되었습니다. 그러나 누군가 제안 할 실제 해결책이 있는지를보기 위해 며칠을 기다릴 것입니다. –

5

여기에 우리가 간다 :

$scriptblock = {param($number) Write-Host "Current Number is $number"} 

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    $digits = 1..10 
    $digits | ForEach-Object{Invoke-Command -ScriptBlock $Action -Args $_} 
} 

사용 :

Invoke-TenTimes $scriptblock 
0

누구나 누릴 수있는 것보다 훨씬 쉽습니다.

고려하십시오 $ A와 $ B는 전역 수준에서 정의되고 $ B 만 모듈 수준에서 정의됩니다. 스크립트 블록은 세 번째 범위입니다. 그 안에 $ A를 참조하고 전역 값을 얻습니다.마찬가지로 $ B를 참조하면 전역 인스턴스가 지나치게 커지기 때문에 모듈 수준 값을 얻습니다.

문제 : 둘 중 하나에 쓰려고하면 로컬 인스턴스가 만들어집니다.

않음 "([참조] $ {이름})" ".value는"실제 변수에 도달 할 필요가 있으므로, 기준 물체인지

([ref]$A).value = 'Something malicious' 

참고. 그래서

([ref]$B).value.Length 

는 범위를 통해 직접 제어 할 수 없습니다 어느 경우

$B.Length 

과 동일합니다. 당신은 당신이 읽을 인스턴스를 얻습니다. 따라서 첫 번째 예제는 Global $ A를 수정하고 두 번째 예제는 $ B의 모듈 수준 인스턴스를 참조합니다.

관련 문제