2011-02-16 8 views
9

Es algo increíble. Este es un fragmento de código de PowerShell en test.ps1 archivo:PowerShell mkdir alias + Set-StrictMode -Version 2. Extraño error. ¿Por qué?

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

inicio cmd.exe, navegue a la carpeta con test.ps1 guión y ejecutarlo:

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

Esto produce el siguiente error:

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 

¿Por qué?

Funciona cuando se inicia desde la consola de PowerShell pero no con cmd.exe. Descubrí este error en un script mucho más grande. Fue un momento WTF.

¿Qué hay de malo en este sencillo script?

Respuesta

14

Aunque ya se ha encontrado una solución, pensé que la gente podría estar interesada en una explicación.

cuanto a por qué se comporta de manera diferente en la carcasa frente a cmd.exe, ver Powershell 2.0 - Running scripts for the command line call vs. from the ISE

Como se menciona en la referencia, hay una diferencia entre los dos comandos siguientes:

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

Cuando se utiliza el primera sintaxis, parece interferir con el alcance, haciendo que el comando Set-StrictMode modifique el modo estricto para las funciones definidas en el alcance global.

Esto desencadena un error (o una suposición incorrecta, tal vez) en la definición de la función mkdir.

La función hace uso del método GetSteppablePipeline para realizar un proxy de la canalización para el cmdlet New-Item. Sin embargo, el autor no tuvo en cuenta el hecho de que la sección PROCESO todavía se ejecuta incluso cuando no hay nada en la tubería. Por lo tanto, cuando se llega a la sección PROCESO, la variable $ _ automática no está definida. Si el modo estricto está habilitado, se producirá una excepción.

Una forma de Microsoft para dar cuenta de esto sería la de sustituir siguiente línea:

$steppablePipeline.Process($_) 

con lo siguiente:

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

Admito que esto puede no ser la mejor manera de solucionarlo , pero la sobrecarga sería insignificante. Otra opción sería probar de alguna manera si la tubería está vacía en la sección BEGIN, y luego configurar $ _ a $ null.

De cualquier forma, si ejecuta los scripts con la sintaxis "powershell.exe -File filename", entonces no tendrá que preocuparse por ello.

+0

¡Bienvenido al club! Muy buena investigación, de hecho. –

2

Parece un error (en PowerShell).

+3

Utilicé 'New-Item 'blah' -type directory' como una solución alternativa. El problema parece ser solo con los alias 'mkdir' y' md' – Roman

+0

Voy a aceptar esta respuesta, pero con la observación "evite usar alias en sus scripts de PowerShell y no tendrá problemas tan extraños". – Roman

+0

Pero esto no se trata de alias. 'mkdir' es una función y tiene un problema cuando el modo estricto está activado. –

Cuestiones relacionadas