.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의 답변참조하십시오 .
Eric Eskildsen

1
비 시스템 전체 및 fileless 솔루션을 참조 이 답변
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으로 강제 마이그레이션합니다.



9
분명히하기 위해 powershell.exe (콘솔 호스트 앱) 자체는 관리되지 않는 기본 응용 프로그램입니다.
Keith Hill

4
나는 위에서 내 문제를 알아 냈다. 64 비트 OS에서 실행될 때 구성 파일을 64 비트 디렉토리에 두어야합니다. 32 비트 powershell 실행 파일은 변경 사항을 적용한 것으로 보입니다.
Chris McKenzie

11
하나의 작은 조언. 더 이상 필요하지 않은 레지스트리 키를 제거하십시오. 방금 작업중 인 .NET 3.5 프로젝트를 만들 수없는 이유를 찾으려고 많은 시간을 잃었습니다.
클라크

7
제안 된 레지스트리 수정 솔루션은 다중 타겟팅 (예 : VS2010에서 .NET 2.0 앱 작성)을 수행하는 경우 심각한 부작용이 있습니다. 조심하십시오.
Todd Sprang

9
Microsoft는이 작업을 수행하지 않을 것을 강력히 경고합니다. "PowerShell에 대한 구성 파일 작성 또는 레지스트리 편집과 같은 다양한 메커니즘을 사용하여 PowerShell 2.0을 .NET Framework 4.0과 함께 실행할 수 있지만 이러한 메커니즘은 지원되지 않으며 혼합 모드 어셈블리를 사용하는 PowerShell 원격 및 cmdlet과 같은 다른 PowerShell 기능에 대한 부작용. " connect.microsoft.com/PowerShell/feedback/details/525435/… Powershell 3.0은 .NET 4.0을 기본적으로 지원합니다.
Timbo

238

내가 찾은 가장 좋은 솔루션은 블로그 게시물 .NET의 최신 버전 .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> 

추가 빠른 설치 정보 :

위치와 파일은 플랫폼에 따라 다릅니다. 그러나 솔루션이 어떻게 작동하게하는지에 대한 인라인 요지를 제공 할 것입니다.

  • cd $pshome Powershell 창에서 실행 하면 컴퓨터에서 PowerShell의 위치를 ​​찾을 수 있습니다 (DOS 프롬프트에서는 작동하지 않음).
    • 경로는 (예)와 같습니다 C:\Windows\System32\WindowsPowerShell\v1.0\
  • 의 구성을 넣어 파일 이름은 다음과 같습니다 powershell.exe.config당신이 경우에 PowerShell.exe(필요하다면 설정 파일을 생성)가 실행되고있다.
    • PowerShellISE.Exe실행중인 경우 다음과 같이 컴패니언 구성 파일을 작성해야합니다.PowerShellISE.Exe.config

23
확실히 올바른 방법입니다. 이것은 컴퓨터의 다른 모든 .NET 앱이 아니라 Powershell의 동작 만 변경합니다.
Erik A. Brandstadmoen

4
이것은 잘 작동하지만 모든 PowerShell에 영향을 미칩니다. 일부 기능 만 원한다면 powershell 폴더를 복사 한 다음 파일을 편집하십시오.
Matt

8
위에서 언급 한대로 파일을 추가했습니다. 그러나 더 이상 해당 파일이있는 상태에서 PowerShell을 실행할 수 없습니다. "열린 파일이 더 이상 유효하지 않도록 파일의 볼륨이 외부에서 변경되었습니다."라는 오류가 발생합니다. 어떤 아이디어?
JoshL

13
@JoshL-64 비트 시스템에서 64 비트 powershell을 실행하려고해도 .exe.config가 SysWOW64 \ WindowsPowershell (32 비트 폴더)로 이동해야한다는 것을 알았습니다. 그렇지 않으면 '외부 적으로 변경된'오류가 발생합니다.
Sam

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 등은 자동 마이그레이션되지 않아야합니다.

4.0에서 PowerShell을 사용해야하는 경우 구성 파일을 사용하여 응용 프로그램별로 수행해야하며 정확한 권장 사항을 PowerShell 팀에 확인해야합니다. 이로 인해 기존 PowerShell 명령이 손상 될 수 있습니다.


레지스트리 키 사용에 대한 아주 좋은 지적. 행복하게도 구성 파일이있는 실행기 응용 프로그램은 정상적으로 작동합니다. 우리의 스크립트는 주로 파일 시스템 명령과 직접 .NET 호출을 사용하며, 깨진 명령에 아무런 문제가 없습니다. .NET 4는 .NET 2.0과 대체로 역 호환되기 때문에 깨진 명령이 많이있을 것 같지는 않습니다 (주의해도 결코 아프지 않습니다).
황제 XLII


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 콘솔 인스턴스를 시작할 수 있습니다.

cmd에서 실행되는 다음 두 명령의 출력을 검사하여 PowerShell 2.0이있는 시스템의 차이점을 확인할 수 있습니다.

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
이것은 매우 현지화 된 변경이므로 시스템을 영구적으로 변경하지 않기 때문에 가장 좋은 대답입니다. 좋은 물건!
Sebastian

환상적입니다! 여기 좀 도와 줄래? stackoverflow.com/questions/39801315/…
johny 왜

@TimLewis, 동일한 ps4.cmd 인스턴스에 여러 명령문을 보낼 수 있습니까?
johny 왜

@johnywhy, .cmd에 여러 문을 보내는 것은 .cmd가 % *를 사용하여 모든 매개 변수를 .exe에 전달하기 때문에 .exe에 여러 문을 보내는 것과 같습니다. 그러나 cmd.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 년 이전의 답변으로, 최신 버전의 .NET Framework 및 CLR (공용 언어 런타임)을 대상으로 PowerShell 1.0 또는 PowerShell 2.0을 "해킹"하는 데 중점을 둡니다.

그러나 많은 의견에서 작성된 것처럼 2012 년 이후 (PowerShell 3.0이 출시 된 이후) 훨씬 더 나은 솔루션은 최신 버전의 PowerShell설치하는 것 입니다. 자동으로 CLR을 대상으로 v4.0.30319합니다. 이는 .NET 4.0, 4.5, 4.5.1, 4.5.2 또는 4.6 (2015 년에 예상 됨)을 의미하며,이 모든 버전은 서로 대체 할 수 있기 때문입니다. PowerShell 버전 이 확실하지 않으면 설치된 PowerShell 버전 확인 스레드를 사용 $PSVersionTable하거나 참조하십시오 .

글을 쓰는 시점에서 최신 버전의 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

실제로 다른 .NET 응용 프로그램에 영향을주지 않고 .NET 4 사용하여 PowerShell을 실행할 수 있습니다 . 새 HttpWebRequest "Host"속성을 사용하려면 그렇게해야했지만 "OnlyUseLatestCLR"을 변경하면 Fiddler가 .NET 4에서 사용할 수 없으므로 Fiddler가 중단되었습니다.

PowerShell 개발자는 분명히 이런 일이 발생할 것으로 예상하고, 사용할 Framework 버전을 지정하기 위해 레지스트리 키를 추가했습니다. 약간의 문제는 관리자조차도 액세스 권한이 없기 때문에 레지스트리 키를 변경하기 전에 소유권을 가져와야한다는 것입니다.

  • HKLM : \ Software \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64 비트 및 32 비트)
  • HKLM : \ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64 비트 시스템에서 32 비트)

해당 키의 값을 필요한 버전으로 변경하십시오. 일부 스냅인은 .NET 4 호환 가능하지 않으면 더 이상로드되지 않을 수 있습니다 (WASP는 문제가있는 유일한 도구이지만 실제로는 사용하지 않습니다). VMWare , SQL Server 2008 , PSCX, Active Directory (Microsoft 및 Quest Software ) 및 SCOM 모두 잘 작동합니다.


+1 이것은 모든 .net 응용 프로그램에 영향을 미치는 다른 reg 항목보다 매우 중요한 대안이며 더 우수하지만이 솔루션은 powershell에만 영향을줍니다.
Christian Mikkelsen

"OnlyUseLatestCLR"을 구현 한 후 Fiddler는 특정 서버에 접속할 수 없어서 일부 Powershell 스크립트가 더 이상 실행되지 않습니다. regedt32에서 수동으로 값을 0으로 다시 변경했으며 이제는 다시 작동하지 않습니다. 감사!
Neville

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.AutomationMicrosoft.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 파일에서 :

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.