Bagaimana saya bisa menjalankan PowerShell dengan runtime .NET 4?

234

Saya memperbarui skrip PowerShell yang mengelola beberapa rakitan .NET. Script ditulis untuk majelis yang dibangun melawan .NET 2 (versi kerangka kerja yang sama yang dijalankan PowerShell), tetapi sekarang perlu bekerja dengan .NET 4 majelis serta .NET 2 majelis.

Karena .NET 4 mendukung aplikasi yang berjalan yang dibangun melawan versi kerangka kerja yang lebih lama, sepertinya solusi paling sederhana adalah meluncurkan PowerShell dengan runtime .NET 4 ketika saya harus menjalankannya melawan .NET 4 rakitan.

Bagaimana saya bisa menjalankan PowerShell dengan runtime .NET 4?

Kaisar XLII
sumber
Gandakan stackoverflow.com/questions/1940983/… .
Jeremy McGee
8
Saat ini solusi termudah adalah menginstal Powershell 3.0 CTP yang menggunakan CLRVersion: 4.0.30319.1.
jon Z
2
Siapa pun yang masih terjebak dengan PowerShell 2, lihat jawaban Tim Lewis untuk solusi terlokalisasi yang tidak memerlukan pengeditan konfigurasi mesin apa pun.
Eric Eskildsen
1
Untuk solusi non-seluruh sistem dan tanpa-filet lihat jawaban ini
vkrzv

Jawaban:

147

PowerShell (engine) bekerja dengan baik di bawah .NET 4.0. PowerShell (host konsol dan ISE ) tidak, hanya karena mereka dikompilasi dengan versi .NET yang lebih lama. Ada pengaturan registri yang akan mengubah .NET dimuat kerangka sistem , yang pada gilirannya akan memungkinkan PowerShell untuk menggunakan .NET 4.0 kelas:

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

Untuk memperbarui hanya ISE untuk menggunakan. NET 4.0, Anda dapat mengubah file konfigurasi ($ psHome \ powershell_ise.exe.config) untuk memiliki chunk seperti ini:

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

Anda dapat membangun aplikasi .NET 4.0 yang memanggil PowerShell menggunakan PowerShell API (System.Management.Automation.PowerShell) baik-baik saja, tetapi langkah-langkah ini akan membantu membuat host PowerShell dalam-kotak untuk bekerja di bawah .NET 4.0.


Hapus kunci registri ketika Anda tidak membutuhkannya lagi. Ini adalah kunci di seluruh mesin dan secara paksa memigrasi SEMUA aplikasi ke .NET 4.0, bahkan aplikasi menggunakan .net 2 dan .net 3.5


Mulai Otomatis
sumber
9
Supaya jelas, powershell.exe (aplikasi host konsol) itu sendiri adalah aplikasi asli - tidak dikelola.
Keith Hill
4
Saya menemukan masalah saya dari atas. Anda harus meletakkan file konfigurasi di direktori 64-bit saat dijalankan pada OS 64-bit. The 32-bit powershell executable tampaknya mengambil perubahan dengan baik dari sana.
Chris McKenzie
11
Hanya satu saran kecil. Hapus kunci registri ketika Anda tidak membutuhkannya lagi. Saya baru saja kehilangan satu ton waktu untuk mencari tahu mengapa saya tidak dapat membangun beberapa proyek .NET 3.5 yang saya kerjakan.
Klark
7
Solusi modifikasi registri yang diusulkan memiliki efek samping buruk jika Anda melakukan multi-penargetan (yaitu menulis aplikasi .NET 2.0 di VS2010). Awas.
Todd Sprang
9
Perhatikan bahwa Microsoft sangat memperingatkan untuk tidak melakukan ini: "Meskipun dimungkinkan untuk memaksa PowerShell 2.0 untuk berjalan dengan .NET Framework 4.0 menggunakan berbagai mekanisme seperti membuat file konfigurasi untuk PowerShell atau mengedit registri, mekanisme ini tidak didukung dan dapat memiliki efek samping negatif pada fungsionalitas PowerShell lain seperti PowerShell remoting dan cmdlet dengan rakitan mode campuran. " connect.microsoft.com/PowerShell/feedback/details/525435/... Powershell 3.0 memiliki dukungan asli untuk .NET 4.0.
Timbo
238

Solusi terbaik yang saya temukan adalah di posting blog Menggunakan Versi yang lebih baru dari .NET dengan PowerShell . Ini memungkinkan powershell.exe dijalankan dengan .NET 4 rakitan.

Cukup modifikasi (atau buat) $pshome\powershell.exe.configsehingga mengandung yang berikut:

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

Catatan pengaturan tambahan yang cepat:

Lokasi dan file agak tergantung platform; namun akan memberi Anda intisari intinya tentang bagaimana membuat solusi itu bekerja untuk Anda.

  • Anda dapat menemukan lokasi PowerShell di komputer Anda dengan mengeksekusi cd $pshome di jendela Powershell (tidak berfungsi dari DOS prompt).
    • Path akan menjadi seperti (contoh) C:\Windows\System32\WindowsPowerShell\v1.0\
  • Nama file untuk meletakkan konfigurasi adalah: powershell.exe.configjika Anda PowerShell.exedieksekusi (buat file konfigurasi jika perlu).
    • Jika PowerShellISE.Exesedang berjalan maka Anda perlu membuat file konfigurasi pendampingnya sebagaiPowerShellISE.Exe.config
cmo999
sumber
23
Jelas cara yang tepat untuk melakukannya. Ini hanya mengubah perilaku Powershell, tidak semua aplikasi .NET lainnya di komputer Anda ...
Erik A. Brandstadmoen
4
Ini bekerja dengan baik tetapi mempengaruhi semua PowerShell Anda. Jika Anda ingin hanya beberapa fungsi, buat salinan folder PowerShell dan kemudian edit file di sana.
Matt
8
Saya menambahkan file seperti disebutkan di atas. Namun, saya tidak bisa lagi menjalankan PowerShell dengan file yang ada - saya mendapatkan kesalahan "Volume untuk file telah diubah secara eksternal sehingga file yang dibuka tidak lagi valid." Ada ide?
JoshL
13
@ JoshL - pada sistem 64 bit, saya telah menemukan .exe.config perlu masuk ke SysWOW64 \ WindowsPowershell (folder 32 bit), bahkan jika Anda mencoba menjalankan PowerShell 64 bit. Kalau tidak, Anda mendapatkan kesalahan 'diubah secara eksternal'.
Sam
4
The powershell.exe.config harus berada di dua tempat .... C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ dan C: \ Windows \ SysWOW64 \ WindowsPowerShell \ v1.0 \
Jonesome Reinstate Monica
28

Harap SANGAT hati-hati dengan menggunakan pendekatan kunci registri. Ini adalah kunci di seluruh mesin dan secara otomatis memigrasi SEMUA aplikasi ke .NET 4.0.

Banyak produk tidak berfungsi jika dimigrasi secara paksa dan ini merupakan alat uji dan bukan mekanisme kualitas produksi. Visual Studio 2008 dan 2010, MSBuild , turbotax, dan sejumlah situs web, SharePoint , dan sebagainya tidak boleh diotomatisasi.

Jika Anda perlu menggunakan PowerShell dengan 4.0, ini harus dilakukan berdasarkan per-aplikasi dengan file konfigurasi, Anda harus memeriksa dengan tim PowerShell pada rekomendasi yang tepat. Ini kemungkinan akan memecah beberapa perintah PowerShell yang ada.

Madhu Talluri
sumber
Poin yang sangat bagus tentang menggunakan kunci registri. Untungnya, aplikasi launcher dengan file config berfungsi dengan baik. Skrip kami terutama menggunakan perintah sistem file dan panggilan .NET langsung, dan kami belum menemukan masalah dengan perintah yang rusak. Karena .NET 4 sebagian besar kompatibel dengan .NET 2.0, saya tidak akan berpikir bahwa akan ada banyak perintah yang rusak (meskipun tidak ada salahnya untuk berhati-hati :).
Kaisar XLII
21

Jika Anda masih terjebak pada PowerShell v1.0 atau v2.0, berikut adalah variasi saya pada jawaban Jason Stangroome yang luar biasa.

Buat suatu powershell4.cmdtempat di jalur Anda dengan konten berikut:

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

Ini akan memungkinkan Anda untuk meluncurkan instance dari konsol PowerShell yang berjalan di bawah .NET 4.0.

Anda dapat melihat perbedaan pada sistem saya di mana saya memiliki PowerShell 2.0 dengan memeriksa output dari dua perintah berikut dijalankan dari 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
Tim Lewis
sumber
3
Sejauh ini, ini adalah jawaban terbaik karena ini merupakan perubahan yang sangat terlokalisasi dan tidak melakukan perubahan terus-menerus pada sistem. Barang bagus!
Sebastian
fantastis! Bisakah Anda membantu di sini? stackoverflow.com/questions/39801315/…
johny mengapa
@ Timimewis, mungkinkah mengirim banyak pernyataan ke instance ps4.cmd yang sama?
Johnny mengapa
@ johny mengapa, mengirim banyak pernyataan ke .cmd sama dengan mengirim banyak pernyataan ke .exe karena .cmd menggunakan% * untuk meneruskan semua parameternya ke .exe. Itu tidak membuat perbedaan namun karena Anda masih harus berhati-hati dengan bagaimana cmd.exe mem-parsing baris perintah ketika melewati parameter ke executable yang diluncurkannya. Saya akan melihat pertanyaan stack-overflow dan alamat spesifik Anda di sana.
Tim Lewis
Saya mencoba menggunakan teknik ini dalam kombinasi dengan parameter perintah baris -Versi docs.microsoft.com/en-us/powershell/scripting/core-powershell/... Sayangnya, itu tidak bekerja; versi terbaru saya dari PowerShell (5.1.17134.407), sebagaimana ditentukan dari $ PSVersionTable.PSVersion, diluncurkan sebagai gantinya.
eisenpony
17

Berikut adalah isi dari file konfigurasi yang saya gunakan untuk mendukung rakitan .NET 2.0 dan .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>

Juga, inilah versi sederhana dari kode yang kompatibel dengan PowerShell 1.0 yang saya gunakan untuk mengeksekusi skrip kami dari argumen baris perintah yang diteruskan:

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

Selain penanganan kesalahan dasar yang ditunjukkan di atas, kami juga menyuntikkan trappernyataan ke dalam skrip untuk menampilkan informasi diagnostik tambahan (mirip dengan fungsi Resolve-Error Jeffrey Snover ).

Kaisar XLII
sumber
10

Jawaban lain dari sebelum 2012, dan mereka fokus pada "peretasan" PowerShell 1.0 atau PowerShell 2.0 ke dalam penargetan versi yang lebih baru dari .NET Framework dan Common Language Runtime (CLR).

Namun, seperti yang telah ditulis dalam banyak komentar, sejak 2012 (ketika PowerShell 3.0 datang) solusi yang jauh lebih baik adalah menginstal versi terbaru PowerShell . Ini akan secara otomatis menargetkan CLR v4.0.30319. Ini berarti .NET 4.0, 4.5, 4.5.1, 4.5.2, atau 4.6 (diharapkan pada 2015) karena semua versi ini merupakan pengganti satu sama lain. Gunakan $PSVersionTableatau lihat Tentukan utas versi PowerShell yang terinstal jika Anda tidak yakin dengan versi PowerShell Anda.

Pada saat penulisan, versi terbaru PowerShell adalah 4.0, dan dapat diunduh dengan Windows Management Framework (tautan pencarian Google) .

Jeppe Stig Nielsen
sumber
2
Persyaratan sistem untuk Windows Management Framework 4.0 (mereka serupa untuk 3.0) adalah: Windows 7, Windows Embedded Standard 7, Windows Server 2008 R2, Windows Server 2012.
Peter Mortensen
9

Sebenarnya, Anda bisa menjalankan PowerShell menggunakan .NET 4 tanpa memengaruhi aplikasi .NET lainnya. Saya perlu melakukannya untuk menggunakan properti "Host" HttpWebRequest baru, namun mengubah "OnlyUseLatestCLR" memecah Fiddler karena itu tidak dapat digunakan dalam .NET 4.

Pengembang PowerShell jelas meramalkan ini terjadi, dan mereka menambahkan kunci registri untuk menentukan versi Kerangka apa yang harus digunakan. Satu masalah kecil adalah bahwa Anda perlu mengambil kepemilikan kunci registri sebelum mengubahnya, karena bahkan administrator tidak memiliki akses.

  • HKLM: \ Software \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (64 bit dan 32 bit)
  • HKLM: \ Software \ Wow6432Node \ Microsoft \ Powershell \ 1 \ PowerShellEngine \ RuntimeVersion (32 bit pada mesin 64 bit)

Ubah nilai kunci itu ke versi yang diperlukan. Perlu diingat bahwa beberapa snapins mungkin tidak lagi memuat kecuali mereka. NET 4 kompatibel (WASP adalah satu-satunya yang saya punya masalah dengan, tetapi saya tidak benar-benar menggunakannya). VMWare , SQL Server 2008 , PSCX, Active Directory (Microsoft dan Quest Software ) dan SCOM semuanya berfungsi dengan baik.

Justin Yancey
sumber
+1 Ini adalah alternatif yang sangat penting (dan lebih baik) daripada entri reg lainnya yang akan memengaruhi semua aplikasi .net, tetapi solusi ini hanya memengaruhi PowerShell.
Christian Mikkelsen
Setelah menerapkan "OnlyUseLatestCLR", Fiddler saya pecah dan beberapa skrip PowerShell tidak lagi berjalan karena tidak dapat menghubungi server tertentu. Saya secara manual mengubah nilai kembali ke 0 di regedt32, dan sekarang semuanya berfungsi lagi. Terima kasih!
Neville
Apa itu WASP, PSCX, dan SCOM (dalam konteks ini)?
Peter Mortensen
7

Jika Anda tidak ingin memodifikasi file registri atau app.config, cara alternatif adalah membuat aplikasi .NET 4 konsol sederhana yang meniru apa yang dilakukan PowerShell.exe dan meng-host PowerShell ConsoleShell.

Lihat Opsi 2 - Hosting sendiri Windows PowerShell

Pertama, tambahkan referensi ke System.Management.Automation dan Microsoft.PowerShell.ConsoleHost rakitan yang dapat ditemukan di bawah % programfiles% \ Assemblies Referensi \ Microsoft \ WindowsPowerShell \ v1.0

Kemudian gunakan kode berikut:

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
            );
        }
    }
}
Grant Holliday
sumber
6

Sama seperti opsi lain, rilis PoshConsole terbaru termasuk binari yang ditargetkan untuk .NET 4 RC (yang berfungsi dengan baik terhadap rilis RTM) tanpa konfigurasi apa pun.

Jaykul
sumber
1

Jalankan powershell.exe dengan COMPLUS_versionvariabel lingkungan diatur ke v4.0.30319. Misalnya, dari cmd.exe atau .bat-file:

set COMPLUS_version=v4.0.30319
powershell -file c:\scripts\test.ps1
vkrzv
sumber