如何使用.NET 4运行时运行PowerShell?

时间:2010-01-19 15:44:06

标签: .net powershell .net-4.0

我正在更新管理某些.NET程序集的PowerShell脚本。该脚本是针对针对.NET 2构建的程序集(与PowerShell运行的框架的相同版本)编写的,但现在需要使用.NET 4程序集以及.NET 2程序集。

由于.NET 4支持运行针对旧版本框架构建的应用程序,因此最简单的解决方案是在需要针对.NET 4程序集运行时,使用.NET 4运行时启动PowerShell。

如何使用.NET 4运行时运行PowerShell?

11 个答案:

答案 0 :(得分:233)

我找到的最佳解决方案是在博客文章 Using Newer Version(s) of .NET with PowerShell 中。这允许powershell.exe与.NET 4程序集一起运行。

只需修改(或创建)$pshome\powershell.exe.config,使其包含以下内容:

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

其他快速设置说明:

位置和文件在某种程度上取决于平台;但是,它将为您提供如何使解决方案适合您的内联要点。

  • 您可以通过在Powershell窗口中执行cd $pshome 在计算机上找到PowerShell的位置(在DOS提示符下无效)。
    • 路径类似于(示例)C:\Windows\System32\WindowsPowerShell\v1.0\
  • 如果正在执行powershell.exe.config,则将配置放入的文件名为:PowerShell.exe(如果需要,创建配置文件)。
    • 如果PowerShellISE.Exe正在运行,那么您需要将其随播配置文件创建为PowerShellISE.Exe.config

答案 1 :(得分:145)

PowerShell(引擎)在.NET 4.0下运行良好。 PowerShell(控制台主机和ISE)没有,因为它们是针对旧版本的.NET编译的。有一个注册表设置将更改加载系统范围的.NET框架,这将允许PowerShell使用.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

要仅更新ISE以使用.NET 4.0,您可以更改配置($ psHome \ powershell_ise.exe.config)文件以获得这样的块:

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

您可以构建使用PowerShell API(System.Management.Automation.PowerShell)调用PowerShell的.NET 4.0应用程序,但这些步骤将有助于使用现成的PowerShell主机在.NET 4.0下运行。


不再需要时删除注册表项。这些是机器范围的密钥,并强制将所有应用程序迁移到.NET 4.0,甚至是使用.net 2和.net 3.5的应用程序


答案 2 :(得分:28)

使用注册表项方法时请非常小心。这些是计算机范围的密钥,并且可以将所有应用程序迁移到.NET 4.0。

如果不经过迁移,许多产品都无法正常工作,这是一种测试辅助工具而非生产质量机制。不应自动迁移Visual Studio 2008和2010,MSBuild,turbotax和许多网站SharePoint等。

如果您需要使用PowerShell 4.0,这应该在每个应用程序的基础上使用配置文件完成,您应该与PowerShell团队一起查看精确的建议。这可能会破坏一些现有的PowerShell命令。

答案 3 :(得分:26)

如果您只需要在.NET 4中执行单个命令,脚本块或脚本文件,请尝试使用Activation Configuration Files from .NET 4仅使用CLR的第4版启动单个PowerShell实例。

完整详情:

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

示例PowerShell模块:

https://gist.github.com/882528

答案 4 :(得分:18)

如果你仍然坚持使用PowerShell v1.0或v2.0,这是我对Jason Stangroome的优秀答案的变化。

使用以下内容在路径的某处创建powershell4.cmd

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

这将允许您启动在.NET 4.0下运行的powershell控制台的实例。

通过检查从cmd运行的以下两个命令的输出,您可以在我的系统中看到我有PowerShell 2.0的区别。

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

答案 5 :(得分:16)

以下是我用来支持.NET 2.0和.NET 4程序集的配置文件的内容:

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

此外,这是我用来从传入的命令行参数执行脚本的PowerShell 1.0兼容代码的简化版本:

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

除了上面显示的基本错误处理之外,我们还在脚本中注入trap语句以显示其他诊断信息(类似于Jeffrey Snover的Resolve-Error函数)。

答案 6 :(得分:10)

其他答案来自2012年之前,他们专注于&#34;黑客攻击&#34; PowerShell 1.0或PowerShell 2.0用于定位较新版本的.NET Framework和公共语言运行时(CLR)。

然而,正如许多评论中所写,自2012年(当PowerShell 3.0推出时),更好的解决方案是 安装最新版本的PowerShell 。它会自动定位CLR v4.0.30319。这意味着.NET 4.0,4.5,4.5.1,4.5.2或4.6(预计在2015年),因为所有这些版本都是相互替换的。如果您不确定PowerShell版本,请使用$PSVersionTable或查看Determine installed PowerShell version thread

在撰写本文时,最新版本的PowerShell是4.0,它可以是downloaded with the Windows Management Framework (Google search link)

答案 7 :(得分:8)

实际上,您可以使用.NET 4 运行PowerShell而不会影响其他.NET应用程序。我需要这样做才能使用新的HttpWebRequest“Host”属性,但是更改“OnlyUseLatestCLR”打破了Fiddler,因为它无法在.NET 4下使用。

PowerShell的开发人员显然预见到了这种情况,他们添加了一个注册表项来指定它应该使用的Framework版本。一个小问题是您需要在更改之前获取注册表项的所有权,因为即使管理员也没有权限。

  • HKLM:\ Software \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion(64位和32位)
  • HKLM:\ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion(64位机器上32位)

将该密钥的值更改为所需的版本。请记住,虽然有些snapins可能不再加载,除非它们是.NET 4兼容的(WASP是唯一一个我遇到过麻烦的,但我还是没有真正使用它)。 VMWareSQL Server 2008,PSCX,Active Directory(Microsoft和Quest Software)和SCOM都运行良好。

答案 8 :(得分:7)

如果您不想修改注册表或app.config文件,另一种方法是创建一个简单的.NET 4控制台应用程序,模仿PowerShell.exe的功能并托管PowerShell ConsoleShell。

请参阅Option 2 – Hosting Windows PowerShell yourself

首先,添加对 System.Management.Automation Microsoft.PowerShell.ConsoleHost 程序集的引用,这些程序集可在%programfiles%\ Reference Assemblies下找到\微软\ WindowsPowerShell \ V1.0

然后使用以下代码:

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

答案 9 :(得分:6)

正如另一个选项一样,最新的PoshConsole版本包含针对.NET 4 RC的二进制文件(在RTM版本中可以正常工作),无需任何配置。

答案 10 :(得分:1)

仅在将COMPLUS_version环境变量设置为v4.0.30319的情况下运行powershell.exe。 例如,来自cmd.exe或.bat文件:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1