views:

2451

answers:

6

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 PowerShell runs with), but now needs to work with .NET 4 assemblies as well as .NET 2 assemblies.

Since .NET 4 supports running applications built against older versions of the framework, it seems like the simplest solution is to launch PowerShell with the .NET 4 runtime when I need to run it against .NET 4 assemblies.

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

+15  A: 

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 config ($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.20826" />
    </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

Hope this helps

Start-Automating
Thanks for all the suggestions! Will look into them soon.
Emperor XLII
Just to be clear, powershell.exe (the console host app) itself is a native application - not managed.
Keith Hill
BTW if you are on VS 2010 Beta2 the version number is v4.0.21006. To bad PowerShell.exe isn't managed, then you could use the same app config trick. :-)
Keith Hill
The registry setting is working fine for now, though I think changing our launcher from a `.bat` script calling `powershell.exe` to a simple app using `System.Management.Automation.PowerShell` will be a better long-term solution.
Emperor XLII
If you want ISE 32 and 64 bit both updated to support 4.0, add the above .config file to both the 'C:\windows\System32\WindowsPowerShell\v1.0' and 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0' folders. Also, note that the answer by 'Emperor XLII' below has a better config file to use.
Scott Bilas
+4  A: 

For those that are interested, here is the contents of the config 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 (additional error handling elided for brevity):

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;
    }
  }
}
Emperor XLII
+3  A: 

Just as another option, the latest PoshConsole release includes binaries targeted to .Net 4 RC (which work fine against the RTM release) without any configuration.

Jaykul
The link should be: http://poshconsole.codeplex.com/
Kevin Driedger
+6  A: 

Please be VERY careful with using the registry key approach. These are machine-wide keys and forcibily migrate ALL applications to .Net 4.0. Many products do not work if forcibily migrated and this is a testing aid and not a production quality mechanism. Visual Studio 2008 and 2010, msbuild, turbotax, and a host of websites, sharepoint so on should not be automigrated.

If you need to use Powershell with 4.0, this should be done on a per-application basis with a config file, you should check with powershell team on the precise recommendation. This is likely to break some existing powershell commands.

Madhu Talluri
Very good point about using the registry key. Happily, the launcher application with config file is working just fine. Our scripts primarily use file system commands and direct .NET calls, and we have not noticed any problems with broken commands. Since .NET 4 is largely backward compatible with .NET 2.0, I would not think it likely that there would be many broken commands (though it never hurts to be cautions :).
Emperor XLII
+3  A: 

NOTE that the Registry hack will cause very strange errors in Visual Studio when your have a target framework that is something that is not 4.0.

"(0,0): warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
Kevin Horvatin
+2  A: 

This is a reiteration of Kevin's warning. The strange errors he is talking about mean that any existing VS2008 project which targets an earlier version of the .Net Framework will not build. There is a discussion here which covers the symptoms and the Microsoft Connect bug report that contains the resolution which is to undo the registry changes in the "best answer" to this question.

This cost me a substantial amount of time and considerable frustration trying to build an existing application to implement a minor change. Sufficient time elapsed between making the registry changes to allow .Net4 for Powershell and applying the fix to a web app that it didn't occur to me to associate the registry change with the build issue.

I would strongly recommend changing the Powershell config file and not modifying the registry.

David Clarke