How can I run PowerShell with the .NET 4 runtime?

前端 未结 11 2141
走了就别回头了
走了就别回头了 2020-11-22 07:38

I am updating a PowerShell script that manages some .NET assemblies. The script was written for assemblies built against .NET 2 (the same version of the framework that Power

相关标签:
11条回答
  • 2020-11-22 07:51

    Actually, you can get PowerShell to run using .NET 4 without affecting other .NET applications. I needed to do so to use the new HttpWebRequest "Host" property, however changing the "OnlyUseLatestCLR" broke Fiddler as that could not be used under .NET 4.

    The developers of PowerShell obviously foresaw this happening, and they added a registry key to specify what version of the Framework it should use. One slight issue is that you need to take ownership of the registry key before changing it, as even administrators do not have access.

    • HKLM:\Software\Microsoft\Powershell\1\PowerShellEngine\RuntimeVersion (64 bit and 32 bit)
    • HKLM:\Software\Wow6432Node\Microsoft\Powershell\1\PowerShellEngine\RuntimeVersion (32 bit on 64 bit machine)

    Change the value of that key to the required version. Keep in mind though that some snapins may no longer load unless they are .NET 4 compatible (WASP is the only one I have had trouble with, but I don't really use it anyway). VMWare, SQL Server 2008, PSCX, Active Directory (Microsoft and Quest Software) and SCOM all work fine.

    0 讨论(0)
  • 2020-11-22 08:00

    Here is the contents of the configuration file I used to support both .NET 2.0 and .NET 4 assemblies:

    <?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>
    

    Also, here’s a simplified version of the PowerShell 1.0 compatible code I used to execute our scripts from the passed in command line arguments:

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

    In addition to the basic error handling shown above, we also inject a trap statement into the script to display additional diagnostic information (similar to Jeffrey Snover's Resolve-Error function).

    0 讨论(0)
  • 2020-11-22 08:01

    PowerShell (the engine) runs fine under .NET 4.0. PowerShell (the console host and the ISE) do not, simply because they were compiled against older versions of .NET. There's a registry setting that will change the .NET framework loaded systemwide, which will in turn allow PowerShell to use .NET 4.0 classes:

    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
    

    To update just the ISE to use .NET 4.0, you can change the configuration ($psHome\powershell_ise.exe.config) file to have a chunk like this:

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

    You can build .NET 4.0 applications that call PowerShell using the PowerShell API (System.Management.Automation.PowerShell) just fine, but these steps will help get the in-the-box PowerShell hosts to work under .NET 4.0.


    Remove the registry keys when you don't need them any more. These are machine-wide keys and forcibly migrate ALL applications to .NET 4.0, even applications using .net 2 and .net 3.5


    0 讨论(0)
  • 2020-11-22 08:01

    The best solution I have found is in the blog post Using Newer Version(s) of .NET with PowerShell. This allows powershell.exe to run with .NET 4 assemblies.

    Simply modify (or create) $pshome\powershell.exe.config so that it contains the following:

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

    Additional, quick setup notes:

    Locations and files are somewhat platform dependent; however will give you an inline gist of how to make the solution work for you.

    • You can find PowerShell's location on your computer by executing cd $pshome in the Powershell window (doesn't work from DOS prompt).
      • Path will be something like (example) C:\Windows\System32\WindowsPowerShell\v1.0\
    • The filename to put configuration in is: powershell.exe.config if your PowerShell.exe is being executed (create the config file if need be).
      • If PowerShellISE.Exe is running then you need to create its companion config file as PowerShellISE.Exe.config
    0 讨论(0)
  • 2020-11-22 08:02

    If you're still stuck on PowerShell v1.0 or v2.0, here is my variation on Jason Stangroome's excellent answer.

    Create a powershell4.cmd somewhere on your path with the following contents:

    @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=
    

    This will allow you to launch an instance of the powershell console running under .NET 4.0.

    You can see the difference on my system where I have PowerShell 2.0 by examining the output of the following two commands run from 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
    
    0 讨论(0)
  • 2020-11-22 08:02

    The other answers are from before 2012, and they focus on "hacking" PowerShell 1.0 or PowerShell 2.0 into targeting newer versions of the .NET Framework and Common Language Runtime (CLR).

    However, as has been written in many comments, since 2012 (when PowerShell 3.0 came) a much better solution is to install the newest version of PowerShell. It will automatically target CLR v4.0.30319. This means .NET 4.0, 4.5, 4.5.1, 4.5.2, or 4.6 (expected in 2015) since all of these versions are in-place replacements of each other. Use $PSVersionTable or see the Determine installed PowerShell version thread if you are unsure of your PowerShell version.

    At the time of writing, the newest version of PowerShell is 4.0, and it can be downloaded with the Windows Management Framework (Google search link).

    0 讨论(0)
提交回复
热议问题