2011-02-16 2 views
9

그것은 믿기지 않는 것입니다. test.ps1 스크립트 폴더를 실행하는PowerShell mkdir alias + Set-StrictMode - 버전 2. 이상한 버그. 왜?

Set-StrictMode -Version 2 
mkdir c:\tmp\1 # same with 'md c:\tmp\1' 

시작 cmd.exe가, 이동 :

c:\tmp>powershell ".\test.ps1" 

를이 생산하는 다음과 같은 오류 :

The variable '$_' cannot be retrieved because it has not been set. 
At line:50 char:38 
+   $steppablePipeline.Process($_ <<<<) 
    + CategoryInfo   : InvalidOperation: (_:Token) [], ParentContainsEr 
    rorRecordException 
    + FullyQualifiedErrorId : VariableIsUndefined 

을이 test.ps1 파일에 PowerShell을 코드 ​​조각입니다 왜?

PowerShell 콘솔에서 시작했지만 cmd.exe에서는 시작할 때 작동하지 않습니다. 나는 훨씬 더 큰 스크립트에서이 버그를 발견했다. 그것은 WTF 순간이었습니다.

이 간단한 스크립트에는 어떤 문제가 있습니까?

답변

14

이미 해결 방법이 발견되었지만 사람들이 설명에 흥미가있을 것으로 생각했습니다. 사용시

powershell ".\test.ps1" 
powershell -File ".\test.ps1" 

:

는 cmd.exe를 대 셸에서 다르게 작동하는 이유에 관해서는, Powershell 2.0 - Running scripts for the command line call vs. from the ISE 기준에서 언급했듯이

은 다음 두 개의 명령 사이의 차이가 볼 첫 번째 구문은 전역 범위에서 정의 된 함수의 엄격 모드를 수정하기 위해 Set-StrictMode 명령을 사용하여 범위가 엉망인 것으로 보입니다.

이것은 mkdir 함수의 정의에서 버그 (또는 틀린 가정)를 유발합니다.

이 함수는 GetSteppablePipeline 메서드를 사용하여 New-Item cmdlet의 파이프 라인을 프록시합니다. 그러나 저자는 파이프 라인에 아무 것도없는 경우에도 PROCESS 섹션이 여전히 실행된다는 사실을 설명하지 않았습니다. 따라서 PROCESS 섹션에 도달하면 $ _ 자동 변수가 정의되지 않습니다. 엄격 모드를 사용하는 경우 예외가 발생합니다.

다음과 같은 라인을 교체하는 Microsoft는 것이 차지하기위한 한 가지 방법은 다음과

$steppablePipeline.Process($_) 

:

if (test-path Variable:Local:_) { 
     $steppablePipeline.Process($_) 
    } 

나는이 문제를 해결할 수있는 가장 좋은 방법이 될 수 없습니다 인정을 그러나 오버 헤드는 무시할 수 있습니다. 또 다른 옵션은 BEGIN 섹션에서 파이프 라인이 비어 있는지 테스트 한 다음 $ _을 $ null로 설정하는 것입니다.

"powershell.exe -File filename"구문을 사용하여 스크립트를 실행하면 아무 래도 걱정할 필요가 없습니다.

+0

클럽에 오신 것을 환영합니다! 정말로 좋은 조사. –

2

이것은 (PowerShell에서) 버그처럼 보입니다.

+3

나는'New-Item 'blah'-type directory'를 임시 해결책으로 사용했다. 문제는'mkdir'과'md' 별명들만있는 것 같습니다. – Roman

+0

이 대답을 받아 들일 것입니다. 그러나 "PowerShell 스크립트에서 별칭을 사용하지 마십시오. 이상한 문제가 없을 것입니다"라는 말로 해결할 것입니다. – Roman

+0

그러나 이것은 별칭에 관한 것이 아닙니다. 'mkdir'는 함수이고 엄격 모드가 켜져있을 때 문제가 있습니다. –