¿Cómo puedo ejecutar PowerShell con .NET 4 runtime?

Estoy actualizando un script de PowerShell que gestiona algunos ensamblados .NET. La secuencia de comandos se escribió para ensamblados construidos contra .NET 2 (la misma versión del marco con el que PowerShell se ejecuta), pero ahora necesita trabajar con ensamblados .NET 4 así como con ensamblados .NET 2.

Como .NET 4 es compatible con las aplicaciones en ejecución creadas con versiones anteriores del marco, parece que la solución más simple es ejecutar PowerShell con .NET 4 runtime cuando necesite ejecutarlo contra ensamblados .NET 4.

¿Cómo puedo ejecutar PowerShell con .NET 4 runtime?

PowerShell (el motor) funciona bien bajo .NET 4.0. PowerShell (el host de consola y el ISE ) no lo hacen, simplemente porque fueron comstackdos contra versiones anteriores de .NET. Hay una configuración de registro que cambiará .NET Framework cargado en todo el sistema , lo que a su vez permitirá a PowerShell utilizar las clases de .NET 4.0:

reg add hklm\software\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1 reg add hklm\software\wow6432node\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1 

Para actualizar solo el ISE para utilizar .NET 4.0, puede cambiar el archivo de configuración ($ psHome \ powershell_ise.exe.config) para tener un fragmento como este:

       

Puede construir aplicaciones .NET 4.0 que llamen a PowerShell utilizando la API de PowerShell (System.Management.Automation.PowerShell) bien, pero estos pasos ayudarán a que los hosts de PowerShell incorporados funcionen bajo .NET 4.0.


Elimine las claves de registro cuando ya no las necesite. Estas son claves para toda la máquina y migran forzosamente TODAS las aplicaciones a .NET 4.0, incluso las aplicaciones que usan .net 2 y .net 3.5


La mejor solución que he encontrado está en la publicación del blog Uso de versiones más recientes de .NET con PowerShell . Esto permite que powershell.exe se ejecute con ensamblados .NET 4.

Simplemente modifique (o cree) $pshome\powershell.exe.config para que contenga lo siguiente:

        

Notas adicionales de configuración rápida:

Las ubicaciones y los archivos son algo dependientes de la plataforma; sin embargo, le dará una idea en línea de cómo hacer que la solución funcione para usted.

  • Puede encontrar la ubicación de PowerShell en su computadora al ejecutar cd $pshome en la ventana de Powershell (no funciona desde el indicador de DOS).
    • La ruta será algo así como (ejemplo) C:\Windows\System32\WindowsPowerShell\v1.0\
  • El nombre de archivo para poner la configuración es: powershell.exe.config si se está ejecutando PowerShell.exe (cree el archivo de configuración si fuera necesario).
    • Si PowerShellISE.Exe está ejecutando, debe crear su archivo de configuración complementario como PowerShellISE.Exe.config

Tenga MUCHO cuidado con el uso del enfoque de clave de registro. Estas son las claves de toda la máquina y forcibily migrar TODAS las aplicaciones a .NET 4.0.

Muchos productos no funcionan si se migra forzosamente y esto es una prueba de ayuda y no un mecanismo de calidad de producción. Visual Studio 2008 y 2010, MSBuild , turbotax y una gran cantidad de sitios web, SharePoint , etc., no se deben automatizar.

Si necesita utilizar PowerShell con 4.0, esto debe hacerse por aplicación con un archivo de configuración, debe consultar con el equipo de PowerShell sobre la recomendación precisa. Es probable que rompa algunos comandos de PowerShell existentes.

Si solo necesita ejecutar un solo comando, bloque de script o archivo de script en .NET 4, intente utilizar los archivos de configuración de activación de .NET 4 para iniciar solo una instancia de PowerShell utilizando la versión 4 de la CLR.

Todos los detalles:

http://blog.codeassassin.com/2011/03/23/executing-individual-powershell-commands-using-net-4/

Un ejemplo de módulo de PowerShell:

https://gist.github.com/882528

Aquí está el contenido del archivo de configuración que utilicé para admitir los ensamblados .NET 2.0 y .NET 4:

         

Además, aquí hay una versión simplificada del código compatible con PowerShell 1.0 que utilicé para ejecutar nuestros scripts desde los argumentos de línea de comando pasados:

 class Program { static void Main( string[] args ) { Console.WriteLine( ".NET " + Environment.Version ); string script = "& " + string.Join( " ", args ); Console.WriteLine( script ); Console.WriteLine( ); // Simple host that sends output to System.Console PSHost host = new ConsoleHost( this ); Runspace runspace = RunspaceFactory.CreateRunspace( host ); Pipeline pipeline = runspace.CreatePipeline( ); pipeline.Commands.AddScript( script ); try { runspace.Open( ); IEnumerable output = pipeline.Invoke( ); runspace.Close( ); // ... } catch( RuntimeException ex ) { string psLine = ex.ErrorRecord.InvocationInfo.PositionMessage; Console.WriteLine( "error : {0}: {1}{2}", ex.GetType( ), ex.Message, psLine ); ExitCode = -1; } } } 

Además del manejo básico de errores que se muestra arriba, también inyectamos una statement de trap en la secuencia de comandos para mostrar información de diagnóstico adicional (similar a la función de resolución de errores de Jeffrey Snover).

Si todavía está atrapado en PowerShell v1.0 o v2.0, aquí está mi variación en la excelente respuesta de Jason Stangroome.

Cree un powershell4.cmd algún lugar de su ruta con los siguientes contenidos:

 @echo off :: http://stackoverflow.com/questions/7308586/using-batch-echo-with-special-characters if exist %~dp0powershell.exe.activation_config goto :run echo.^ > %~dp0powershell.exe.activation_config echo.^ >> %~dp0powershell.exe.activation_config echo. ^ >> %~dp0powershell.exe.activation_config echo. ^ >> %~dp0powershell.exe.activation_config echo. ^ >> %~dp0powershell.exe.activation_config echo.^ >> %~dp0powershell.exe.activation_config :run :: point COMPLUS_ApplicationMigrationRuntimeActivationConfigPath to the directory that this cmd file lives in :: and the directory contains a powershell.exe.activation_config file which matches the executable name powershell.exe set COMPLUS_ApplicationMigrationRuntimeActivationConfigPath=%~dp0 %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe %* set COMPLUS_ApplicationMigrationRuntimeActivationConfigPath= 

Esto le permitirá iniciar una instancia de la consola de powershell que se ejecuta bajo .NET 4.0.

Puede ver la diferencia en mi sistema donde tengo PowerShell 2.0 al examinar la salida de los siguientes dos comandos ejecutados desde cmd.

 C:\>powershell -ExecutionPolicy ByPass -Command $PSVersionTable Name Value ---- ----- CLRVersion 2.0.50727.5485 BuildVersion 6.1.7601.17514 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1 C:\>powershell4.cmd -ExecutionPolicy ByPass -Command $PSVersionTable Name Value ---- ----- PSVersion 2.0 PSCompatibleVersions {1.0, 2.0} BuildVersion 6.1.7601.17514 CLRVersion 4.0.30319.18408 WSManStackVersion 2.0 PSRemotingProtocolVersion 2.1 SerializationVersion 1.1.0.1 

Las otras respuestas son anteriores a 2012, y se centran en “piratear” PowerShell 1.0 o PowerShell 2.0 en la orientación de las versiones más recientes de .NET Framework y Common Language Runtime (CLR).

Sin embargo, como se ha escrito en muchos comentarios, desde 2012 (cuando apareció PowerShell 3.0), una solución mucho mejor es instalar la versión más nueva de PowerShell . Se dirigirá automáticamente a CLR v4.0.30319 . Esto significa .NET 4.0, 4.5, 4.5.1, 4.5.2 o 4.6 (esperado en 2015) ya que todas estas versiones son sustitutos in situ entre sí. Use $PSVersionTable o consulte el tema Determinación de la versión de PowerShell instalada si no está seguro de su versión de PowerShell.

En el momento de redactar este informe, la versión más nueva de PowerShell es 4.0 y se puede descargar con el Marco de gestión de Windows (enlace de búsqueda de Google) .

En realidad, puede hacer que PowerShell se ejecute usando .NET 4 sin afectar otras aplicaciones .NET. Necesitaba hacerlo para usar la nueva propiedad HttpWebRequest “Host”, sin embargo cambiar el “OnlyUseLatestCLR” rompió Fiddler ya que no se podía usar bajo .NET 4.

Los desarrolladores de PowerShell obviamente previeron que esto sucediera, y agregaron una clave de registro para especificar qué versión del Framework debería usar. Un pequeño problema es que debe apropiarse de la clave de registro antes de cambiarla, ya que incluso los administradores no tienen acceso.

  • HKLM: \ Software \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64 bit y 32 bit)
  • HKLM: \ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (máquina de 32 bits en 64 bits)

Cambie el valor de esa clave a la versión requerida. Sin embargo, tenga en cuenta que algunos snapins ya no se pueden cargar a menos que sean compatibles con .NET 4 (WASP es el único con el que he tenido problemas, pero en realidad no lo uso). VMWare , SQL Server 2008 , PSCX, Active Directory (Microsoft y Quest Software ) y SCOM funcionan bien.

Si no desea modificar los archivos de registro o app.config, una forma alternativa es crear una aplicación de consola simple .NET 4 que imita lo que hace PowerShell.exe y aloja PowerShell ConsoleShell.

Consulte la Opción 2: alojar Windows PowerShell usted mismo

Primero, agregue una referencia a los ensamblados System.Management.Automation y Microsoft.PowerShell.ConsoleHost que se pueden encontrar en % programfiles% \ Reference Assemblies \ Microsoft \ WindowsPowerShell \ v1.0

Luego usa el siguiente código:

 using System; using System.Management.Automation.Runspaces; using Microsoft.PowerShell; namespace PSHostCLRv4 { class Program { static int Main(string[] args) { var config = RunspaceConfiguration.Create(); return ConsoleShell.Start( config, "Windows PowerShell - Hosted on CLR v4\nCopyright (C) 2010 Microsoft Corporation. All rights reserved.", "", args ); } } } 

Al igual que otra opción, la última versión de PoshConsole incluye binarios dirigidos a .NET 4 RC (que funcionan bien contra la versión RTM) sin ninguna configuración.