2010-01-19 14 views
219

Sto aggiornando uno script PowerShell che gestisce alcuni assembly .NET. Lo script è stato scritto per gli assembly creati su .NET 2 (la stessa versione del framework con cui PowerShell viene eseguito), ma ora ha bisogno di lavorare con .NET 4 assembly e con .NET 2 assembly.Come posso eseguire PowerShell con .NET 4 runtime?

Poiché .NET 4 supporta le applicazioni in esecuzione basate su versioni precedenti del framework, sembra che la soluzione più semplice sia quella di avviare PowerShell con il runtime .NET 4 quando è necessario eseguirlo su .NET 4 assembly.

Come posso eseguire PowerShell con .NET 4 runtime?

+0

duplicati di http://stackoverflow.com/questions/1940983/loading-net-4-0-beta2-assembly-in-powershell-2-0. –

+6

In questi giorni la soluzione più semplice sarebbe installare il CTP Powershell 3.0 che utilizza CLRVersion: 4.0.30319.1. –

+0

** Chiunque sia ancora bloccato con PowerShell 2, [vedere la risposta di Tim Lewis] (https://stackoverflow.com/a/31279372/1958726) ** per una soluzione localizzata che non richiede la modifica di alcuna configurazione a livello di macchina. –

risposta

138

PowerShell (il motore) funziona correttamente con .NET 4.0. PowerShell (l'host della console e lo ISE) non lo fanno, semplicemente perché sono stati compilati rispetto alle versioni precedenti di .NET. C'è un'impostazione di Registro di sistema che cambiare il framework .NET caricato systemwide, che a sua volta permetterà PowerShell utilizzare .NET 4.0 classi:

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 

Per aggiornare solo l'ISE di utilizzare NET 4.0, è possibile modificare la configurazione ($ PSHome \ powershell_ise.exe.config) file per avere un pezzo come questo:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0.30319" /> 
    </startup> 
</configuration> 

È possibile creare applicazioni .NET 4.0 che chiamano PowerShell utilizzando l'API PowerShell (System.Management.Automation.PowerShell) bene, ma questi passaggi aiuteranno a far funzionare gli host PowerShell in-the-box sotto .NET 4 .0.


Rimuovere le chiavi di registro quando non servono più. Queste sono le chiavi a livello di computer e forzatamente migrare tutte le applicazioni .NET 4.0, anche le applicazioni che utilizzano Net 2 e .NET 3,5


+9

Giusto per essere chiari, powershell.exe (l'app host della console) è di per sé un'applicazione nativa, non gestita. –

+0

L'impostazione del registro funziona bene per ora, anche se penso che cambiando il nostro launcher da uno script '.bat' che chiama' powershell.exe' a una semplice app utilizzando 'System.Management.Automation.PowerShell' sarà una soluzione migliore a lungo termine. –

+0

Se si desidera che ISE 32 e 64 bit siano entrambi aggiornati per supportare 4.0, aggiungere il file .config precedente a "C: \ windows \ System32 \ WindowsPowerShell \ v1.0" e "C: \ Windows \ SysWOW64 \ WindowsPowerShell \ v1" .0 'cartelle. Inoltre, tieni presente che la risposta di "Emperor XLII" di seguito presenta un file di configurazione migliore da utilizzare. – scobi

16

Ecco il contenuto del file di configurazione che ho usato per supportare sia .NET 2.0 e .NET 4 gruppi:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <!-- http://msdn.microsoft.com/en-us/library/w4atty68.aspx --> 
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
    <supportedRuntime version="v4.0" /> 
    <supportedRuntime version="v2.0.50727" /> 
    </startup> 
</configuration> 

Inoltre, ecco una versione semplificata del codice compatibile PowerShell 1.0 che ho usato per eseguire i nostri script dal passato in argomenti della riga di comando:

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<PSObject> 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; 
    } 
    } 
} 

Oltre alla gestione degli errori di base mostrata sopra, iniettiamo anche un'istruzione trap nello script per visualizzare ulteriori informazioni diagnostiche (simile alla funzione Resolve-Error di Jeffrey Snover).

6

Proprio come un'altra opzione, l'ultima versione di PoshConsole include i binari indirizzati a .NET 4 RC (che funzionano bene contro la versione RTM) senza alcuna configurazione.

28

Si prega di prestare molta attenzione all'utilizzo dell'approccio con chiave di registro. Queste sono chiavi a livello di macchina e migrano forzatamente TUTTE le applicazioni a .NET 4.0.

Molti prodotti non funzionano se migrati forzatamente e questo è un ausilio di prova e non un meccanismo di qualità di produzione. Visual Studio 2008 e 2010, MSBuild, turbotassico e una serie di siti Web, SharePoint e così via non devono essere automatizzati.

Se è necessario utilizzare PowerShell con 4.0, questo dovrebbe essere fatto su una base per applicazione con un file di configurazione, si dovrebbe verificare con il team PowerShell sulla raccomandazione precisa. È probabile che questo interrompa alcuni comandi PowerShell esistenti.

+0

Punto molto buono sull'utilizzo della chiave di registro. Fortunatamente, l'applicazione di avvio con il file di configurazione funziona perfettamente. I nostri script usano principalmente i comandi del file system e le chiamate .NET dirette, e non abbiamo notato alcun problema con i comandi non funzionanti. Poiché .NET 4 è ampiamente compatibile con le versioni precedenti di .NET 2.0, non penserei che ci sarebbero molti comandi non funzionanti (anche se non fa mai male essere precauzioni :). –

8

In realtà, è possibile ottenere PowerShell per eseguire utilizzando .NET 4 senza influenzare altre applicazioni .NET. Avevo bisogno di farlo per utilizzare la nuova proprietà "Host" di HttpWebRequest, tuttavia la modifica di "OnlyUseLatestCLR" interrompeva Fiddler in quanto non poteva essere utilizzata su .NET 4.

Gli sviluppatori di PowerShell prevedevano ovviamente che ciò accada, e hanno aggiunto una chiave di registro per specificare quale versione del Framework deve utilizzare. Un piccolo problema è che è necessario assumere la proprietà della chiave di registro prima di cambiarla, poiché anche gli amministratori non hanno accesso.

  • HKLM: \ Software \ Microsoft \ PowerShell \ 1 \ PowerShellEngine \ runtimeVersion (64 bit e 32 bit)
  • HKLM: \ Software \ Wow6432Node \ Microsoft \ PowerShell \ 1 \ PowerShellEngine \ runtimeVersion (32 bit su Macchina a 64 bit)

Modificare il valore di tale chiave nella versione richiesta. Tieni presente che alcuni snap-in potrebbero non caricarsi più a meno che non siano compatibili con .NET 4. (WASP è l'unico con cui ho avuto problemi, ma non lo uso comunque). VMWare, SQL Server 2008, PSCX, Active Directory (Microsoft e Quest Software) e SCOM funzionano correttamente.

+0

+1 Questa è un'alternativa molto importante (e migliore) rispetto all'altra voce di registro che interesserà tutte le applicazioni .net, ma questa soluzione riguarda solo PowerShell. –

+0

Dopo l'implementazione di "OnlyUseLatestCLR", il mio Fiddler si è rotto e alcuni script di PowerShell non eseguivano più runnign a causa dell'impossibilità di contattare determinati server. Ho modificato manualmente i valori su 0 nel regedt32, e ora tutto funziona nuovamente. Grazie! – Neville

+0

Cosa sono WASP, PSCX e SCOM (in questo contesto)? –

7

Se non si desidera modificare i file di registro o app.config, in alternativa è possibile creare una semplice app per console .NET 4 che riproduca ciò che PowerShell.exe esegue e ospita PowerShell ConsoleShell.

Vedi Option 2 – Hosting Windows PowerShell yourself

In primo luogo, aggiungere un riferimento al System.Management.Automation e Microsoft.PowerShell.ConsoleHost assemblee che si trova sotto % programfiles% \ Reference Assemblies \ Microsoft \ WindowsPowerShell \ v1.0

Quindi utilizzare il seguente codice:

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 
      ); 
     } 
    } 
} 
225

La soluzione migliore che ho trovato è nel post del blog Using Newer Version(s) of .NET with PowerShell. Ciò consente a powershell.exe di funzionare con .NET 4 assembly.

sufficiente modificare (o creare) $pshome\powershell.exe.config in modo che contenga il seguente:

<?xml version="1.0"?> 
<configuration> 
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
     <supportedRuntime version="v4.0.30319"/> 
     <supportedRuntime version="v2.0.50727"/> 
    </startup> 
</configuration> 

supplementari, rapide note di impostazione:

Sedi e file sono in qualche modo dipendente dalla piattaforma; tuttavia ti fornirà una sintesi di come far funzionare la soluzione per te.

  • È possibile trovare la posizione di PowerShell sul computer eseguendo cd $pshomenella finestra PowerShell (non funziona da prompt di DOS).
    • percorso sarà qualcosa di simile (ad esempio) C:\Windows\System32\WindowsPowerShell\v1.0\
  • Il nome del file di configurazione per mettere in è: powershell.exe.config se il PowerShell.exe che viene eseguito (creare il file di configurazione, se necessario).
    • Se PowerShellISE.Exe è in esecuzione, allora avete bisogno di creare il file di configurazione compagna come PowerShellISE.Exe.config
+20

Decisamente il modo corretto per farlo. Ciò altera solo il comportamento di Powershell, non tutte le altre app .NET sulla tua macchina ... –

+4

Funziona bene ma riguarda tutto il tuo PowerShell. Se vuoi solo alcune delle funzionalità, fai una copia della cartella di PowerShell e modifica il file lì. – Matt

+7

Ho aggiunto un file come indicato sopra. Tuttavia, non riesco a eseguire PowerShell con quel file presente. Viene visualizzato l'errore "Il volume di un file è stato modificato esternamente in modo che il file aperto non sia più valido."Qualsiasi idea? – JoshL

10

Le altre risposte sono da prima del 2012, e si concentrano su "hacking" PowerShell 1.0 o PowerShell 2.0 in targeting per le versioni più recenti di .NET Framework e Common Language Runtime (CLR).

Tuttavia, come è stato scritto in molti commenti, dal 2012 (quando PowerShell 3.0 è venuto) una soluzione molto migliore è quella di installare l'ultima versione di PowerShell. Verrà automaticamente indirizzato a CLR v4.0.30319. Questo significa .NET 4.0, 4.5, 4.5.1, 4.5.2 o 4.6 (previsto per il 2015) poiché tutte queste versioni sono sostituzioni locali. Utilizzare $PSVersionTable o vedere lo Determine installed PowerShell version thread se non si è sicuri della propria versione di PowerShell.

Al momento della scrittura, la versione più recente di PowerShell è 4.0 e può essere downloaded with the Windows Management Framework (Google search link).

+1

I requisiti di sistema per Windows Management Framework 4.0 (sono simili per 3.0) sono: Windows 7, Windows 7, Windows Server 2008 R2, Windows Server 2012. –

15

Se sei ancora bloccato su PowerShell v1.0 o v2.0, ecco la mia variazione sull'eccellente risposta di Jason Stangroome.

Creare un powershell4.cmd da qualche parte sul vostro percorso con il seguente contenuto:

@echo off 
:: http://stackoverflow.com/questions/7308586/using-batch-echo-with-special-characters 
if exist %~dp0powershell.exe.activation_config goto :run 
echo.^<?xml version="1.0" encoding="utf-8" ?^>     > %~dp0powershell.exe.activation_config 
echo.^<configuration^>          >> %~dp0powershell.exe.activation_config 
echo. ^<startup useLegacyV2RuntimeActivationPolicy="true"^> >> %~dp0powershell.exe.activation_config 
echo. ^<supportedRuntime version="v4.0"/^>     >> %~dp0powershell.exe.activation_config 
echo. ^</startup^>           >> %~dp0powershell.exe.activation_config 
echo.^</configuration^>          >> %~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= 

questo vi permetterà di lanciare un'istanza della console PowerShell in esecuzione in .NET 4.0.

È possibile vedere la differenza sul mio sistema in cui ho PowerShell 2.0 esaminando l'output dei seguenti due comandi eseguiti da 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 
+2

Questa è di gran lunga la migliore risposta poiché è molto localizzata cambia e non esegue alcuna modifica persistente al sistema. Roba buona! – Sebastian

+0

fantastico! Potete aiutare qui? http://stackoverflow.com/questions/39801315/how-to-chain-commands-at-a-special-powershell-4-command-prompt –

+0

@TimLewis, è possibile inviare più istruzioni allo stesso ps4.cmd esempio? –

Problemi correlati