Làm cách nào để chạy PowerShell với thời gian chạy .NET 4?


234

Tôi đang cập nhật tập lệnh PowerShell quản lý một số cụm .NET. Kịch bản được viết cho các hội đồng được xây dựng dựa trên .NET 2 (cùng phiên bản của khung mà PowerShell chạy cùng), nhưng bây giờ cần phải làm việc với các hội đồng .NET 4 cũng như các hội đồng .NET 2.

Do .NET 4 hỗ trợ chạy các ứng dụng được xây dựng dựa trên các phiên bản cũ hơn của khung, nên có vẻ như giải pháp đơn giản nhất là khởi chạy PowerShell với thời gian chạy .NET 4 khi tôi cần chạy nó với các hội đồng .NET 4.

Làm cách nào để chạy PowerShell với thời gian chạy .NET 4?



8
Ngày nay, giải pháp đơn giản nhất là cài đặt Powershell 3.0 CTP sử dụng CLRVersion: 4.0.30319.1.
jon Z

2
Bất cứ ai vẫn bị mắc kẹt với PowerShell 2, hãy xem câu trả lời của Tim Lewis để biết giải pháp được bản địa hóa không yêu cầu chỉnh sửa bất kỳ cấu hình nào trên toàn máy.
Eric Eskildsen

1
Đối với một giải pháp không có hệ thống và không có hệ thống, hãy xem câu trả lời này
vkrzv

Câu trả lời:


147

PowerShell (công cụ) chạy tốt trong .NET 4.0. PowerShell (máy chủ bảng điều khiển và ISE ) thì không, đơn giản vì chúng được biên dịch dựa trên các phiên bản .NET cũ hơn. Có một cài đặt đăng ký sẽ thay đổi .NET framework được tải trên toàn hệ thống , điều này sẽ cho phép PowerShell sử dụng các lớp .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

Để chỉ cập nhật ISE để sử dụng .NET 4.0, bạn có thể thay đổi tệp cấu hình ($ psHome \ powershell_ise.exe.config) để có một đoạn như thế này:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup>
      <supportedRuntime version="v4.0.30319" />
    </startup>
</configuration>

Bạn có thể xây dựng các ứng dụng .NET 4.0 gọi PowerShell bằng API PowerShell (System.Man Quản lý.Automation.PowerShell), nhưng các bước này sẽ giúp các máy chủ PowerShell trong hộp hoạt động theo .NET 4.0.


Xóa các khóa đăng ký khi bạn không cần chúng nữa. Đây là các khóa toàn máy và di chuyển cưỡng bức TẤT CẢ các ứng dụng sang .NET 4.0, ngay cả các ứng dụng sử dụng .net 2 và .net 3.5



9
Nói rõ hơn, chính powershell.exe (ứng dụng máy chủ bảng điều khiển) là một ứng dụng gốc - không được quản lý.
Keith Hill

4
Tôi đã tìm ra vấn đề của tôi từ trên cao. Bạn phải đặt tệp cấu hình trong thư mục 64 bit khi chạy trên HĐH 64 bit. Việc thực thi quyền hạn 32 bit dường như nhận được sự thay đổi tốt từ đó.
Chris McKenzie

11
Chỉ cần một lời khuyên nhỏ. Xóa các khóa đăng ký khi bạn không cần chúng nữa. Tôi vừa mất rất nhiều thời gian để cố gắng tìm hiểu lý do tại sao tôi không thể xây dựng một số dự án .NET 3.5 mà tôi đang làm.
Klark

7
Giải pháp sửa đổi sổ đăng ký được đề xuất có tác dụng phụ khó chịu nếu bạn đang thực hiện đa mục tiêu (ví dụ: viết ứng dụng .NET 2.0 trong VS2010). Coi chừng.
Todd Sprang

9
Lưu ý rằng Microsoft cảnh báo mạnh mẽ chống lại việc này: "Mặc dù có thể buộc PowerShell 2.0 chạy với .NET Framework 4.0 bằng nhiều cơ chế khác nhau như tạo tệp cấu hình cho PowerShell hoặc chỉnh sửa sổ đăng ký, các cơ chế này không được hỗ trợ và có thể có tác dụng phụ tiêu cực đối với chức năng PowerShell khác như điều khiển từ xa PowerShell và lệnh ghép ngắn với các cụm chế độ hỗn hợp. " connect.microsoft.com/PowerShell/feedback/details/525435/ từ Powershell 3.0 có hỗ trợ riêng cho .NET 4.0.
Timbo

238

Giải pháp tốt nhất tôi đã tìm thấy là trong bài đăng trên blog Sử dụng (các) Phiên bản mới hơn của .NET với PowerShell . Điều này cho phép powershell.exe chạy với các hội đồng .NET 4.

Chỉ cần sửa đổi (hoặc tạo) $pshome\powershell.exe.configđể nó chứa các mục sau:

<?xml version="1.0"?> 
<configuration> 
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
        <supportedRuntime version="v4.0.30319"/> 
        <supportedRuntime version="v2.0.50727"/> 
    </startup> 
</configuration> 

Bổ sung, ghi chú thiết lập nhanh:

Vị trí và tập tin phụ thuộc vào nền tảng; tuy nhiên sẽ cung cấp cho bạn một ý chính nội tuyến về cách làm cho giải pháp hoạt động cho bạn.

  • Bạn có thể tìm vị trí của PowerShell trên máy tính của mình bằng cách thực thi cd $pshome trong cửa sổ Powershell (không hoạt động từ dấu nhắc DOS).
    • Đường dẫn sẽ giống như (ví dụ) C:\Windows\System32\WindowsPowerShell\v1.0\
  • Tên tệp để đặt cấu hình là: powershell.exe.confignếu bạn PowerShell.exeđang được thực thi (tạo tệp cấu hình nếu cần).
    • Nếu PowerShellISE.Exeđang chạy thì bạn cần tạo tệp cấu hình đồng hành của nó làPowerShellISE.Exe.config

23
Chắc chắn là cách chính xác để làm điều đó. Điều này chỉ thay đổi hành vi của Powershell, không phải mọi ứng dụng .NET khác trên máy của bạn ...
Erik A. Brandstadmoen

4
Điều này hoạt động tốt nhưng ảnh hưởng đến tất cả PowerShell của bạn. Nếu bạn chỉ muốn một số chức năng tạo một bản sao của thư mục powershell và sau đó chỉnh sửa tệp ở đó.
Matt

8
Tôi đã thêm một tập tin như đã lưu ý ở trên. Tuy nhiên, tôi không còn có thể chạy PowerShell với tệp đó nữa - Tôi gặp lỗi "Âm lượng cho tệp đã bị thay đổi bên ngoài để tệp đã mở không còn hợp lệ." Có ý kiến ​​gì không?
JoshL

13
@JoshL - trên hệ thống 64 bit, tôi đã tìm thấy .exe.config cần phải truy cập vào SysWOW64 \ WindowsPowershell (thư mục 32 bit), ngay cả khi bạn đang cố chạy quyền hạn 64 bit. Nếu không, bạn sẽ gặp lỗi 'thay đổi bên ngoài'.
Sam

4
Powerhell.exe.config cần ở hai vị trí .... C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ và C: \ Windows \ SysWOW64 \ WindowsPowerShell \ v1.0 \
Jonesome Phục hồi

28

Hãy cẩn thận với việc sử dụng phương pháp khóa đăng ký. Đây là các khóa toàn máy và di chuyển TẤT CẢ các ứng dụng sang .NET 4.0.

Nhiều sản phẩm không hoạt động nếu di chuyển cưỡng bức và đây là một hỗ trợ thử nghiệm và không phải là một cơ chế chất lượng sản xuất. Visual Studio 2008 và 2010, MSBuild , turbotax và một loạt các trang web, SharePoint , v.v không nên tự động hóa.

Nếu bạn cần sử dụng PowerShell với 4.0, việc này nên được thực hiện trên cơ sở mỗi ứng dụng với tệp cấu hình, bạn nên kiểm tra với nhóm PowerShell theo khuyến nghị chính xác. Điều này có khả năng phá vỡ một số lệnh PowerShell hiện có.


Điểm rất tốt về việc sử dụng khoá đăng ký. Hạnh phúc, ứng dụng launcher với tập tin cấu hình đang hoạt động tốt. Các tập lệnh của chúng tôi chủ yếu sử dụng các lệnh hệ thống tệp và các cuộc gọi .NET trực tiếp và chúng tôi không nhận thấy bất kỳ vấn đề nào với các lệnh bị hỏng. Vì .NET 4 phần lớn tương thích ngược với .NET 2.0, tôi không nghĩ rằng có khả năng sẽ có nhiều lệnh bị hỏng (mặc dù nó không bao giờ gây tổn hại khi phải thận trọng :).
Hoàng đế XLII


21

Nếu bạn vẫn bị mắc kẹt trên PowerShell v1.0 hoặc v2.0, đây là biến thể của tôi về câu trả lời tuyệt vời của Jason Stangroome.

Tạo một powershell4.cmdnơi nào đó trên đường dẫn của bạn với các nội dung sau:

@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=

Điều này sẽ cho phép bạn khởi chạy một phiên bản của bảng điều khiển powershell chạy trong .NET 4.0.

Bạn có thể thấy sự khác biệt trên hệ thống của tôi nơi tôi có PowerShell 2.0 bằng cách kiểm tra đầu ra của hai lệnh sau chạy từ 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
Đây là câu trả lời tốt nhất vì đây là một thay đổi rất cục bộ và không thực hiện bất kỳ thay đổi liên tục nào đối với hệ thống. Đồ tốt!
Sebastian

tuyệt diệu! Bạn có thể giúp đỡ ở đây? stackoverflow.com/questions/39801315/ từ
johny tại sao

@TimLewis, có thể gửi nhiều câu lệnh đến cùng một ví dụ ps4.cmd không?
johny tại sao

@johnywhy, gửi nhiều câu lệnh đến .cmd cũng giống như gửi nhiều câu lệnh đến .exe vì .cmd sử dụng% * để truyền tất cả các tham số của nó qua .exe. Tuy nhiên, điều này không tạo ra sự khác biệt vì bạn vẫn phải cẩn thận với cách cmd.exe phân tích cú pháp dòng lệnh khi nó chuyển các tham số cho tệp thực thi mà nó đang khởi chạy. Tôi sẽ xem xét câu hỏi tràn chồng khác của bạn và địa chỉ cụ thể ở đó.
Tim Lewis

Tôi đã thử sử dụng kỹ thuật này kết hợp với tham số dòng lệnh -Version docs.microsoft.com/en-us/powershell/scripting/core-powershell/. Đáng buồn thay, nó không hoạt động; Phiên bản mới nhất của PowerShell (5.1.17134.407), như được xác định từ $ PSVersionTable.PSVersion, được ra mắt thay thế.
eisenpony

17

Dưới đây là nội dung của tệp cấu hình mà tôi đã sử dụng để hỗ trợ cả hai phiên bản .NET 2.0 và .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>

Ngoài ra, đây là phiên bản đơn giản của mã tương thích PowerShell 1.0 mà tôi đã sử dụng để thực thi các tập lệnh của chúng tôi từ các đối số dòng lệnh được truyền:

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;
    }
  }
}

Ngoài cách xử lý lỗi cơ bản được hiển thị ở trên, chúng tôi cũng đưa một trapcâu lệnh vào tập lệnh để hiển thị thông tin chẩn đoán bổ sung (tương tự như chức năng Giải quyết lỗi của Jeffrey Snover ).


10

Các câu trả lời khác là từ trước năm 2012 và họ tập trung vào "hack" PowerShell 1.0 hoặc PowerShell 2.0 để nhắm mục tiêu các phiên bản mới hơn của .NET Framework và Common Language Runtime (CLR).

Tuy nhiên, như đã được viết trong nhiều bình luận, kể từ năm 2012 (khi PowerShell 3.0 xuất hiện), một giải pháp tốt hơn nhiều là cài đặt phiên bản PowerShell mới nhất . Nó sẽ tự động nhắm mục tiêu CLR v4.0.30319. Điều này có nghĩa là .NET 4.0, 4.5, 4.5.1, 4.5.2 hoặc 4.6 (dự kiến ​​vào năm 2015) vì tất cả các phiên bản này là thay thế tại chỗ của nhau. Sử dụng $PSVersionTablehoặc xem Xác định cài đặt PowerShell phiên bản đề nếu bạn không chắc chắn về phiên bản PowerShell bạn.

Tại thời điểm viết bài, phiên bản mới nhất của PowerShell là 4.0 và có thể tải xuống bằng Windows Management Framework (liên kết tìm kiếm của Google) .


2
Các yêu cầu hệ thống cho Windows Management Framework 4.0 (tương tự 3.0) là: Windows 7, Windows Embedded Standard 7, Windows Server 2008 R2, Windows Server 2012.
Peter Mortensen

9

Trên thực tế, bạn có thể có được PowerShell để chạy bằng .NET 4 mà không ảnh hưởng đến các ứng dụng .NET khác. Tôi cần phải làm như vậy để sử dụng thuộc tính "Máy chủ" mới của httpWebRequest, tuy nhiên việc thay đổi "OnlyUseLatestCLR" đã phá vỡ Fiddler vì không thể sử dụng được trong .NET 4.

Các nhà phát triển của PowerShell rõ ràng đã thấy trước điều này xảy ra và họ đã thêm khóa đăng ký để chỉ định phiên bản nào của Khung nên sử dụng. Một vấn đề nhỏ là bạn cần có quyền sở hữu khóa đăng ký trước khi thay đổi, vì ngay cả quản trị viên cũng không có quyền truy cập.

  • HKLM: \ Phần mềm \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64 bit và 32 bit)
  • HKLM: \ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (32 bit trên máy 64 bit)

Thay đổi giá trị của khóa đó thành phiên bản bắt buộc. Hãy nhớ rằng mặc dù một số snapins có thể không tải nữa trừ khi chúng tương thích với .NET 4 (WASP là người duy nhất tôi gặp sự cố, nhưng dù sao tôi cũng không thực sự sử dụng nó). VMWare , SQL Server 2008 , PSCX, Active Directory (Microsoft và Quest Software ) và SCOM đều hoạt động tốt.


+1 Đây là một thay thế rất quan trọng (và tốt hơn) so với mục reg khác sẽ ảnh hưởng đến tất cả các ứng dụng .net, nhưng giải pháp này chỉ ảnh hưởng đến powershell.
Christian Mikkelsen

Sau khi thực hiện "OnlyUseLatestCLR", Fiddler của tôi đã bị hỏng cũng như một số tập lệnh powershell không chạy nữa do không thể liên lạc với một số máy chủ nhất định. Tôi đã tự thay đổi các giá trị trở về 0 trong regedt32 và bây giờ hoạt động trở lại hoạt động. Cảm ơn!
Neville

WASP, PSCX và SCOM là gì (trong bối cảnh này)?
Peter Mortensen

7

Nếu bạn không muốn sửa đổi các tệp registry hoặc app.config, một cách khác là tạo một ứng dụng bảng điều khiển .NET 4 đơn giản bắt chước những gì PowerShell.exe làm và lưu trữ PowerShell ConsoleShell.

Xem Tùy chọn 2 - Lưu trữ Windows PowerShell cho mình

Trước tiên, hãy thêm một tham chiếu đến các cụm System.Man Quản lý.AutomationMicrosoft.PowerShell.Consolehost có thể được tìm thấy trong % programfiles% \ Reference Assemblies \ Microsoft \ WindowsPowerShell \ v1.0

Sau đó sử dụng mã sau đây:

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

Cũng giống như một tùy chọn khác, bản phát hành PoshConsole mới nhất bao gồm các tệp nhị phân được nhắm mục tiêu đến .NET 4 RC (hoạt động tốt so với bản phát hành RTM) mà không cần bất kỳ cấu hình nào.


1

Chỉ cần chạy powershell.exe với COMPLUS_versionbiến môi trường được đặt thành v4.0.30319. Ví dụ: từ cmd.exe hoặc .bat-file:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.