Diferencias entre Windows PowerShell 5.1 y PowerShell 7.x

Windows PowerShell 5.1 se basa en .NET Framework v4.5. Con el lanzamiento de PowerShell 6.0, PowerShell se convirtió en un proyecto de código abierto basado en .NET Core 2.0. La migración de .NET Framework a .NET Core permitió a PowerShell convertirse en una solución multiplataforma. PowerShell se ejecuta en Windows, macOS y Linux.

Hay algunas diferencias en el lenguaje de PowerShell entre Windows PowerShell y PowerShell. Las diferencias más notables son la disponibilidad y el comportamiento de los cmdlets de PowerShell entre las plataformas Windows y no Windows y los cambios que se derivan de las diferencias entre .NET Framework y .NET Core.

En este artículo se resumen las diferencias significativas y los cambios importantes entre Windows PowerShell y la versión actual de PowerShell. El resumen no incluye nuevas características ni cmdlets que se han agregado. En el artículo tampoco se habla de los cambios entre versiones. El objetivo de este artículo es presentar el estado actual de PowerShell y en qué difiere de Windows PowerShell. Para obtener una explicación detallada de los cambios entre versiones y la incorporación de nuevas características, vea los artículos Novedades de cada versión.

.NET Framework frente a .NET Core

PowerShell en Linux y macOS usa .NET Core, que es un subconjunto de la instancia completa de .NET Framework en Microsoft Windows. Esto es importante, porque PowerShell proporciona acceso directo a los tipos de marco subyacentes y los métodos. Como resultado, los scripts que se ejecutan en Windows pueden no ejecutarse en plataformas que no son de Windows por las diferencias en los marcos. Para obtener más información sobre los cambios en .NET Core, vea Cambios importantes para la migración desde .NET Framework a .NET Core.

Cada nueva versión de PowerShell se basa en una versión más reciente de .NET. Puede haber cambios rotundos en .NET que afecten a PowerShell.

  • PowerShell 7.5: basado en .NET 9.0
  • PowerShell 7.4: basado en .NET 8.0
  • PowerShell 7.3: basado en .NET 7.0
  • PowerShell 7.2 (LTS-current): basado en .NET 6.0 (LTS-current)
  • PowerShell 7.1: basado en .NET 5.0
  • PowerShell 7.0 (LTS): basado en .NET Core 3.1 (LTS)
  • PowerShell 6.2: basado en .NET Core 2.1
  • PowerShell 6.1: basado en .NET Core 2.1
  • PowerShell 6.0: basado en .NET Core 2.0

Con el lanzamiento de .NET Standard 2.0, PowerShell puede cargar muchos módulos tradicionales de Windows PowerShell sin modificación. Además, PowerShell 7 incluye una característica de compatibilidad de Windows PowerShell que permite usar módulos de Windows PowerShell que todavía requieren el marco completo.

Para obtener más información, consulte:

Tenga en cuenta los cambios en el método de .NET

Aunque los cambios de método de .NET no son específicos de PowerShell, pueden afectar a los scripts, especialmente si llama directamente a métodos de .NET. Además, puede haber nuevas sobrecargas para constructores. Esto puede tener un impacto en cómo se crean objetos mediante New-Object o el método [type]::new().

Por ejemplo, .NET agregó sobrecargas al método [System.String]::Split() que no están disponibles en .NET Framework 4.5. En la lista siguiente se muestran las sobrecargas del método Split() disponible en Windows PowerShell 5.1:

PS> "".Split

OverloadDefinitions
-------------------
string[] Split(Params char[] separator)
string[] Split(char[] separator, int count)
string[] Split(char[] separator, System.StringSplitOptions options)
string[] Split(char[] separator, int count, System.StringSplitOptions options)
string[] Split(string[] separator, System.StringSplitOptions options)
string[] Split(string[] separator, int count, System.StringSplitOptions options)

En la lista siguiente se muestran las sobrecargas del método Split() disponible en PowerShell 7:

"".Split

OverloadDefinitions
-------------------
string[] Split(char separator, System.StringSplitOptions options)
string[] Split(char separator, int count, System.StringSplitOptions options)
string[] Split(Params char[] separator)
string[] Split(char[] separator, int count)
string[] Split(char[] separator, System.StringSplitOptions options)
string[] Split(char[] separator, int count, System.StringSplitOptions options)
string[] Split(string separator, System.StringSplitOptions options)
string[] Split(string separator, int count, System.StringSplitOptions options)
string[] Split(string[] separator, System.StringSplitOptions options)
string[] Split(string[] separator, int count, System.StringSplitOptions options)

En Windows PowerShell 5.1, puede pasar una matriz de caracteres (char[]) al método Split() como string. El método divide la cadena de destino cuando aparezca un carácter determinado en la matriz. El siguiente comando divide la cadena de destino en Windows PowerShell 5.1, pero no en PowerShell 7:

# PowerShell 7 example
"1111p2222q3333".Split('pq')
1111p2222q3333

Para enlazar a la sobrecarga correcta, debe escribir la cadena en una matriz de caracteres:

# PowerShell 7 example
"1111p2222q3333".Split([char[]]'pq')
1111
2222
3333

Módulos que ya no se incluyen en PowerShell

Por distintas razones de compatibilidad, los módulos a continuación ya no se incluyen en PowerShell.

  • ISE
  • Microsoft.PowerShell.LocalAccounts
  • Microsoft.PowerShell.ODataUtils
  • Microsoft.PowerShell.Operation.Validation
  • PSScheduledJob
  • PSWorkflow
  • PSWorkflowUtility

Flujo de trabajo de PowerShell

El flujo de trabajo de PowerShell es una característica de Windows PowerShell basada en Windows Workflow Foundation (WF) que permite la creación de runbooks sólidos para tareas de larga ejecución o paralelizadas.

Debido a la falta de compatibilidad con Windows Workflow Foundation en .NET Core, se ha quitado de PowerShell el flujo de trabajo de PowerShell.

En el futuro, nos gustaría habilitar paralelismo nativo/simultaneidad en el lenguaje de PowerShell sin la necesidad del flujo de trabajo de PowerShell.

Si es necesario usar puntos de control para reanudar un script una vez reiniciado el sistema operativo, recomendamos usar Programador de tareas para ejecutar un script al iniciarse el sistema operativo, pero el script debería mantener su propio estado (como conservarlo en un archivo).

Cmdlets quitados de PowerShell

En los módulos incluidos en PowerShell, se han quitado los cmdlets de PowerShell a continuación por distintos motivos de compatibilidad o el uso de API no admitidas.

CimCmdlets

  • Export-BinaryMiLog

Microsoft.PowerShell.Core

  • Add-PSSnapin
  • Export-Console
  • Get-PSSnapin
  • Remove-PSSnapin
  • Resume-Job
  • Suspend-Job

Microsoft.PowerShell.Diagnostics

  • Export-Counter
  • Import-Counter

Microsoft.PowerShell.Management

  • Add-Computer
  • Checkpoint-Computer
  • Clear-EventLog
  • Complete-Transaction
  • Disable-ComputerRestore
  • Enable-ComputerRestore
  • Get-ComputerRestorePoint
  • Get-ControlPanelItem
  • Get-EventLog
  • Get-Transaction
  • Get-WmiObject
  • Invoke-WmiMethod
  • Limit-EventLog
  • New-EventLog
  • New-WebServiceProxy
  • Register-WmiEvent
  • Remove-Computer
  • Remove-EventLog
  • Remove-WmiObject
  • Reset-ComputerMachinePassword
  • Restore-Computer
  • Set-WmiInstance
  • Show-ControlPanelItem
  • Show-EventLog
  • Start-Transaction
  • Test-ComputerSecureChannel
  • Undo-Transaction
  • Use-Transaction
  • Write-EventLog

Microsoft.PowerShell.Utility

  • Convert-String
  • ConvertFrom-String

PSDesiredStateConfiguration

  • Disable-DscDebug
  • Enable-DscDebug
  • Get-DscConfiguration
  • Get-DscConfigurationStatus
  • Get-DscLocalConfigurationManager
  • Publish-DscConfiguration
  • Remove-DscConfigurationDocument
  • Restore-DscConfiguration
  • Set-DscLocalConfigurationManager
  • Start-DscConfiguration
  • Stop-DscConfiguration
  • Test-DscConfiguration
  • Update-DscConfiguration

Cmdlets WMI v1

Los cmdlets de WMI v1 siguientes se han quitado de PowerShell:

  • Register-WmiEvent
  • Set-WmiInstance
  • Invoke-WmiMethod
  • Get-WmiObject
  • Remove-WmiObject

Los cmdlets del módulo CimCmdlets (también conocido como WMI v2) realizan la misma función, y proporcionan nueva funcionalidad y una sintaxis rediseñada.

Cmdlet New-WebServiceProxy quitado

.NET Core no es compatible con Windows Communication Framework, que proporciona servicios para usar el protocolo SOAP. Este cmdlet se quitó porque requiere SOAP.

*-Transaction cmdlets quitados

Estos cmdlets tenían un uso muy limitado. Se tomó la decisión de dejar de admitirlos.

  • Complete-Transaction
  • Get-Transaction
  • Start-Transaction
  • Undo-Transaction
  • Use-Transaction

Cmdlets de *-EventLog

Debido al uso de API no admitidas, los cmdlets de *-EventLog se han quitado de PowerShell. Get-WinEvent y New-WinEvent están disponibles para obtener y crear eventos en Windows.

Cmdlets que usan Windows Presentation Framework (WPF)

.NET Core 3.1 incorporó compatibilidad con WPF, por lo que el lanzamiento de PowerShell 7.0 ha restaurado las características específicas de Windows siguientes:

  • El cmdlet Show-Command
  • El cmdlet Out-GridView
  • El parámetro ShowWindow de Get-Help

Cambios de Desired State Configuration (DSC) de PowerShell

Invoke-DscResource se restauró como característica experimental en PowerShell 7.0.

A partir de PowerShell 7.2, el módulo PSDesiredStateConfiguration se ha quitado de PowerShell y se ha publicado en la Galería de PowerShell. Para obtener más información, vea el anuncio en el blog del equipo de PowerShell.

Cambios en el archivo ejecutable de PowerShell

Cambio de nombre de powershell.exe a pwsh.exe

El nombre binario de PowerShell se ha cambiado de powershell(.exe) a pwsh(.exe). Este cambio proporciona una forma determinista de ejecutar PowerShell en las máquinas y de admitir instalaciones en paralelo de Windows PowerShell y PowerShell.

Cambios adicionales en pwsh(.exe) con respecto a powershell.exe:

  • Se ha cambiado el primer parámetro posicional de -Command a -File. Este cambio corrige el uso de #! (también conocido como par de caracteres shebang) en los scripts de PowerShell que se ejecutan desde shells que no son de PowerShell en plataformas distintas de Windows. También implica que se pueden ejecutar comandos como pwsh foo.ps1 o pwsh fooScript sin especificar -File. Aun así, este cambio requiere que se especifique explícitamente -c o -Command al intentar ejecutar comandos como pwsh.exe -Command Get-Command.
  • pwsh acepta el modificador -i (o -Interactive) para indicar un shell interactivo. Esto permite usar PowerShell como shell predeterminado en plataformas Unix.
  • Se han quitado los parámetros -ImportSystemModules y -PSConsoleFile de pwsh.exe.
  • Se ha cambiado pwsh -version y se ha integrado ayuda para pwsh.exe para que sea acorde con otras herramientas nativas.
  • Mensajes de error de argumento no válido para -File y -Command y códigos de salida coherentes con los estándares de Unix
  • Se ha agregado el parámetro -WindowStyle en Windows. De forma similar, las actualizaciones de instalaciones basadas en paquete en plataformas no Windows son actualizaciones en contexto.

El nombre abreviado también es coherente con la nomenclatura de los shells en las plataformas que no son de Windows.

Compatibilidad con la ejecución de un script de PowerShell con el parámetro bool

Anteriormente, el uso de pwsh.exe para ejecutar un script de PowerShell con -File no proporcionaba ninguna forma de pasar $true/$false como valores de parámetro. La compatibilidad con $true/$false como valores analizados de parámetros se agregó. También se admiten valores de modificador.

Compatibilidad con versiones anteriores mejoradas con Windows PowerShell

En Windows, se agrega un nuevo parámetro de modificador UseWindowsPowerShell a Import-Module. Este modificador crea un módulo de proxy en PowerShell 7 que usa un proceso local de Windows PowerShell para ejecutar implícitamente los cmdlets contenidos en ese módulo. Para obtener más información, consulte Import-Module.

Para más información sobre qué módulos de Microsoft funcionan con PowerShell 7.0, vea la tabla de compatibilidad de módulos.

Soporte técnico de Microsoft Update en Windows

PowerShell 7.2 incluyó soporte técnico con Microsoft Update. Al habilitar esta característica, se obtienen las actualizaciones más recientes de PowerShell 7 en el flujo de administración tradicional de Windows Update (WU), ya sea con Windows Update for Business, WSUS, SCCM o el cuadro de diálogo WU interactivo de Configuración.

El paquete MSI de PowerShell 7.2 incluye las siguientes opciones de línea de comandos:

  • USE_MU: esta propiedad tiene dos valores posibles:
    • 1 (valor predeterminado): permite actualizar mediante Microsoft Update o WSUS
    • 0: no permite realizar la actualización mediante Microsoft Update o WSUS
  • ENABLE_MU
    • 1 (valor predeterminado): permite usar Microsoft Update para las actualizaciones automáticas o Windows Update.
    • 0: no permite usar Microsoft Update para las actualizaciones automáticas o Windows Update

Cambios en el motor

Compatibilidad de PowerShell como shell de Unix predeterminado

En Unix, es una convención para que los shells acepten -i para un shell interactivo y muchas herramientas esperan este comportamiento (script por ejemplo y al establecer PowerShell como el shell predeterminado) y llama al shell con el conmutador -i. Este cambio es importante en que -i podía usarse anteriormente como fórmula sencilla para coincidir con -inputformat, que ahora debe ser -in.

Complementos personalizados

Los complementos de PowerShell son un predecesor de los módulos de PowerShell cuya adopción en la comunidad de PowerShell no está generalizada.

Debido a la complejidad de admitir complementos y a su falta de uso en la comunidad, ya no se admiten complementos personalizados en PowerShell.

Marcas de características experimentales

En PowerShell 6.2 ya habíamos habilitado la compatibilidad con las características experimentales. Esto permite a los desarrolladores de PowerShell ofrecer nuevas características y obtener comentarios antes de completar el diseño. De este modo, evitamos realizar cambios importantes a medida que evoluciona el diseño.

Use Get-ExperimentalFeature para obtener una lista de las características experimentales disponibles. Puede habilitar o deshabilitar estas características con Enable-ExperimentalFeature y Disable-ExperimentalFeature.

Carga de un ensamblado desde la ruta de acceso base del módulo antes de intentar cargar desde GAC

Anteriormente, si un módulo binario tenía el ensamblado de módulo en GAC, se cargaba el ensamblado desde GAC antes de intentar cargarlo desde la ruta de acceso base del módulo.

Omisión de la comprobación del elemento NULL en las colecciones con un tipo de elemento de tipo de valor

En el parámetro Mandatory y los atributos ValidateNotNull y ValidateNotNullOrEmpty, omita la comprobación del elemento NULL si el tipo de elemento de la colección es tipo de valor.

Conservación de $? en ParenExpression, SubExpression y ArrayExpression

Esta solicitud de incorporación de cambios modifica la forma en que se compilan las subcanalizaciones (...), las subexpresiones $(...) y las expresiones de matriz @() para que $? no sea automáticamente true. En su lugar, el valor de $? depende del resultado de la canalización o las instrucciones ejecutadas.

Corrección de $? para que no sea $false cuando el comando nativo escribe en stderr

$? no se establece en $false cuando el comando nativo escribe en stderr. Es habitual que los comandos nativos escriban en stderr sin intención de indicar un error. $? se establece en $false únicamente cuando el comando nativo tiene un código de salida distinto de cero.

$ErrorActionPreference no afecta a la salida stderr de los comandos nativos

Es habitual que los comandos nativos escriban en stderr sin intención de indicar un error. Con este cambio, la salida de stderr se sigue capturando en los objetos ErrorRecord, pero el entorno de ejecución ya no aplica $ErrorActionPreference si ErrorRecord proviene de un comando nativo.

Cambio de $OutputEncoding para usar codificación UTF-8 NoBOM en lugar de ASCII

La codificación anterior, ASCII (7 bits), daría lugar a una alteración incorrecta de la salida en algunos casos. Al convertir UTF-8 NoBOM en el valor predeterminado, se conserva la salida Unicode con una codificación admitida por la mayoría de las herramientas y los sistemas operativos.

Unificación de los cmdlets con el parámetro -Encoding para que sean de tipo System.Text.Encoding

El valor -EncodingByte se ha quitado de los cmdlets del proveedor del sistema de archivos. Un nuevo parámetro, -AsByteStream, se usa ahora para especificar que un flujo de bytes se necesita como entrada o que la salida es un flujo de bytes.

Cambio de la codificación New-ModuleManifest por UTF8NoBOM en plataformas no Windows

Anteriormente, New-ModuleManifest creaba manifiestos psd1 en UTF-16 con BOM, lo que creaba un problema para las herramientas de Linux. Este cambio importante cambia la codificación de New-ModuleManifest para que sea UTF (sin BOM) en plataformas que no son de Windows.

Eliminación de AllScope de la mayoría de los alias predeterminados

Para acelerar la creación de ámbito, AllScope se quitó de la mayoría de los alias predeterminados. AllScope se dejó para un alias no usado con frecuencia donde la búsqueda era más rápida.

-Verbose y -Debug ya no invalidan $ErrorActionPreference

Anteriormente, si se especificaban -Verbose o -Debug, invalidaba el comportamiento de $ErrorActionPreference. Con este cambio, -Verbose y -Debug ya no influyen en el comportamiento de $ErrorActionPreference.

Además, el parámetro -Debug establece $DebugPreference en Continue en lugar de en Inquire.

$PSCulture refleja de forma coherente los cambios en la referencia cultural en la sesión

En Windows PowerShell, el valor actual de la referencia cultural se almacena en caché, lo que puede permitir que el valor se desincronice si la referencia cultural se cambia después de iniciar sesión. Este comportamiento de almacenamiento en caché se ha corregido en PowerShell Core.

Permisos para que un parámetro con nombre especificado explícitamente reemplace al mismo de la expansión mediante tabla hash

Con este cambio, los parámetros con nombre de la expansión se mueven al final de la lista de parámetros para que se enlacen después de que se hayan enlazado todos los parámetros con nombre especificados explícitamente. El enlace de parámetros para funciones simples no produce ningún error cuando no se puede encontrar un parámetro con nombre especificado. Los parámetros con nombre desconocidos se enlazan con el parámetro $args de la función simple. Al mover la expansión al final de la lista de argumentos, se cambia el orden en el que aparecen los parámetros en $args.

Por ejemplo:

function SimpleTest {
    param(
        $Name,
        $Path
    )
    "Name: $Name; Path: $Path; Args: $args"
}

En el comportamiento anterior, MyPath no está enlazado con -Path porque es el tercer argumento de la lista de argumentos. ## Por lo tanto, termina rellenándose en "$args" junto con Blah = "World".

PS> $hash = @{ Name = "Hello"; Blah = "World" }
PS> SimpleTest @hash "MyPath"
Name: Hello; Path: ; Args: -Blah: World MyPath

Con este cambio, los argumentos de @hash se mueven al final de la lista de argumentos. MyPath se convierte en el primer argumento de la lista, así que está enlazado con -Path.

PS> SimpleTest @hash "MyPath"
Name: Hello; Path: MyPath; Args: -Blah: World

Cambios de idioma

Operador de fusión de NULL ??

El operador de fusión de NULL ?? devuelve el valor de su operando de la izquierda si no es NULL. De lo contrario, evalúa el operando de la derecha y devuelve su resultado. El operador ?? no evalúa su operando de la derecha si el operando de la izquierda se evalúa como no NULL.

$x = $null
$x ?? 100
100

En el ejemplo siguiente, el operando de la derecha no se evaluará.

[string] $todaysDate = '1/10/2020'
$todaysDate ?? (Get-Date).ToShortDateString()
1/10/2020

Operador de asignación de coalescencia NULL ??=

El operador de asignación de coalescencia NULL ??= asigna el valor del operando de la derecha a su operando de la izquierda solo si este último se evalúa como NULL. El operador ??= no evalúa su operando de la derecha si el operando de la izquierda se evalúa como no NULL.

$x = $null
$x ??= 100
$x
100

En el ejemplo siguiente, el operando de la derecha no se evaluará.

[string] $todaysDate = '1/10/2020'
$todaysDate ??= (Get-Date).ToShortDateString()
1/10/2020

Operadores condicionales NULL

Nota

Esta característica se movió de la rama experimental a la estándar en PowerShell 7.1.

Un operador condicional NULL aplica un acceso a miembros, ?., o el acceso a elementos, ?[], operación a su operando solo si ese operando se evalúa como no NULL; de lo contrario, devuelve NULL.

Puesto que PowerShell permite que ? forme parte del nombre de la variable, se requiere la especificación formal del nombre de la variable para utilizar estos operadores. Por lo tanto, es necesario usar {} en torno a los nombres de variable como ${a} o cuando ? forma parte del nombre de la variable ${a?}.

En el siguiente ejemplo, se devuelve el valor de PropName.

$a = @{ PropName = 100 }
${a}?.PropName
100

En el ejemplo siguiente se devolverá NULL, sin intentar acceder al nombre de miembro PropName.

$a = $null
${a}?.PropName

Del mismo modo se devolverá el valor del elemento.

$a = 1..10
${a}?[0]
1

Y cuando el operando es NULL, no se accede al elemento y se devuelve NULL.

$a = $null
${a}?[0]

Nota

La sintaxis de nombre de variable de ${<name>} no debe confundirse con el operador de subexpresión $(). Para obtener más información, consulte la sección Nombre de variable de about_Variables.

Incorporación del operador & para el control de un trabajo

Cuando se incluye & al final de una canalización, esta se ejecuta como un trabajo de PowerShell. Cuando una canalización se pasa a segundo plano, se devuelve un objeto de trabajo. Una vez que la canalización se ejecuta como un trabajo, se pueden usar todos los cmdlets *-Job estándar para administrar el trabajo. Las variables (se omiten las específicas del proceso) que se usan en la canalización se copian automáticamente en el trabajo para que funcione Copy-Item $foo $bar &. El trabajo también se ejecuta en el directorio actual, en lugar del directorio principal del usuario.

Nuevos métodos y propiedades en PSCustomObject

Se han agregado nuevos métodos y propiedades a PSCustomObject. PSCustomObject ahora incluye una propiedad Count/Length como otros objetos.

$PSCustomObject = [pscustomobject]@{foo = 1}

$PSCustomObject.Length
1
$PSCustomObject.Count
1

Este trabajo también incluye los métodos ForEach y Where que permiten operar y filtrar en elementos PSCustomObject:

$PSCustomObject.ForEach({$_.foo + 1})
2
$PSCustomObject.Where({$_.foo -gt 0})
foo
---
  1

Conversiones de PSMethod a delegado

Puede convertir PSMethod en un delegado. Esto permite hacer cosas como pasar PSMethod[M]::DoubleStrLen como un valor de delegado en [M]::AggregateString:

class M {
    static [int] DoubleStrLen([string] $value) { return 2 * $value.Length }

    static [long] AggregateString([string[]] $values, [func[string, int]] $selector) {
        [long] $res = 0
        foreach($s in $values){
            $res += $selector.Invoke($s)
        }
        return $res
    }
}

[M]::AggregateString((gci).Name, [M]::DoubleStrLen)

Comportamiento de comparación de cadenas cambiado en PowerShell 7.1

PowerShell 7.1 se basa en .NET 5.0, que introdujo el siguiente cambio rotundo:

A partir de .NET 5.0, las comparaciones de cadenas de referencia cultural invariable omiten los caracteres de control no imprimibles.

Por ejemplo, las dos cadenas siguientes se consideran idénticas:

# Escape sequence "`a" is Ctrl-G or [char]7
'Food' -eq "Foo`ad"
True

Nuevos cmdlets

Nuevo cmdlet Get-Uptime

El cmdlet Get-Uptime devuelve el tiempo transcurrido desde el último arranque del sistema operativo. Este cmdlet se introdujo en PowerShell 6.0.

Nuevo cmdlet Remove-Alias

El cmdlet Remove-Alias quita un alias de la sesión actual de PowerShell. Este cmdlet se introdujo en PowerShell 6.0.

Nuevo cmdlet Remove-Service

El cmdlet Remove-Service quita un servicio de Windows del Registro y de la base de datos del servicio. El cmdlet Remove-Service se introdujo en PowerShell 6.0.

Nuevos cmdlets de Markdown

Markdown es un estándar para crear documentos de texto simple legible con el formato básico que se puede representar en HTML.

Los siguientes cmdlets se agregaron en PowerShell 6.1:

  • ConvertFrom-Markdown: convierte el contenido de una cadena o un archivo en un objeto MarkdownInfo.
  • Get-MarkdownOption: devuelve los colores y estilos actuales que se usan para representar el contenido de Markdown en la consola.
  • Set-MarkdownOption: devuelve los colores y estilos actuales que se usan para representar el contenido de Markdown en la consola.
  • Show-Markdown: muestra el contenido de Markdown en la consola o como HTML.

Nuevo cmdlet Test-Json

El cmdlet Test-Json prueba si una cadena es un documento válido de notación de objetos JavaScript (JSON) y puede comprobar opcionalmente el documento JSON según un esquema proporcionado.

Este cmdlet se introdujo en PowerShell 6.1.

Nuevos cmdlets para admitir características experimentales

Los siguientes cmdlets se agregaron en PowerShell 6.2 para admitir características experimentales.

Nuevo cmdlet Join-String

El cmdlet Join-String combina objetos de la canalización en una sola cadena. Este cmdlet se agregó en PowerShell 6.2.

Nueva vista ConciseView y cmdlet Get-Error

PowerShell 7.0 mejora la visualización de los mensajes de error para aumentar la legibilidad de los errores interactivos y de script con una nueva vista predeterminada, ConciseView. Las vistas las puede seleccionar el usuario a través de la variable de preferencia $ErrorView.

Con ConciseView, si no se trata de un error de script o de analizador, se trata de un mensaje de error de una sola línea:

Get-Childitem -Path c:\NotReal
Get-ChildItem: Cannot find path 'C:\NotReal' because it does not exist

Si el error se produce durante la ejecución del script o es un error de análisis, PowerShell devuelve un mensaje de error de varias líneas que contiene el error, un puntero y un mensaje de error que muestra dónde se encuentra el error en esa línea. Si el terminal no es compatible con las secuencias de escape de color ANSI (VT100), no se muestran los colores.

La vista predeterminada de PowerShell 7 es ConciseView. La vista predeterminada anterior era NormalView; para seleccionarla, el usuario puede establecer la variable de preferencia $ErrorView.

$ErrorView = 'NormalView' # Sets the error view to NormalView
$ErrorView = 'ConciseView' # Sets the error view to ConciseView

Nota

Se agrega una nueva propiedad ErrorAccentColor a $Host.PrivateData para admitir el cambio del color de énfasis del mensaje de error.

El nuevo cmdlet Get-Error proporciona una vista detallada del error completo cuando se solicite. De forma predeterminada, el cmdlet muestra todos los detalles, incluidas las excepciones internas, del último error que se produjo.

El cmdlet Get-Error admite la entrada desde la canalización mediante la variable $Error integrada. Get-Error muestra todos los errores canalizados.

$Error | Get-Error

El cmdlet Get-Error admite el parámetro Newest, lo que le permite especificar el número de errores de la sesión actual que desea mostrar.

Get-Error -Newest 3 # Displays the lst three errors that occurred in the session

Para obtener más información, consulte Get-Error.

Cambios en el cmdlet

Ejecución en paralelo agregada a ForEach-Object

A partir de PowerShell 7.0, el cmdlet ForEach-Object, que itera los elementos de una colección, ahora tiene un paralelismo integrado con el nuevo parámetro Parallel.

De forma predeterminada, los bloques de script paralelos usan el directorio de trabajo actual del autor de la llamada que inició las tareas paralelas.

En este ejemplo se recuperan 50 000 entradas de registro de cinco registros del sistema en una máquina local Windows:

$logNames = 'Security','Application','System','Windows PowerShell','Microsoft-Windows-Store/Operational'

$logEntries = $logNames | ForEach-Object -Parallel {
    Get-WinEvent -LogName $_ -MaxEvents 10000
} -ThrottleLimit 5

$logEntries.Count

50000

El parámetro Parallel especifica el bloque de script que se ejecuta en paralelo para cada nombre de registro de entrada.

El nuevo parámetro ThrottleLimit limita el número de bloques de scripts que se ejecutan en paralelo en un momento dado. El valor predeterminado es 5.

Use la variable $_ para representar el objeto de entrada actual en el bloque de scripts. Utilice el ámbito $using: para pasar las referencias de variable al bloque de script en ejecución.

Para obtener más información, consulte ForEach-Object.

Comprobación de system32 para conocer los módulos integrados compatibles en Windows

En la actualización 1809 de Windows 10 y Windows Server 2019 se han actualizado una serie de módulos integrados de PowerShell para marcarlos como compatibles con PowerShell.

Cuando PowerShell se inicia, incluye automáticamente $windir\System32 como parte de la variable de entorno PSModulePath. Pero solo expone módulos a Get-Module y Import-Module si su CompatiblePSEdition está marcado como compatible con Core.

Puede invalidar este comportamiento para que se muestren todos los módulos mediante el parámetro de modificador -SkipEditionCheck. También hemos agregado una propiedad PSEdition a la salida de la tabla.

Alias -lp para todos los parámetros -LiteralPath

Se ha creado un alias de parámetro estándar -lp para todos los cmdlets integrados de PowerShell que tienen un parámetro -LiteralPath.

Corrección de Get-Item -LiteralPath a*b si a*b no existe realmente para devolver un error

Anteriormente, -LiteralPath al que se le daba un carácter comodín lo trataría de la misma forma que -Path y, si el carácter comodín no encontraba ningún archivo, existiría en modo silencioso. El comportamiento correcto debería ser que -LiteralPath fuera literal de modo que, de no existir el archivo, debería producir un error. El cambio consiste en tratar los caracteres comodín usados con -Literal como literales.

Establecimiento del directorio de trabajo en el directorio actual en Start-Job

El cmdlet Start-Job ahora usa el directorio actual como directorio de trabajo del nuevo trabajo.

Eliminación de -Protocol de los cmdlets de *-Computer

Debido a problemas con la comunicación remota RPC en CoreFX (especialmente en plataformas que no son de Windows) y la garantía de una experiencia de comunicación remota coherente en PowerShell, el parámetro -Protocol se quitó de los cmdlets \*-Computer. DCOM ya no se admite para la comunicación remota. Los cmdlets siguientes solo admiten la comunicación remota mediante WSMAN:

  • Rename-Computer
  • Restart-Computer
  • Stop-Computer

Eliminación de -ComputerName de los cmdlets de *-Service

Para fomentar el uso coherente de PSRP, el parámetro -ComputerName se quitó de los cmdlets *-Service.

Corrección de Get-Content -Delimiter para no incluir el delimitador en las líneas devueltas

Anteriormente, la salida mientras se usaba Get-Content -Delimiter era incoherente e incómoda, ya que requería un mayor procesamiento de los datos para quitar el delimitador. Este cambio quita el delimitador en líneas devueltas.

Cambios en Format-Hex

El parámetro -Raw ahora es un "no-op" (ahí no hace nada). En adelante, toda salida se muestra con una representación verdadera de números que incluye todos los bytes de su tipo. Esto es lo que hacía el parámetro -Raw antes de este cambio.

Corrección de error de escritura en el nombre de la propiedad Get-ComputerInfo

BiosSerialNumber se escribió incorrectamente como BiosSeralNumber y se ha cambiado a la ortografía correcta.

Incorporación de los cmdlets Get-StringHash y Get-FileHash

Este cambio consiste en que algunos algoritmos hash no son compatibles con CoreFX, por lo que ya no están disponibles:

  • MACTripleDES
  • RIPEMD160

Incorporación de validación a los cmdlets de Get-* donde al pasar $null se devuelven todos los objetos en lugar de un error

Ahora, al pasar $null a cualquiera de los siguientes elementos, se muestra un error:

  • Get-Credential -UserName
  • Get-Event -SourceIdentifier
  • Get-EventSubscriber -SourceIdentifier
  • Get-Help -Name
  • Get-PSBreakpoint -Script
  • Get-PSProvider -PSProvider
  • Get-PSSessionConfiguration -Name
  • Get-Runspace -Name
  • Get-RunspaceDebug -RunspaceName
  • Get-Service -Name
  • Get-TraceSource -Name
  • Get-Variable -Name

Incorporación de compatibilidad con el formato de archivo de registro extendido W3C en Import-Csv

Anteriormente, el cmdlet Import-Csv no se podía usar directamente para importar los archivos de registro en el formato de registro extendido W3C y se requerían medidas adicionales. Con este cambio, el formato de registro extendido W3C se admite.

Import-Csv aplica PSTypeNames durante la importación cuando la información de tipo está presente en el CSV

Anteriormente, los objetos exportados mediante el uso de Export-CSV con TypeInformation importado con ConvertFrom-Csv no retenían la información de tipo. Este cambio agrega la información de tipo al miembro PSTypeNames si está disponible desde el archivo CSV.

-NoTypeInformation es el valor predeterminado en Export-Csv

Anteriormente, el cmdlet Export-CSV generaba un comentario como primera línea que incluía el nombre de tipo del objeto. El cambio excluye la información de tipo de manera predeterminada porque la mayoría de las herramientas CSV no la entienden. Este cambio se ha realizado en respuesta a los comentarios de los clientes.

Use -IncludeTypeInformation para retener el comportamiento anterior.

Permiso para usar * en la ruta de acceso del Registro para Remove-Item

Anteriormente, -LiteralPath al que se le daba un carácter comodín lo trataría de la misma forma que -Path y, si el carácter comodín no encontraba ningún archivo, existiría en modo silencioso. El comportamiento correcto debería ser que -LiteralPath fuera literal de modo que, de no existir el archivo, debería producir un error. El cambio consiste en tratar los caracteres comodín usados con -Literal como literales.

Ahora, Group-Object ordena los grupos

Como parte de la mejora del rendimiento, Group-Object ahora devuelve una lista ordenada de los grupos. Aunque no debe confiar en el orden, podría verse interrumpida por este cambio si quisiera el primer grupo. Decidimos que esta mejora en el rendimiento valía la pena el cambio, ya que el impacto de depender del comportamiento previo es bajo.

Desviación estándar en Measure-Object

La salida de Measure-Object ahora incluye una propiedad StandardDeviation.

Get-Process | Measure-Object -Property CPU -AllStats
Count             : 308
Average           : 31.3720576298701
Sum               : 9662.59375
Maximum           : 4416.046875
Minimum           :
StandardDeviation : 264.389544720926
Property          : CPU

Get-PfxCertificate -Password

Get-PfxCertificate tiene ahora el parámetro Password, que toma SecureString. Esto permite usarlo de forma no interactiva:

$certFile = '\\server\share\pwd-protected.pfx'
$certPass = Read-Host -AsSecureString -Prompt 'Enter the password for certificate: '

$certThumbPrint = (Get-PfxCertificate -FilePath $certFile -Password $certPass ).ThumbPrint

Eliminación de la función more

Antes, PowerShell incluía una función en Windows llamada more que encapsulaba more.com. Se ha quitado esa función.

Además, se ha cambiado la función help para usar more.com en Windows o el elemento de paginación del sistema predeterminado especificado por $env:PAGER en plataformas que no sean Windows.

cd DriveName: ahora devuelve a los usuarios al directorio de trabajo actual en esa unidad

Antes, al usar Set-Location o cd para volver a un PSDrive enviaba a los usuarios a la ubicación predeterminada para esa unidad. Ahora se envía a los usuarios al último directorio de trabajo actual conocido de esa sesión.

cd - vuelve al directorio anterior

C:\Windows\System32> cd C:\
C:\> cd -
C:\Windows\System32>

O en Linux:

PS /etc> cd /usr/bin
PS /usr/bin> cd -
PS /etc>

Además, cd y cd -- cambian a $HOME.

Update-Help como no administrador

Por petición popular, Update-Help ya no debe ejecutarse como administrador. Update-Help ahora tiene como valor predeterminado guardar la Ayuda en una carpeta con ámbito de usuario.

Where-Object -Not

Con la incorporación del parámetro -Not a Where-Object, puede filtrar un objeto en la canalización para la no existencia de una propiedad o un valor de propiedad nula o vacía.

Por ejemplo, este comando devuelve todos los servicios que no tienen los servicios dependientes definidos:

Get-Service | Where-Object -Not DependentServices

Cambios en los cmdlets web

La API de .NET subyacente de los cmdlets web se ha cambiado a System.Net.Http.HttpClient. Este cambio ofrece muchas ventajas. Sin embargo, este cambio y una falta de interoperabilidad con Internet Explorer han dado lugar a varios cambios importantes en Invoke-WebRequest y Invoke-RestMethod.

  • Invoke-WebRequest ahora solo admite un análisis básico de HTML. Invoke-WebRequest siempre devuelve un objeto BasicHtmlWebResponseObject. Las propiedades ParsedHtml y Forms se han quitado.
  • Los valores BasicHtmlWebResponseObject.Headers ahora son String[] en lugar de String.
  • BasicHtmlWebResponseObject.BaseResponse ahora es un objeto System.Net.Http.HttpResponseMessage.
  • La propiedad Response de excepciones de cmdlets web ahora es un objeto System.Net.Http.HttpResponseMessage.
  • El análisis estricto del encabezado RFC ahora es el valor predeterminado de los parámetros -Headers y -UserAgent. Esto se puede omitir con -SkipHeaderValidation.
  • Los esquemas de URI file:// y ftp:// ya no se admiten.
  • La configuración System.Net.ServicePointManager ya no se admite.
  • Actualmente no hay ninguna autenticación disponible en macOS basada en certificado.
  • El uso de -Credential sobre un URI http:// dará lugar a un error. Use un URI https:// o proporcione el parámetro -AllowUnencryptedAuthentication para suprimir el error.
  • -MaximumRedirection ahora genera un error de terminación cuando los intentos de redirección superan el límite proporcionado en lugar de devolver los resultados de la última redirección.
  • En PowerShell 6.2, se ha realizado un cambio para usar de forma predeterminada la codificación UTF-8 en las respuestas JSON. Cuando no se proporciona un juego de caracteres para una respuesta JSON, la codificación predeterminada debe ser UTF-8 según la norma RFC 8259.
  • Codificación predeterminada establecida en UTF-8 para respuestas application-json
  • Incorporación del parámetro -SkipHeaderValidation para permitir encabezados Content-Type que no son compatibles con estándares
  • Incorporación del parámetro -Form para admitir compatibilidad con multipart/form-data simplificada
  • Control compatible que distingue entre mayúsculas y minúsculas de claves de relación
  • Incorporación del parámetro -Resume para cmdlets web

Invoke-RestMethod devuelve información útil cuando no se devuelven datos

Cuando una API devolvía simplemente null, Invoke-RestMethod lo serializaba como la cadena "null" en lugar de $null. Este cambio corrige la lógica en Invoke-RestMethod para serializar correctamente un valor único válido JSON null literal como $null.

Los cmdlets web avisan cada vez que -Credential se envía a través de conexiones sin cifrar

Al usar HTTP, el contenido y las contraseñas se envían como texto no cifrado. Este cambio consiste en no permitir esto de forma predeterminada y devolver un error si las credenciales se pasan de forma segura. Los usuarios pueden omitir esto con el conmutador -AllowUnencryptedAuthentication.

Se ha creado el parámetro -OutFile en cmdlets web para que funcione como -LiteralPath.

A partir de PowerShell 7.1, el parámetro OutFile de los cmdlets web funciona como LiteralPath y no procesa caracteres comodín.

Cambios de API

Eliminación de la clase AddTypeCommandBase

La clase AddTypeCommandBase se quitó de Add-Type para mejorar el rendimiento. El cmdlet Add-Type es el único que usa esta clase, por lo que no debe afectar a los usuarios.

Se quitó VisualBasic como lenguaje compatible en Add-Type

Antes, se podía compilar código de Visual Basic mediante el cmdlet Add-Type. Visual Basic se usó rara vez con Add-Type. Hemos quitado esta característica para reducir el tamaño de PowerShell.

Eliminación de la compatibilidad con RunspaceConfiguration

Anteriormente, al crear un espacio de ejecución de PowerShell mediante programación con la API, podía usar el elemento RunspaceConfiguration heredado o las clases InitialSessionState más recientes. Este cambio quitó la compatibilidad con RunspaceConfiguration y solo admite InitialSessionState.

CommandInvocationIntrinsics.InvokeScript enlaza argumentos a $input en lugar de $args

Una posición incorrecta de un parámetro dio como resultado que los argumentos se pasaran como entrada en lugar de como argumentos.

Eliminación de las propiedades ClrVersion y BuildVersion de $PSVersionTable

La propiedad ClrVersion de $PSVersionTable no es útil con CoreCLR. Los usuarios finales no deben usar ese valor para determinar la compatibilidad.

La propiedad BuildVersion estaba vinculada a la versión de compilación de Windows, que no está disponible en plataformas no Windows. Use la propiedad GitCommitId para recuperar la versión de compilación exacta de PowerShell.

Implementación de análisis de escape Unicode

`u#### o `u{####} se convierte en el carácter Unicode correspondiente. Para generar un elemento `u literal, evite la tilde aguda: ``u.

Problema de enlace de parámetros con ValueFromRemainingArguments en funciones de PS

ValueFromRemainingArguments ahora devuelve los valores como una matriz en lugar de un solo valor que en sí mismo es una matriz.

Se limpiaron los usos de CommandTypes.Workflow y WorkflowInfoCleaned

Limpie el código relacionado con los usos de CommandTypes.Workflow y WorkflowInfo en System.Management.Automation.

Estos cambios importantes menores afectan principalmente al código del proveedor de ayuda.

  • Cambie los constructores públicos de WorkflowInfo a internal. Ya no se admite el flujo de trabajo, por lo que tiene sentido no permitir que los usuarios creen instancias Workflow.
  • Quite el tipo System.Management.Automation.DebugSource, ya que solo se usa para la depuración del flujo de trabajo.
  • Quite la sobrecarga de SetParent de la clase abstracta Debugger, que solo se usa para la depuración del flujo de trabajo.
  • Quite la misma sobrecarga de SetParent de la clase derivada RemotingJobDebugger.

No ajuste del resultado devuelto en PSObject al convertir ScriptBlock en un delegado

Cuando un valor ScriptBlock se convierte en un tipo delegado que se debe usar en un contexto de C#, al ajustar el resultado en un valor PSObject se producen problemas innecesarios:

  • Cuando el valor se convierte en el tipo devuelto delegado, el valor PSObject, básicamente, se desajusta. Por lo tanto, no se necesita PSObject.
  • Cuando el tipo devuelto delegado es object, se ajusta en un valor PSObject, lo que dificulta trabajar en un código de C#.

Después de este cambio, el objeto devuelto es el subyacente.

Compatibilidad con la comunicación remota

La comunicación remota de PowerShell (PSRP) mediante WinRM en plataformas Unix requiere NTLM/Negotiate o autenticación básica a través de HTTPS. PSRP en macOS solo admite autenticación básica a través de HTTPS. La autenticación basada en Kerberos no se admite en las plataformas no Windows.

PowerShell también admite la comunicación remota de PowerShell (PSRP) a través de SSH en todas las plataformas (Windows, macOS y Linux). Para obtener más información, vea Comunicación remota de PowerShell a través de SSH.

PowerShell Direct para contenedores intenta usar primero pwsh

PowerShell Direct es una característica de PowerShell e Hyper-V que permite conectarse a una máquina virtual de Hyper-V o un contenedor sin conectividad de red u otros servicios de administración remota.

Antes, PowerShell Direct se conectaba mediante la instancia de Windows PowerShell integrada en el contenedor. Ahora, PowerShell Direct intenta primero conectarse usando cualquier pwsh.exe disponible en la variable de entorno PATH. Si pwsh.exe no está disponible, PowerShell Direct recurre a usar powershell.exe.

Enable-PSRemoting ahora crea puntos de conexión de comunicación remota independientes para versiones preliminares

Enable-PSRemoting ahora crea dos configuraciones de sesión de comunicación remota:

  • Una para la versión principal de PowerShell. Por ejemplo, PowerShell.6. Este punto de conexión en el que se puede confiar en todas las actualizaciones de versiones secundarias como la configuración de sesión de PowerShell 6 "para todo el sistema".
  • Una configuración de sesión específica de la versión, por ejemplo: PowerShell.6.1.0

Este comportamiento es útil si quiere tener varias versiones de PowerShell 6 instaladas y accesibles en la misma máquina.

Además, las versiones preliminares de PowerShell ahora obtienen sus propias configuraciones de sesión de comunicación remota después de ejecutar el cmdlet Enable-PSRemoting:

C:\WINDOWS\system32> Enable-PSRemoting

El resultado puede ser diferente si no ha configurado WinRM antes.

WinRM is already set up to receive requests on this computer.
WinRM is already set up for remote management on this computer.

Después puede ver las configuraciones de sesión de PowerShell independientes para la versión preliminar y compilaciones estables de PowerShell 6, para cada versión específica.

Get-PSSessionConfiguration
Name          : PowerShell.6.2-preview.1
PSVersion     : 6.2
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : PowerShell.6-preview
PSVersion     : 6.2
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : powershell.6
PSVersion     : 6.1
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : powershell.6.1.0
PSVersion     : 6.1
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Sintaxis user@host:port para SSH

Los clientes SSH suelen admitir una cadena de conexión en el formato user@host:port. Al agregar SSH como protocolo para la comunicación remota de PowerShell, se ha agregado compatibilidad con este formato de cadena de conexión:

Enter-PSSession -HostName fooUser@ssh.contoso.com:2222

Solo se puede deshabilitar la telemetría con una variable de entorno

PowerShell envía datos de telemetría básicos a Microsoft cuando se inicia. Los datos incluyen el nombre del sistema operativo, la versión del sistema operativo y la versión de PowerShell. Estos datos nos permiten comprender mejor los entornos donde se usa PowerShell y nos permite dar prioridad a nuevas características y correcciones.

Para dejar de participar en esta telemetría, establezca la variable de entorno POWERSHELL_TELEMETRY_OPTOUT en true, yes o 1. Ya no se admite la eliminación del archivo DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY para deshabilitar la telemetría.