Як я можу запустити PowerShell при виконанні .NET 4?


234

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

Оскільки .NET 4 підтримує запущені програми, побудовані на старих версіях фреймворку, здається, що найпростішим рішенням є запуск PowerShell за допомогою .NET 4, коли мені потрібно запустити його проти збірок .NET 4

Як я можу запустити PowerShell при виконанні .NET 4?



8
У наші дні найпростішим рішенням було б встановити Powershell 3.0 CTP, який використовує CLRVersion: 4.0.30319.1.
j 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-розрядна програма, що виконується в повному обсязі, здається, що звідти просто змінить зміни.
Кріс Макензі

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. Якщо ви хочете лише деякі функції, зробіть копію папки з повноваженнями, а потім відредагуйте файл.
Метт

8
Я додав файл, як зазначено вище. Однак я більше не можу запускати PowerShell із наявним файлом - я отримую помилку "Об'єм для файлу зовнішньо змінено, щоб відкритий файл більше не був дійсним". Будь-які ідеї?
JoshL

13
@JoshL - у 64-бітній системі я виявив, що .exe.config повинен перейти в SysWOW64 \ WindowsPowershell (32-бітова папка), навіть якщо ви намагаєтеся запустити 64-бітну панель повноважень. Інакше ви отримуєте помилку «зовні».
Сем

4
Потрібно бути в двох місцях .... 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=

Це дозволить запустити екземпляр консолі powerhell, що працює під .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 / ...
Johny чому

@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 та загальної мови виконання (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.
Peter Mortensen

9

Насправді ви можете змусити PowerShell запускати за допомогою .NET 4, не впливаючи на інші програми .NET. Мені потрібно було це зробити, щоб використовувати нову властивість "Host" HttpWebRequest, проте зміна "OnlyUseLatestCLR" порушила Fiddler, оскільки це не можна було використовувати в .NET 4.

Розробники PowerShell, очевидно, передбачили це, і вони додали ключ реєстру, щоб вказати, яку версію Framework вона повинна використовувати. Одна незначна проблема полягає в тому, що вам потрібно взяти право власності на ключ реєстру, перш ніж змінювати його, оскільки навіть адміністратори не мають доступу.

  • HKLM: \ Програмне забезпечення \ 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 Це дуже важлива альтернатива (і краща), ніж інша запис реєстру, яка вплине на всі програми .net, але це рішення впливає лише на повноваження.
Крістіан Міккельсен

Після впровадження "OnlyUseLatestCLR" мій Fiddler зламав, а також деякі сценарії оболонок повноважень більше не працювали через те, що не вдалося зв’язатися з певними серверами. Я вручну змінив значення назад на 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-file:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.