Memilih paket PowerShell NuGet yang tepat untuk proyek .NET Anda

Bersama dengan pwsh paket yang dapat dieksekusi yang diterbitkan dengan setiap rilis PowerShell, tim PowerShell juga mempertahankan beberapa paket yang tersedia di NuGet. Paket ini memungkinkan penargetan PowerShell sebagai platform API di .NET.

Sebagai aplikasi .NET yang menyediakan API dan mengharapkan untuk memuat pustaka .NET yang menerapkan sendiri (modul biner), sangat penting bahwa PowerShell tersedia dalam bentuk paket NuGet.

Saat ini ada beberapa paket NuGet yang menyediakan beberapa representasi area permukaan POWERShell API. Paket mana yang akan digunakan dengan proyek tertentu yang belum selalu diperjelas. Artikel ini menjelaskan beberapa skenario umum untuk proyek .NET yang menargetkan PowerShell dan cara memilih paket NuGet yang tepat untuk ditargetkan untuk proyek .NET berorientasi PowerShell Anda.

Hosting vs referensi

Beberapa proyek .NET berusaha menulis kode untuk dimuat ke dalam runtime PowerShell yang sudah ada sebelumnya (seperti pwsh, , powershell.exeKonsol Terintegrasi PowerShell atau ISE), sementara yang lain ingin menjalankan PowerShell di aplikasi mereka sendiri.

  • Referensi adalah ketika proyek, biasanya modul, dimaksudkan untuk dimuat ke PowerShell. Ini harus dikompilasi terhadap API yang disediakan PowerShell untuk berinteraksi dengannya, tetapi implementasi PowerShell disediakan oleh proses PowerShell yang memuatnya. Untuk referensi, proyek dapat menggunakan rakitan referensi atau rakitan runtime aktual sebagai target kompilasi, tetapi harus memastikan bahwa proyek tersebut tidak menerbitkan salah satu dari ini dengan build-nya.
  • Hosting adalah ketika proyek membutuhkan implementasi PowerShell sendiri, biasanya karena ini adalah aplikasi mandiri yang perlu menjalankan PowerShell. Dalam hal ini, rakitan referensi murni tidak dapat digunakan. Sebaliknya, implementasi PowerShell konkret harus diandalkan. Karena implementasi PowerShell konkret harus digunakan, versi PowerShell tertentu harus dipilih untuk hosting; satu aplikasi host tidak dapat melakukan multi-target versi PowerShell.

Menerbitkan proyek yang menargetkan PowerShell sebagai referensi

Catatan

Kami menggunakan istilah penerbitan dalam artikel ini untuk merujuk ke menjalankan dotnet publish, yang menempatkan pustaka .NET ke dalam direktori dengan semua dependensinya, siap untuk penyebaran ke runtime tertentu.

Untuk mencegah dependensi proyek penerbitan yang hanya digunakan sebagai target referensi kompilasi, disarankan untuk mengatur atribut PrivateAssets :

<PackageReference Include="PowerShellStandard.Library" Version="5.1.0.0" PrivateAssets="all" />

Jika Anda lupa melakukan ini dan menggunakan perakitan referensi sebagai target Anda, Anda mungkin melihat masalah yang terkait dengan penggunaan implementasi default perakitan referensi alih-alih implementasi aktual. Ini mungkin berbentuk NullReferenceException, karena rakitan referensi sering meniru API implementasi hanya dengan mengembalikan null.

Jenis kunci proyek .NET yang menargetkan PowerShell

Meskipun pustaka atau aplikasi .NET apa pun dapat menyematkan PowerShell, ada beberapa skenario umum yang menggunakan API PowerShell:

  • Menerapkan modul biner PowerShell

    Modul biner PowerShell adalah pustaka .NET yang dimuat oleh PowerShell yang harus menerapkan API PowerShell seperti jenis PSCmdlet atau CmdletProvider untuk mengekspos cmdlet atau penyedia masing-masing. Karena dimuat, modul berusaha mengkompilasi terhadap referensi ke PowerShell tanpa menerbitkannya di build mereka. Modul juga umum untuk ingin mendukung beberapa versi dan platform PowerShell, idealnya dengan minimal overhead ruang disk, kompleksitas, atau implementasi berulang. Lihat about_Modules untuk informasi selengkapnya tentang modul.

  • Menerapkan Host PowerShell

    Host PowerShell menyediakan lapisan interaksi untuk runtime PowerShell. Ini adalah bentuk hosting tertentu, di mana PSHost diimplementasikan sebagai antarmuka pengguna baru ke PowerShell. Misalnya, PowerShell ConsoleHost menyediakan antarmuka pengguna terminal untuk PowerShell yang dapat dieksekusi, sementara Host Layanan Editor PowerShell dan Host ISE menyediakan antarmuka pengguna grafis sebagian yang terintegrasi editor di sekitar PowerShell. Meskipun dimungkinkan untuk memuat host ke proses PowerShell yang ada, jauh lebih umum bagi implementasi host untuk bertindak sebagai implementasi PowerShell mandiri yang mendistribusikan ulang mesin PowerShell.

  • Memanggil ke PowerShell dari aplikasi .NET lain

    Seperti halnya aplikasi apa pun, PowerShell dapat dipanggil sebagai sub-proses untuk menjalankan beban kerja. Namun, sebagai aplikasi .NET, dimungkinkan juga untuk memanggil PowerShell dalam proses untuk mendapatkan kembali objek .NET penuh untuk digunakan dalam aplikasi panggilan. Ini adalah bentuk hosting yang lebih umum, di mana aplikasi memegang implementasi PowerShell sendiri untuk penggunaan internal. Contohnya mungkin layanan atau daemon yang menjalankan PowerShell untuk mengelola status mesin atau aplikasi web yang menjalankan PowerShell berdasarkan permintaan untuk melakukan sesuatu seperti mengelola penyebaran cloud.

  • Unit yang menguji modul PowerShell dari .NET

    Meskipun modul dan pustaka lain yang dirancang untuk mengekspos fungsionalitas ke PowerShell harus diuji terutama dari PowerShell (kami merekomendasikan Pester), terkadang perlu untuk menyatukan API pengujian yang ditulis untuk modul PowerShell dari .NET. Situasi ini melibatkan kode modul yang mencoba menargetkan sejumlah versi PowerShell, sementara pengujian harus menjalankannya pada implementasi konkret tertentu.

Sekilas paket PowerShell NuGet

Dalam artikel ini, kita akan membahas paket NuGet berikut yang mengekspos API PowerShell:

  • PowerShellStandard.Library, rakitan referensi yang memungkinkan pembuatan satu rakitan yang dapat dimuat oleh beberapa runtime PowerShell.
  • Microsoft.PowerShell.SDK, cara untuk menargetkan dan menghosting ulang seluruh SDK PowerShell
  • Paket System.Management.Automation , runtime PowerShell inti dan implementasi mesin, yang dapat berguna dalam implementasi minimal yang dihosting dan untuk skenario penargetan khusus versi.
  • Rakitan referensi Windows PowerShell, cara untuk menargetkan dan secara efektif menghosting ulang Windows PowerShell (PowerShell versi 5.1 ke bawah).

Catatan

Paket PowerShell NuGet sama sekali bukan paket pustaka .NET, tetapi sebaliknya menyediakan implementasi alat global dotnet PowerShell. Ini tidak boleh digunakan oleh proyek apa pun, karena hanya menyediakan executable.

PowerShellStandard.Library

Pustaka PowerShell Standard adalah rakitan referensi yang menangkap persimpangan API PowerShell versi 7, 6, dan 5.1. Ini menyediakan permukaan API yang diperiksa waktu kompilasi untuk mengkompilasi kode .NET, memungkinkan proyek .NET menargetkan PowerShell versi 7, 6, dan 5.1 tanpa berisiko memanggil API yang tidak akan berada di sana.

PowerShell Standard ditujukan untuk menulis modul PowerShell, atau kode lain hanya dimaksudkan untuk dijalankan setelah memuatnya ke dalam proses PowerShell. Karena ini adalah rakitan referensi, PowerShell Standard tidak berisi implementasi itu sendiri, jadi tidak menyediakan fungsionalitas untuk aplikasi mandiri.

Menggunakan PowerShell Standard dengan runtime .NET yang berbeda

PowerShell Standard menargetkan runtime target .NET Standard 2.0, yang merupakan runtime fasad yang dirancang untuk menyediakan area permukaan umum yang dibagikan oleh .NET Framework dan .NET Core. Ini memungkinkan penargetan satu runtime untuk menghasilkan satu assembly yang akan berfungsi dengan beberapa versi PowerShell, tetapi memiliki konsekuensi berikut:

  • PowerShell yang memuat modul atau pustaka harus menjalankan minimal .NET 4.6.1; .NET 4.6 dan .NET 4.5.2 tidak mendukung .NET Standard. Perhatikan bahwa versi Windows PowerShell yang lebih baru tidak berarti versi .NET Framework yang lebih baru; Windows PowerShell 5.1 dapat berjalan pada .NET 4.5.2.
  • Untuk bekerja dengan PowerShell yang menjalankan .NET Framework 4.7.1 atau di bawahnya, implementasi .NET 4.6.1 NETStandard.Library diperlukan untuk menyediakan netstandard.dll dan rakitan shim lainnya di versi .NET Framework yang lebih lama.

PowerShell 6+ menyediakan rakitan shim sendiri untuk penerusan jenis dari .NET Framework 4.6.1 (dan lebih tinggi) ke .NET Core. Ini berarti bahwa selama modul hanya menggunakan API yang ada di .NET Core, PowerShell 6+ dapat memuat dan menjalankannya ketika telah dibangun untuk .NET Framework 4.6.1 (net461target runtime).

Ini berarti bahwa modul biner yang menggunakan PowerShell Standard untuk menargetkan beberapa versi PowerShell dengan satu DLL yang diterbitkan memiliki dua opsi:

  1. Menerbitkan rakitan yang dibuat untuk net461 runtime target. Alur ini mencakup:

    • Menerbitkan proyek untuk net461 runtime
    • Kompilasi juga terhadap netstandard2.0 runtime (tanpa menggunakan output build-nya) untuk memastikan bahwa semua API yang digunakan juga ada di .NET Core.
  2. Menerbitkan build rakitan untuk netstandard2.0 runtime target. Hal ini membutuhkan:

    • Menerbitkan proyek untuk netstandard2.0 runtime
    • net461 Mengambil dependensi NETStandard.Library dan menyalinnya ke lokasi penerbitan perakitan proyek sehingga perakitan diteruskan jenis diperbaiki di .NET Framework.

Untuk membangun modul atau pustaka PowerShell yang menargetkan versi .NET Framework yang lebih lama, lebih baik menargetkan beberapa runtime .NET. Ini akan menerbitkan rakitan untuk setiap runtime target, dan rakitan yang benar perlu dimuat pada waktu pemuatan modul (misalnya dengan psm1 kecil sebagai modul akar).

Menguji proyek PowerShell Standard di .NET

Dalam hal menguji modul Anda di runner pengujian .NET seperti xUnit, ingatlah bahwa pemeriksaan waktu kompilasi hanya dapat berlangsung sejauh ini. Anda harus menguji modul Anda terhadap platform PowerShell yang relevan.

Untuk menguji API yang dibangun terhadap PowerShell Standard di .NET, Anda harus menambahkan Microsoft.Powershell.SDK sebagai dependensi pengujian dengan .NET Core (dengan versi yang diatur agar sesuai dengan versi PowerShell yang diinginkan), dan rakitan referensi Windows PowerShell yang sesuai dengan .NET Framework.

Untuk informasi selengkapnya tentang PowerShell Standard dan menggunakannya untuk menulis modul biner yang berfungsi di beberapa versi PowerShell, lihat posting blog ini. Lihat juga repositori PowerShell Standard di GitHub.

Microsoft.PowerShell.SDK

Microsoft.PowerShell.SDK adalah paket meta yang menggabungkan semua komponen PowerShell SDK ke dalam satu paket NuGet. Aplikasi .NET mandiri dapat menggunakan Microsoft.PowerShell.SDK untuk menjalankan fungsionalitas PowerShell arbitrer tanpa bergantung pada penginstalan atau pustaka PowerShell eksternal apa pun.

Catatan

PowerShell SDK hanya mengacu pada semua paket komponen yang membentuk PowerShell, dan yang dapat digunakan untuk pengembangan .NET dengan PowerShell.

Versi tertentu Microsoft.Powershell.SDK berisi implementasi konkret dari versi aplikasi PowerShell yang sama; versi 7.0 berisi implementasi PowerShell 7.0 dan menjalankan perintah atau skrip dengannya sebagian besar akan bereaksi seperti menjalankannya di PowerShell 7.0.

Menjalankan perintah PowerShell dari SDK sebagian besar, tetapi tidak sepenuhnya, sama seperti menjalankannya dari pwsh. Misalnya, Start-Job saat ini bergantung pada executable yang pwsh tersedia, sehingga tidak akan berfungsi secara Microsoft.Powershell.SDK default.

Penargetan Microsoft.Powershell.SDK dari aplikasi .NET memungkinkan Anda untuk berintegrasi dengan semua rakitan implementasi PowerShell, seperti System.Management.Automation, Microsoft.PowerShell.Management, dan rakitan modul lainnya.

Menerbitkan penargetan Microsoft.Powershell.SDK aplikasi akan mencakup semua rakitan ini, dan dependensi apa pun yang diperlukan PowerShell. Ini juga akan mencakup aset lain yang diperlukan PowerShell dalam build-nya, seperti manifes modul untuk Microsoft.PowerShell.* modul dan direktori yang ref diperlukan oleh Add-Type.

Mengingat kelengkapan Microsoft.Powershell.SDK, ini paling cocok untuk:

  • Implementasi host PowerShell.
  • Pengujian xUnit pustaka yang menargetkan rakitan referensi PowerShell.
  • Memanggil PowerShell dalam proses dari aplikasi .NET.

Microsoft.PowerShell.SDK juga dapat digunakan sebagai target referensi ketika proyek .NET dimaksudkan untuk digunakan sebagai modul atau dimuat oleh PowerShell, tetapi tergantung pada API hanya ada dalam versi PowerShell tertentu. Perhatikan bahwa rakitan yang diterbitkan terhadap versi Microsoft.PowerShell.SDK tertentu hanya akan aman untuk dimuat dan digunakan dalam versi PowerShell tersebut. Untuk menargetkan beberapa versi PowerShell dengan API tertentu, diperlukan beberapa build, masing-masing menargetkan versi mereka sendiri.Microsoft.Powershell.SDK

Catatan

PowerShell SDK hanya tersedia untuk PowerShell versi 6 ke atas. Untuk menyediakan fungsionalitas yang setara dengan Windows PowerShell, gunakan rakitan referensi Windows PowerShell yang dijelaskan di bawah ini.

System.Management.Automation

Paket System.Management.Automation ini adalah inti dari PowerShell SDK. Ini ada di NuGet, terutama, sebagai aset untuk Microsoft.Powershell.SDK menarik masuk. Namun, ini juga dapat digunakan langsung sebagai paket untuk skenario hosting yang lebih kecil dan modul penargetan versi.

Secara khusus, System.Management.Automation paket mungkin penyedia fungsionalitas PowerShell yang lebih disukai saat:

  • Anda hanya ingin menggunakan fungsionalitas bahasa PowerShell (di System.Management.Automation.Language namespace) seperti parser PowerShell, AST, dan API pengunjung AST (misalnya untuk analisis statis PowerShell).
  • Anda hanya ingin menjalankan perintah tertentu dari Microsoft.PowerShell.Core modul dan dapat menjalankannya dalam status sesi yang dibuat dengan metode pabrik CreateDefault2 .

Selain itu, System.Management.Automation adalah rakitan referensi yang berguna ketika:

  • Anda ingin menargetkan API yang hanya ada dalam versi PowerShell tertentu
  • Anda tidak akan bergantung pada jenis yang terjadi di luar perakitan System.Management.Automation (misalnya, jenis yang diekspor oleh cmdlet dalam Microsoft.PowerShell.* modul).

Windows PowerShell rakitan referensi

Untuk PowerShell versi 5.1 dan yang lebih lama (Windows PowerShell), tidak ada SDK untuk menyediakan implementasi PowerShell, karena implementasi Windows PowerShell adalah bagian dari Windows.

Sebaliknya, rakitan referensi Windows PowerShell menyediakan target referensi dan cara untuk menghosting ulang Windows PowerShell, bertindak sama seperti yang dilakukan PowerShell SDK untuk versi 6 ke atas.

Daripada dibingkai oleh versi, rakitan referensi Windows PowerShell memiliki paket yang berbeda untuk setiap versi Windows PowerShell:

Informasi tentang cara menggunakan rakitan referensi Windows PowerShell dapat ditemukan di SDK Windows PowerShell.

Contoh dunia nyata menggunakan paket NuGet ini

Proyek alat PowerShell yang berbeda menargetkan paket PowerShell NuGet yang berbeda tergantung pada kebutuhannya. Tercantum di sini adalah beberapa contoh penting.

PSReadLine

PSReadLine, modul PowerShell yang memberikan banyak pengalaman konsol PowerShell yang kaya, menargetkan PowerShell Standard sebagai dependensi daripada versi PowerShell tertentu, dan menargetkan net461 runtime .NET dalam csproj-nya.

PowerShell 6+ memasok rakitan shim sendiri yang memungkinkan DLL yang menargetkan net461 runtime untuk "hanya berfungsi" saat dimuat (dengan mengalihkan pengikatan ke .NET Framework mscorlib.dll ke rakitan .NET Core yang relevan).

Ini menyederhanakan tata letak dan pengiriman modul PSReadLine secara signifikan, karena PowerShell Standard memastikan satu-satunya API yang digunakan akan ada di PowerShell 5.1 dan PowerShell 6+, sekaligus memungkinkan modul untuk dikirim hanya dengan satu rakitan.

Target .NET 4.6.1 berarti bahwa Windows PowerShell berjalan pada .NET 4.5.2 dan .NET 4.6 tidak didukung sekalipun.

Layanan Editor PowerShell

PowerShell Editor Services (PSES) adalah backend untuk ekstensi PowerShell untuk Visual Studio Code, dan sebenarnya merupakan bentuk modul PowerShell yang dimuat oleh PowerShell yang dapat dieksekusi dan kemudian mengambil alih proses tersebut untuk menghosting ulang PowerShell dengan sendirinya sambil menyediakan fitur Protokol Layanan Bahasa dan Adaptor Debug.

PSES menyediakan target implementasi konkret untuk netcoreapp2.1 menargetkan PowerShell 6+ (karena runtime PowerShell 7 netcoreapp3.1 kompatibel mundur) dan net461 untuk menargetkan Windows PowerShell 5.1, tetapi berisi sebagian besar logikanya dalam rakitan kedua yang menargetkan netstandard2.0 dan PowerShell Standard. Ini memungkinkannya untuk menarik dependensi yang diperlukan untuk platform .NET Core dan .NET Framework, sambil tetap menyederhanakan sebagian besar basis kode di balik abstraksi seragam.

Karena dibangun terhadap PowerShell Standard, PSES memerlukan implementasi runtime PowerShell agar dapat diuji dengan benar. Untuk melakukan ini, pengujian xUnit PSES menarik Microsoft.PowerShell.SDK dan Microsoft.PowerShell.5.ReferenceAssemblies untuk menyediakan implementasi PowerShell di lingkungan pengujian.

Seperti halnya PSReadLine, PSES tidak dapat mendukung .NET 4.6 ke bawah, tetapi melakukan pemeriksaan pada runtime sebelum memanggil salah satu API yang dapat menyebabkan crash pada runtime .NET Framework yang lebih rendah.

PSScriptAnalyzer

PSScriptAnalyzer, linter untuk PowerShell, harus menargetkan elemen sintaksis yang hanya diperkenalkan dalam versi PowerShell tertentu. Karena pengenalan elemen-elemen sintaksis ini dicapai dengan menerapkan AstVisitor2, tidak mungkin menggunakan PowerShellStandard dan juga menerapkan metode pengunjung AST untuk sintaks PowerShell yang lebih baru.

Sebaliknya, PSScriptAnalyzer menargetkan setiap versi PowerShell sebagai konfigurasi build, dan menghasilkan DLL terpisah untuk masing-masing versi tersebut. Ini meningkatkan ukuran dan kompleksitas build, tetapi memungkinkan:

  • Penargetan API khusus versi
  • Fungsionalitas khusus versi yang akan diimplementasikan pada dasarnya tanpa biaya runtime
  • Total dukungan untuk Windows PowerShell hingga .NET Framework 4.5.2

Ringkasan

Dalam artikel ini, kami telah mencantumkan dan membahas paket NuGet yang tersedia untuk ditargetkan saat menerapkan proyek .NET yang menggunakan PowerShell, dan alasan yang mungkin Anda miliki untuk menggunakan satu sama lain.

Jika Anda telah melompat ke ringkasan, beberapa rekomendasi yang luas adalah:

  • Modul PowerShell harus dikompilasi terhadap PowerShell Standard jika hanya memerlukan API yang umum untuk versi PowerShell yang berbeda.
  • Host dan aplikasi PowerShell yang perlu menjalankan PowerShell secara internal harus menargetkan PowerShell SDK untuk PowerShell 6+ atau rakitan referensi Windows PowerShell yang relevan untuk Windows PowerShell.
  • Modul PowerShell yang memerlukan API khusus versi harus menargetkan rakitan referensi PowerShell SDK atau Windows PowerShell untuk versi PowerShell yang diperlukan, menggunakannya sebagai rakitan referensi (yaitu, tidak menerbitkan dependensi PowerShell).