Desarrollé una función de PowerShell que realiza una serie de acciones que implican el aprovisionamiento de sitios de SharePoint Team. En última instancia, quiero que la función devuelva la URL del sitio aprovisionado como una Cadena, así que al final de mi función tengo el siguiente código:
$rs = $url.ToString();
return $rs;
El código que llama a esta función se ve así:
$returnURL = MyFunction -param 1 ...
Así que espero una cadena, sin embargo, no lo es. En cambio, es un objeto de tipo System.Management.Automation.PSMethod. ¿Por qué devuelve ese tipo en lugar de un tipo de cadena?
powershell
ChiliYago
fuente
fuente
Respuestas:
PowerShell tiene una semántica de retorno realmente extraña, al menos cuando se ve desde una perspectiva de programación más tradicional. Hay dos ideas principales para entender:
Por lo tanto, los siguientes dos bloques de script harán exactamente lo mismo:
La variable $ a en el segundo ejemplo se deja como salida en la tubería y, como se mencionó, se devuelve toda la salida. De hecho, en el segundo ejemplo, podría omitir el retorno por completo y obtendría el mismo comportamiento (el retorno estaría implícito a medida que la función se completa y sale de forma natural).
Sin más de su definición de función, no puedo decir por qué está obteniendo un objeto PSMethod. Supongo que probablemente tengas algo en línea que no se está capturando y se está colocando en la tubería de salida.
También vale la pena señalar que probablemente no necesite esos puntos y comas, a menos que esté anidando varias expresiones en una sola línea.
Puede leer más sobre la semántica de retorno en la página about_Return en TechNet, o invocando el
help return
comando desde PowerShell.fuente
write-debug
después de configurar la variable en$DebugPreference = "Continue"
lugar de"SilentlyContinue"
echo
fue el problema para mí! Ese pequeño punto secundario es muy muy importante. Estaba devolviendo una tabla hash, siguiendo todo lo demás, pero aún así el valor de retorno no era lo que esperaba. Eliminadoecho
y trabajado como un encanto.Esta parte de PowerShell es probablemente el aspecto más estúpido. Cualquier salida extraña generada durante una función contaminará el resultado. A veces no hay salida, y luego, en algunas condiciones, hay otra salida no planificada, además de su valor de retorno planificado.
Entonces, elimino la asignación de la llamada a la función original, de modo que el resultado termina en la pantalla, y luego paso hasta que algo que no planeé aparece en la ventana del depurador (usando el ISE de PowerShell ).
Incluso cosas como reservar variables en ámbitos externos causan resultados, como lo
[boolean]$isEnabled
cual escupirá molestamente un False a menos que lo haga[boolean]$isEnabled = $false
.Otra buena es la
$someCollection.Add("thing")
que escupe el nuevo recuento de colecciones.fuente
[boolean]$a
en powershell en realidad no declara la variable $ a. Puede confirmar esto siguiendo esa línea con la línea$a.gettype()
y comparar esa salida con cuando declara e inicializa con la cadena$a = [boolean]$false
.>
y<
ya se utilizan para la redirección de flujo de E / S hacia / desde archivos.>=
escribe stdout en un archivo llamado=
.Con PowerShell 5 ahora tenemos la capacidad de crear clases. Cambie su función a una clase, y return solo devolverá el objeto inmediatamente anterior. Aquí hay un ejemplo muy simple.
Si esta fuera una función, el resultado esperado sería
pero como clase, lo único que se devuelve es el entero 808979. Una clase es como una garantía de que solo devolverá el tipo declarado o nulo.
fuente
static
métodos. Conduciendo a la sintaxis[test_class]::return_what()
return 808979
, función o no.Write-Output
? Aquí no se hace referencia a la salida de "consola", sino a la función / cmdlet. Si quieres volcar cosas en la consola hayWrite-Verbose
,Write-Host
yWrite-Error
funciones, entre otras. Básicamente,Write-Output
está más cerca de lareturn
semántica que de un procedimiento de salida de consola. No abuses de ella,Write-Verbose
úsala con verbosidad, para eso es.Como solución, he estado devolviendo el último objeto en la matriz que obtienes de la función ... No es una gran solución, pero es mejor que nada:
Con todo, una forma más lineal de escribir lo mismo podría ser:
fuente
$b = $b[-1]
sería una forma más simple de obtener el último elemento o la matriz, pero aún más simple sería simplemente no generar valores que no desea.write-host
para enviarlo directamente.Paso un objeto Hashtable simple con un solo miembro de resultado para evitar la locura de retorno, ya que también quiero enviar a la consola. Actúa a través del pase por referencia.
Puedes ver ejemplos reales de uso en mi proyecto GitHub unpackTunes .
fuente
Es difícil de decir sin mirar el código. Asegúrese de que su función no devuelva más de un objeto y que capture los resultados de otras llamadas. ¿Qué obtienes por:
De todos modos, dos sugerencias:
Lanza el objeto a una cadena:
O simplemente enciérrelo entre comillas dobles, igual que arriba pero más corto para escribir:
fuente
"$rs"
- elreturn
sólo se requiere al regresar temprano de la función. Dejar de lado el retorno es mejor modismo de PowerShell.La descripción de Luke de los resultados de la función en estos escenarios parece ser correcta. Solo deseo comprender la causa raíz y el equipo del producto PowerShell haría algo al respecto. Parece ser bastante común y me ha costado demasiado tiempo de depuración.
Para solucionar este problema, he estado usando variables globales en lugar de devolver y usar el valor de la llamada a la función.
Aquí hay otra pregunta sobre el uso de variables globales: establecer una variable global de PowerShell desde una función donde el nombre de la variable global es una variable que se pasa a la función
fuente
Lo siguiente simplemente devuelve 4 como respuesta. Cuando reemplaza las expresiones de agregar para cadenas, devuelve la primera cadena.
Esto también se puede hacer para una matriz. El siguiente ejemplo devolverá "Texto 2"
Tenga en cuenta que debe llamar a la función debajo de la función misma. De lo contrario, la primera vez que se ejecute devolverá un error que no sabe qué es "StartingMain".
fuente
Las respuestas existentes son correctas, pero a veces no estás devolviendo algo explícitamente con a
Write-Output
o areturn
, sin embargo, hay un valor misterioso en los resultados de la función. Esta podría ser la salida de una función integrada comoNew-Item
Todo ese ruido extra de la creación del directorio se está recopilando y emitiendo en la salida. La manera fácil de mitigar esto es agregar
| Out-Null
al final de laNew-Item
declaración, o puede asignar el resultado a una variable y simplemente no usar esa variable. Se vería así ...New-Item
es probablemente el más famoso de estos, pero otros incluyen todos losStringBuilder.Append*()
métodos, así como elSqlDataAdapter.Fill()
método.fuente