.NET 4ランタイムでPowerShellを実行するにはどうすればよいですか?


234

一部の.NETアセンブリを管理するPowerShellスクリプトを更新しています。このスクリプトは、.NET 2(PowerShellが実行されるのと同じバージョンのフレームワーク)に対してビルドされたアセンブリ用に作成されましたが、.NET 4アセンブリおよび.NET 2アセンブリで動作する必要があります。

.NET 4は古いバージョンのフレームワークに対してビルドされたアプリケーションの実行をサポートしているため、.NET 4アセンブリに対して実行する必要がある場合は、.NET 4ランタイムでPowerShellを起動するのが最も簡単な解決策のようです。

.NET 4ランタイムでPowerShellを実行するにはどうすればよいですか?



8
最近の最も簡単な解決策は、CLRVersion:4.0.30319.1を使用するPowershell 3.0 CTPをインストールすることです。
jon Z

2
まだPowerShell 2を使用している人は誰でも、マシン全体の構成を編集する必要がないローカライズされたソリューションについて、Tim Lewisの回答参照してください
エリックエスキルセン2017

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

.NET 4.0を使用するようにISEのみを更新するには、構成($ 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に強制的に移行します。.net2および.net 3.5を使用するアプリケーションも



9
明確にするために、powershell.exe(コンソールホストアプリ)自体はネイティブアプリケーションであり、管理対象ではありません。
キース・ヒル

4
私は上から自分の問題を理解しました。64ビットOSで実行する場合は、構成ファイルを64ビットディレクトリに配置する必要があります。32ビットのpowershell実行可能ファイルは、そこから変更をうまく取得するようです。
クリスマッケンジー

11
ほんの少しのアドバイス。不要になったレジストリキーを削除します。自分が取り組んでいる.NET 3.5プロジェクトを構築できなかった理由を突き止めるのに膨大な時間を費やしました。
Klark、2011

7
提案されたレジストリ変更ソリューションは、マルチターゲティング(つまり、VS2010で.NET 2.0アプリを作成)している場合、厄介な副作用があります。注意してください。
Todd Sprang

9
Microsoftはこれを強く警告しています:「PowerShellの構成ファイルの作成やレジストリの編集などのさまざまなメカニズムを使用して、PowerShell 2.0を.NET Framework 4.0で強制的に実行することは可能ですが、これらのメカニズムはサポートされておらず、 PowerShellリモート処理や混合モードアセンブリを使用したコマンドレットなど、他のPowerShell機能への悪影響。」connect.microsoft.com/PowerShell/feedback/details/525435/…Powershell 3.0は、.NET 4.0をネイティブでサポートしています。
Timbo

238

私が見つけた最良の解決策は、ブログ記事「PowerShellでの.NETの新しいバージョンの使用」にあります。これにより、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アプリは変更されません...
Erik A. Brandstadmoen

4
これはうまく機能しますが、すべてのPowerShellに影響します。機能の一部だけが必要な場合は、powershellフォルダーのコピーを作成し、そこでファイルを編集します。
Matt

8
上記のようにファイルを追加しました。しかし、そのファイルが存在する状態でPowerShellを実行することはできません。「ファイルのボリュームが外部で変更されたため、開かれたファイルが無効になっています」というエラーが表示されます。何か案は?
JoshL、2011年

13
@JoshL-64ビットシステムで、64ビットのpowershellを実行しようとしている場合でも、.exe.configをSysWOW64 \ WindowsPowershell(32ビットフォルダー)に移動する必要があることがわかりました。そうしないと、「外部で変更された」エラーが発生します。
Sam

4
powershell.exe.configは2か所にある必要があります。...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、および多数のWebサイト、SharePointなどは自動移行しないでください。

PowerShellを4.0で使用する必要がある場合は、構成ファイルを使用してアプリケーションごとに行う必要があります。正確な推奨事項については、PowerShellチームに確認する必要があります。これにより、既存のPowerShellコマンドの一部が壊れる可能性があります。


レジストリキーの使用について非常に良い点。幸い、設定ファイルを含むランチャーアプリケーションは問題なく動作しています。私たちのスクリプトは主にファイルシステムコマンドと直接.NET呼び出しを使用しており、壊れたコマンドの問題には気づいていません。.NET 4の大部分は.NET 2.0との下位互換性があるため、多くの壊れたコマンドが存在する可能性は低いと思います(ただし、注意する必要はありません)。
XLII皇帝、2010年

26

.NET 4で単一のコマンド、スクリプトブロック、またはスクリプトファイルを実行するだけでよい場合は、.NET 4のアクティベーション構成ファイルを使用して、バージョン4のCLRを使用するPowerShellの単一インスタンスのみを起動してみてください。

全詳細:

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に行き詰まっている場合は、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コンソールのインスタンスを起動できます。

PowerShell 2.0を使用している私のシステムの違いは、cmdから実行される次の2つのコマンドの出力を調べることで確認できます。

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に複数のステートメントを送信することは、.cmdが%*を使用してすべてのパラメーターを.exeに渡すため、.exeに複数のステートメントを送信することと同じです。ただし、起動する実行可能ファイルにパラメーターを渡すときに、cmd.exeがコマンドラインを解析する方法に注意する必要があるため、違いはありません。他のスタックオーバーフローの質問を確認し、そこで詳細を説明します。
Tim Lewis

この手法を-Versionコマンドラインパラメーターdocs.microsoft.com/en-us/powershell/scripting/core-powershell/…と組み合わせて使用​​しようとしましたが、残念ながら機能しません。$ PSVersionTable.PSVersionから決定された私の最新バージョンのPowerShell(5.1.17134.407)が代わりに起動されます。
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スクリプトにステートメントを挿入して、追加の診断情報を表示します(Jeffrey SnoverのResolve-Error関数と同様)。


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年にリリース予定)を意味します。これらのバージョンはすべて、相互に置き換えられているためです。PowerShellのバージョンがわからない場合$PSVersionTableは、インストールされているPowerShellバージョンのスレッドを確認または使用してください。

執筆時点では、PowerShellの最新バージョンは4.0であり、Windows管理フレームワーク(Google検索リンク)を使用してダウンロードできます。


2
Windows管理フレームワーク4.0のシステム要件は、(彼らは3.0のために類似している)している:標準7、Windows Server 2008のR2、Windows Serverの2012のWindows Embedded 7、Windowsの
ピーター・モーテンセン

9

実際、他の.NETアプリケーションに影響を与えることなく、 .NET 4 使用してPowerShellを実行できます。新しいHttpWebRequestの "Host"プロパティを使用するには、そうする必要がありましたが、 "OnlyUseLatestCLR"を変更すると、Fiddlerが破損しました。これは、.NET 4では使用できなかったためです。

PowerShellの開発者は、これが発生することを明らかに予測しており、使用するフレームワークのバージョンを指定するためのレジストリキーを追加しました。わずかな問題の1つは、管理者でもアクセスできないため、変更する前にレジストリキーの所有権を取得する必要があることです。

  • 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にのみ影響します。
クリスチャンミケルセン2012年

「OnlyUseLatestCLR」を実装した後、特定のサーバーに接続できないため、Fiddlerが壊れ、一部のpowershellスクリプトが実行されなくなりました。regedt32で値を手動で0に戻したところ、すべてが再び機能するようになりました。ありがとう!
ネヴィル

WASP、PSCX、SCOMとは(このコンテキストでは)?
Peter Mortensen

7

レジストリまたはapp.configファイルを変更したくない場合は、PowerShell.exeの動作を模倣してPowerShell ConsoleShellをホストする単純な.NET 4コンソールアプリを作成する方法もあります。

オプション2 – Windows PowerShellを自分でホストするを参照してください

最初に、%programfiles%\ Reference Assemblies \ Microsoft \ WindowsPowerShell \ v1.0にあるSystem.Management.AutomationおよびMicrosoft.PowerShell.ConsoleHostアセンブリへの参照を追加します。

次に、次のコードを使用します。

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

COMPLUS_version環境変数をに設定してpowershell.exeを実行するだけv4.0.30319です。たとえば、cmd.exeまたは.bat-fileから:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.