ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

如今,最简单的解决方案是安装使用 CLRVersion:4.0.30319.1 的 Powershell 3.0 CTP。
任何人仍然坚持使用 PowerShell 2,see Tim Lewis's answer 以获得不需要编辑任何机器范围配置的本地化解决方案。
有关非系统范围的无文件解决方案,请参阅 this answer

M
Martin Prikryl

我发现的最佳解决方案是在博文中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\

路径将类似于(示例)C:\Windows\System32\WindowsPowerShell\v1.0\

放置配置的文件名是:powershell.exe.config 如果您的 PowerShell.exe 正在执行(如果需要,请创建配置文件)。如果 PowerShellISE.Exe 正在运行,那么您需要将其配套配置文件创建为 PowerShellISE.Exe.config

如果 PowerShellISE.Exe 正在运行,那么您需要将其配套配置文件创建为 PowerShellISE.Exe.config


绝对是正确的方法。这只会改变 Powershell 的行为,而不是您机器上的所有其他 .NET 应用程序......
这很好用,但会影响您的所有 PowerShell。如果您只想要一些功能,请复制 powershell 文件夹,然后在那里编辑文件。
如上所述,我添加了一个文件。但是,我无法再在该文件存在的情况下运行 PowerShell - 我收到错误消息“文件的卷已被外部更改,因此打开的文件不再有效。”有任何想法吗?
@JoshL - 在 64 位系统上,我发现 .exe.config 需要进入 SysWOW64\WindowsPowershell (32 位文件夹),即使您尝试运行 64 位 powershell。否则,您会收到“外部更改”错误。
powershell.exe.config 需要在两个地方.... C:\Windows\System32\WindowsPowerShell\v1.0\ 和 C:\Windows\SysWOW64\WindowsPowerShell\v1.0\
I
Iain

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 的应用程序


需要明确的是,powershell.exe(控制台主机应用程序)本身是一个本机应用程序 - 不受管理。
我从上面发现了我的问题。在 64 位操作系统上运行时,您必须将配置文件放在 64 位目录中。 32 位 powershell 可执行文件似乎可以很好地从那里获得更改。
只是一个小建议。不再需要时删除注册表项。我只是浪费了大量时间试图找出为什么我不能构建我正在处理的一些 .NET 3.5 项目。
如果您正在执行多目标(即在 VS2010 中编写 .NET 2.0 应用程序),建议的注册表修改解决方案会产生令人讨厌的副作用。谨防。
请注意,Microsoft 强烈警告不要这样做:“虽然可以使用各种机制(例如为 PowerShell 创建配置文件或编辑注册表)强制 PowerShell 2.0 与 .NET Framework 4.0 一起运行,但这些机制不受支持并且可以对其他 PowerShell 功能的负面影响,例如 PowerShell 远程处理和具有混合模式程序集的 cmdlet。” connect.microsoft.com/PowerShell/feedback/details/525435/… Powershell 3.0 原生支持 .NET 4.0。
P
Peter Mortensen

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

如果强制迁移,许多产品将无法工作,这是一种测试辅助手段,而不是生产质量机制。 Visual Studio 2008 和 2010、MSBuild、turbotax 和许多网站、SharePoint 等不应自动迁移。

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


关于使用注册表项的非常好的一点。令人高兴的是,带有配置文件的启动器应用程序运行良好。我们的脚本主要使用文件系统命令和直接 .NET 调用,我们没有注意到命令损坏的任何问题。由于 .NET 4 在很大程度上向后兼容 .NET 2.0,我认为不太可能会有很多损坏的命令(尽管小心一点也无妨:)。
M
Mike Zboray

如果您只需要在 .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


T
Tim Lewis

如果您仍然停留在 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

这是迄今为止最好的答案,因为它是一个非常本地化的更改,并且不会对系统进行任何持久更改。好东西!
极好的!你能在这里帮忙吗? stackoverflow.com/questions/39801315/…
@TimLewis,是否可以将多个语句发送到同一个 ps4.cmd 实例?
@johnywhy,向 .cmd 发送多个语句与向 .exe 发送多个语句相同,因为 .cmd 使用 %* 将其所有参数传递给 .exe。但是,这并没有什么不同,因为在将参数传递给它正在启动的可执行文件时,您仍然必须小心 cmd.exe 如何解析命令行。我会看看你的其他堆栈溢出问题并在那里解决细节。
我尝试将此技术与 -Version 命令行参数结合使用 docs.microsoft.com/en-us/powershell/scripting/core-powershell/… 遗憾的是,它不起作用;我的最新版本的 PowerShell (5.1.17134.407) 由 $PSVersionTable.PSVersion 确定,而是启动。
G
Glorfindel

以下是我用来支持 .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 函数)。


J
Jeppe Stig Nielsen

其他答案来自 2012 年之前,他们专注于“破解”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编辑:还有thread Which .NET version is my PowerShell script using?

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


Windows Management Framework 4.0(它们与 3.0 类似)的系统要求是:Windows 7、Windows Embedded Standard 7、Windows Server 2008 R2、Windows Server 2012。
P
Peter Mortensen

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

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

HKLM:\Software\Microsoft\Powershell\1\PowerShellEngine\RuntimeVersion(64 位和 32 位)

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

将该键的值更改为所需的版本。请记住,尽管某些管理单元可能不再加载,除非它们与 .NET 4 兼容(WASP 是唯一一个我遇到问题的管理单元,但我并没有真正使用它)。 VMWareSQL Server 2008、PSCX、Active Directory(Microsoft 和 Quest Software)和 SCOM 都可以正常工作。


+1这是一个非常重要的替代方案(并且更好),而不是影响所有 .net 应用程序的其他 reg 条目,但此解决方案仅影响 powershell。
在实施“OnlyUseLatestCLR”后,我的 Fiddler 坏了,一些 powershell 脚本由于无法联系某些服务器而不再运行。我在 regedt32 中手动将值更改回 0,现在一切都可以正常工作了。谢谢!
什么是 WASP、PSCX 和 SCOM(在此上下文中)?
G
Grant Holliday

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

请参阅Option 2 – Hosting Windows PowerShell yourself

首先,添加对 System.Management.Automation 和 Microsoft.PowerShell.ConsoleHost 程序集的引用,这些程序集可以在 %programfiles%\Reference Assemblies\Microsoft\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
            );
        }
    }
}

P
Peter Mortensen

作为另一种选择,最新的 PoshConsole 版本包括针对 .NET 4 RC 的二进制文件(它在 RTM 版本上运行良好),无需任何配置。


t
txt

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

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