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

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

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

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

10 ответов

Решение

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.


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

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

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

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

Если вам нужно выполнить только одну команду, блок сценария или файл сценария в.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

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

Создать powershell4.cmd где-то на вашем пути со следующим содержанием:

@echo off
:: http://stackru.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

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

Другие ответы - до 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).

Фактически, вы можете заставить 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 работают нормально.

Если вы не хотите изменять реестр или файлы 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
            );
        }
    }
}

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

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

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
Другие вопросы по тегам