Как я могу запустить PowerShell со средой выполнения .NET 4?


234

Я обновляю скрипт PowerShell, который управляет некоторыми сборками .NET. Сценарий был написан для сборок, созданных на основе .NET 2 (той же версии платформы, с которой работает PowerShell), но теперь он должен работать как со сборками .NET 4, так и со сборками .NET 2.

Поскольку .NET 4 поддерживает запуск приложений, созданных на основе более старых версий инфраструктуры, кажется, что самое простое решение - запустить PowerShell со средой выполнения .NET 4, когда мне нужно запустить ее на сборках .NET 4.

Как я могу запустить PowerShell со средой выполнения .NET 4?



8
В наши дни самым простым решением будет установить CTP-версию Powershell 3.0, которая использует CLRVersion: 4.0.30319.1.
— Jon Z

2
Любой, кто все еще застрял в PowerShell 2, видит ответ Тима Льюиса о локализованном решении, которое не требует редактирования какой-либо конфигурации для всей машины.
— Эрик

1
Для несистемного и безфайлового решения смотрите этот ответ
— vkrzv

Ответы:


147

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>

Вы можете создавать приложения .NET 4.0, которые вызывают PowerShell, используя API-интерфейс PowerShell (System.Management.Automation.PowerShell), но эти шаги помогут настроить встроенные хосты PowerShell для работы в .NET 4.0.


Удалите ключи реестра, когда они вам больше не нужны. Это ключи компьютера и принудительная миграция ВСЕХ приложений в .NET 4.0, даже приложений, использующих .net 2 и .net 3.5.



9
Для ясности, powershell.exe (приложение хоста консоли) является нативным приложением, а не управляемым.
— Кит Хилл

4
Я разобрался со своей проблемой сверху. Вы должны поместить файл конфигурации в 64-битный каталог при работе в 64-битной ОС. 32-битный исполняемый файл powershell, похоже, отлично воспринимает изменения.
— Крис Маккензи,

11
Всего один маленький совет. Удалите ключи реестра, когда они вам больше не нужны. Я просто потерял кучу времени, пытаясь выяснить, почему я не смог создать какой-то проект .NET 3.5, над которым я работаю.
— Кларк

7
Предлагаемое решение для модификации реестра имеет неприятные побочные эффекты, если вы используете многоцелевой таргетинг (например, написание приложений .NET 2.0 в VS2010). Осторожно.
— Тодд Спранг

9
Обратите внимание, что Microsoft настоятельно рекомендует не делать этого: «Хотя можно заставить PowerShell 2.0 работать с .NET Framework 4.0, используя различные механизмы, такие как создание файла конфигурации для PowerShell или редактирование реестра, эти механизмы не поддерживаются и могут иметь отрицательные побочные эффекты для других функций PowerShell, таких как удаленное взаимодействие PowerShell и командлеты со сборками в смешанном режиме ». connect.microsoft.com/PowerShell/feedback/details/525435/… Powershell 3.0 имеет встроенную поддержку .NET 4.0.
— Тимбо

238

Лучшее решение, которое я нашел, - это сообщение в блоге « Использование более новых версий .NET с 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

23
Определенно правильный способ сделать это. Это изменяет только поведение Powershell, а не любого другого приложения .NET на вашем компьютере ...
— Эрик А. Брандштадмоен,

4
Это хорошо работает, но влияет на все ваши PowerShell. Если вам нужны только некоторые функции, сделайте копию папки powershell, а затем отредактируйте файл там.
— Мэтт

8
Я добавил файл, как отмечено выше. Однако я больше не могу запускать PowerShell с этим файлом - я получаю сообщение об ошибке «Том для файла был изменен извне, так что открытый файл больше не действителен». Любые идеи?
— JoshL

13
@JoshL - в 64-битной системе я обнаружил, что .exe.config должен идти в SysWOW64 \ WindowsPowershell (32-битная папка), даже если вы пытаетесь запустить 64-битную powershell. В противном случае вы получите «внешне измененную» ошибку.
— Сэм

4
Файл powershell.exe.config должен находиться в двух местах .... C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ и C: \ Windows \ SysWOW64 \ WindowsPowerShell \ v1.0 \
— Jonesome Reinstate Monica

28

Пожалуйста, будьте ОЧЕНЬ осторожны с использованием ключа реестра. Это машинные ключи, которые принудительно переносят ВСЕ приложения в .NET 4.0.

Многие продукты не работают при принудительной миграции, и это средство тестирования, а не механизм обеспечения качества производства. Visual Studio 2008 и 2010, MSBuild , Turbotax и множество веб-сайтов, SharePoint и т. Д. Не должны быть перенастроены.

Если вам нужно использовать PowerShell с 4.0, это следует делать для каждого приложения с помощью файла конфигурации, вам следует проконсультироваться с командой PowerShell о точной рекомендации. Это может нарушить некоторые существующие команды PowerShell.


Очень хороший момент об использовании ключа реестра. К счастью, приложение запуска с файлом конфигурации работает просто отлично. Наши сценарии в основном используют команды файловой системы и прямые вызовы .NET, и мы не заметили никаких проблем со сломанными командами. Поскольку .NET 4 в значительной степени обратно совместима с .NET 2.0, я не думаю, что будет много неработающих команд (хотя это не мешает быть предостерегающим :).
— Император XLII

26

Если вам нужно выполнить только одну команду, блок сценария или файл сценария в .NET 4, попробуйте использовать файлы конфигурации активации из .NET 4, чтобы запустить только один экземпляр PowerShell с использованием версии 4 CLR.

Полная информация:

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

Пример модуля PowerShell:

https://gist.github.com/882528


21

Если вы все еще застряли на PowerShell v1.0 или v2.0, вот мой вариант отличного ответа Джейсона Стангрума.

Создайте 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=

Это позволит вам запустить экземпляр консоли powershell, работающей под .NET 4.0.

Вы можете увидеть разницу в моей системе, где у меня PowerShell 2.0, просмотрев вывод следующих двух команд, запущенных из 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

3
Это, безусловно, лучший ответ, поскольку это очень локализованное изменение, которое не вносит постоянных изменений в систему. Хорошая вещь!
— Себастьян

фантастика! Вы можете помочь здесь? 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.
— eisenpony

17

Вот содержимое файла конфигурации, который я использовал для поддержки сборок .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в скрипт оператор для отображения дополнительной диагностической информации (аналогично функции разрешения ошибок Джеффри Сновера ).


10

Другие ответы - до 2012 года, и они сосредоточены на «взломе» PowerShell 1.0 или PowerShell 2.0 для нацеливания на более новые версии .NET Framework и Common Language Runtime (CLR).

Однако, как было написано во многих комментариях, с 2012 года (когда вышла PowerShell 3.0) гораздо лучшим решением будет установка самой новой версии PowerShell . Это будет автоматически предназначаться для CLR v4.0.30319. Это означает .NET 4.0, 4.5, 4.5.1, 4.5.2 или 4.6 (ожидается в 2015 году), поскольку все эти версии являются заменой друг друга. Использование $PSVersionTableили увидеть определение установленной версии PowerShell нитки , если вы не уверены в версии PowerShell.

На момент написания этой статьи новейшая версия PowerShell составляла 4.0, и ее можно загрузить с помощью Windows Management Framework (поисковая ссылка Google) .


2
Системные требования для Windows Management Framework 4.0 (они аналогичны для 3.0): Windows 7, Windows Embedded Standard 7, Windows Server 2008 R2, Windows Server 2012.
— Питер Мортенсен

9

На самом деле вы можете заставить PowerShell работать с использованием .NET 4, не затрагивая другие приложения .NET. Мне нужно было сделать это, чтобы использовать новое свойство «Host» HttpWebRequest, однако изменение «OnlyUseLatestCLR» сломало Fiddler, поскольку его нельзя было использовать в .NET 4.

Разработчики PowerShell, очевидно, предвидели это, и они добавили раздел реестра, чтобы указать, какую версию Framework он должен использовать. Одна небольшая проблема заключается в том, что вам необходимо вступить во владение ключом реестра, прежде чем его менять, поскольку даже администраторы не имеют доступа.

  • HKLM: \ Software \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64-разрядная и 32-разрядная)
  • HKLM: \ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (32-разрядная на 64-разрядной машине)

Измените значение этого ключа на требуемую версию. Имейте в виду, что некоторые оснастки могут больше не загружаться, если они не совместимы с .NET 4 (WASP - единственная, с которой у меня были проблемы, но я все равно не использую ее). VMWare , SQL Server 2008 , PSCX, Active Directory (Microsoft и программное обеспечение Quest ) и SCOM работают нормально.


+1 Это очень важная альтернатива (и лучше), чем другая запись reg, которая повлияет на все приложения .net, но это решение влияет только на powershell.
— Кристиан Миккельсен

После реализации «OnlyUseLatestCLR» мой Fiddler сломался, а некоторые сценарии PowerShell больше не запускаются из-за невозможности связаться с определенными серверами. Я вручную изменил значения обратно на 0 в regedt32, и теперь все снова работает. Спасибо!
— Невилл

Что такое WASP, PSCX и SCOM (в этом контексте)?
— Питер Мортенсен

7

Если вы не хотите изменять реестр или файлы app.config, альтернативный способ - создать простое консольное приложение .NET 4, которое имитирует действия PowerShell.exe и размещает PowerShell ConsoleShell.

См. Вариант 2 - хостинг Windows PowerShell самостоятельно

Сначала добавьте ссылку на сборки 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
            );
        }
    }
}

6

Как и еще один вариант, последний выпуск PoshConsole включает в себя двоичные файлы, нацеленные на .NET 4 RC (которые отлично работают с версией RTM) без какой-либо настройки.


1

Просто запустите powershell.exe с COMPLUS_versionустановленной переменной среды v4.0.30319. Например, из cmd.exe или .bat-файла:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.