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

234

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

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

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

Император XLII
источник
Дубликат stackoverflow.com/questions/1940983/… .
Джереми МакГи
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.


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

Император XLII
источник
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) без какой-либо настройки.

Jaykul
источник
1

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

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
vkrzv
источник