Memilih paket PowerShell NuGet yang tepat untuk proyek .NET Anda

Bersama dengan paket pwsh 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 mengimplementasikan sendiri (modul biner), sangat penting bahwa PowerShell tersedia dalam bentuk paket NuGet.

Saat ini ada beberapa paket NuGet yang menyediakan beberapa representasi area permukaan API PowerShell. Paket mana yang akan digunakan dengan proyek tertentu tidak selalu jelas. 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 digunakan saat proyek, biasanya modul, dirancang untuk dimuat ke dalam PowerShell. Anda harus mengkompilasi modul terhadap API yang disediakan PowerShell untuk berinteraksi dengannya. Tetapi PowerShell menyediakan implementasi dengan memuatnya. Proyek dapat menggunakan rakitan referensi atau rakitan runtime aktual sebagai target kompilasi, tetapi harus memastikan bahwa proyek tersebut tidak menerbitkan salah satu rakitan ini dengan buildnya.
  • 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 menargetkan beberapa versi PowerShell sekaligus.

Menerbitkan proyek yang menargetkan PowerShell sebagai referensi

Nota

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

Atur atribut PrivateAssets untuk mencegah dependensi proyek penerbitan yang hanya digunakan sebagai target referensi kompilasi:

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

Jika Anda tidak mengatur atribut ini dan menggunakan assembly referensi sebagai target Anda, Anda dapat mengalami masalah terkait dengan penggunaan implementasi bawaan dari assembly referensi, daripada implementasi yang sebenarnya. Misalnya, Anda dapat menerima NullReferenceException, karena rakitan referensi sering meniru API implementasi dengan mengembalikan null.

Jenis utama 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 tipe PSCmdlet atau CmdletProvider untuk memaparkan cmdlet atau penyedia masing-masing. Karena dimuat, modul berusaha mengkompilasi terhadap referensi ke PowerShell tanpa menerbitkannya dalam build mereka. Adalah umum bagi modul untuk mendukung beberapa versi dan platform PowerShell, idealnya dengan overhead seminimal mungkin pada ruang disk, kompleksitas, atau implementasi berulang. Untuk informasi selengkapnya, lihat about_Modules.

  • 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 program PowerShell, sementara Host Layanan Editor PowerShell dan Host ISE menyediakan antarmuka pengguna grafis parsial yang terintegrasi dengan editor untuk 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 PowerShell dari aplikasi .NET lain

    Seperti halnya aplikasi apa pun, Anda dapat memanggil PowerShell 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 yang lebih umum dari hosting, di mana aplikasi memegang implementasi PowerShell sendiri untuk penggunaan internal. Misalnya, Anda dapat membuat layanan atau daemon yang menjalankan PowerShell untuk mengelola status mesin, atau aplikasi web yang menjalankan PowerShell berdasarkan permintaan untuk melakukan beberapa pekerjaan seperti mengelola penyebaran cloud.

  • Unit yang menguji modul PowerShell dari .NET

    Biasanya, modul dan pustaka lain yang dirancang untuk mengekspos fungsionalitas ke PowerShell harus diuji dari PowerShell. Namun, terkadang perlu untuk menyatukan API pengujian yang ditulis untuk modul PowerShell dari .NET.

Paket PowerShell NuGet Sekilas Pandang

Paket NuGet berikut mengekspos API PowerShell:

  • PowerShellStandard.Library, rakitan referensi yang memungkinkan pembuatan satu rakitan yang dapat Anda muat dalam beberapa runtime PowerShell.
  • Microsoft.PowerShell.SDK, cara untuk menargetkan dan menghosting ulang seluruh PowerShell SDK
  • Paket System.Management.Automation, runtime dan implementasi mesin PowerShell inti, yang dapat berguna dalam implementasi yang dihosting minimal 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).

Nota

Paket PowerShell NuGet sama sekali bukan paket pustaka .NET, tetapi sebaliknya menyediakan implementasi alat global Dotnet PowerShell. Jangan gunakan paket ini dalam proyek apa pun, karena hanya menyediakan executable.

PowerShellStandard.Library

Pustaka PowerShell Standard adalah rakitan referensi yang menangkap persimpangan API PowerShell v7 dan v5.1. Ini menyediakan antarmuka API yang diperiksa saat kompilasi untuk menguji kode .NET, memungkinkan proyek .NET untuk menargetkan PowerShell versi v7 dan v5.1 tanpa berisiko memanggil API yang tidak tersedia.

Gunakan PowerShell Standard 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, sehingga 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 bersama untuk .NET Framework dan .NET Core. Ini memungkinkan Anda untuk menargetkan satu runtime untuk menghasilkan satu rakitan yang berfungsi dengan beberapa versi PowerShell, tetapi memiliki konsekuensi berikut:

  • Instans 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.

    Nota

    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 dalam versi .NET Framework yang lebih lama.

PowerShell 6 (dan versi yang lebih baru) menyediakan shim assembly-nya sendiri untuk penerusan tipe dari .NET Framework 4.6.1 (dan versi yang lebih baru) ke .NET Core. Selama modul hanya menggunakan API yang ada di .NET Core, PowerShell 6 (dan yang lebih tinggi) dapat memuat dan menjalankannya jika dibangun untuk .NET Framework 4.6.1 ( net461 target runtime).

Modul biner menggunakan PowerShell Standard untuk menargetkan beberapa versi PowerShell dengan satu DLL yang diterbitkan memiliki dua opsi:

  1. Menerbitkan rakitan yang dibangun untuk target runtime net461 melibatkan:

    • Menerbitkan proyek untuk runtime net461
    • Juga melakukan kompilasi terhadap runtime netstandard2.0 (tanpa menggunakan hasil build) untuk memastikan bahwa semua API yang digunakan juga ada di .NET Core.
  2. Menerbitkan rakitan program untuk target runtime netstandard2.0 memerlukan:

    • Menerbitkan proyek untuk runtime netstandard2.0
    • Mengambil dependensi net461 NETStandard.Library dan menyalinnya ke lokasi publikasi rakitan proyek sehingga rakitan tersebut diteruskan dengan tipe yang benar dalam .NET Framework.

Untuk membangun modul atau pustaka PowerShell yang menargetkan versi .NET Framework yang lebih lama, Anda mungkin lebih suka menargetkan beberapa runtime .NET. Melakukannya menerbitkan rakitan untuk setiap runtime target. Rakitan yang benar harus dimuat pada waktu pemuatan modul, misalnya dengan file kecil .psm1 sebagai modul akar.

Menguji proyek PowerShell Standard di .NET

Saat Anda menguji modul di .NET dengan runner pengujian 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 instalasi atau pustaka PowerShell eksternal apa pun.

Nota

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. Perintah atau skrip bereaksi seperti menjalankannya di PowerShell 7.0. Namun, menjalankan perintah PowerShell dari SDK tidak sama dengan menjalankannya dari pwsh. Misalnya, Start-Job bergantung pada executable pwsh yang tersedia, sehingga tidak berfungsi secara default dengan Microsoft.PowerShell.SDK.

Menargetkan 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 aplikasi yang menargetkan Microsoft.PowerShell.SDK mencakup semua komponen ini dan dependensi yang dibutuhkan oleh PowerShell. Ini juga mencakup aset lain yang diperlukan PowerShell dalam build-nya, seperti manifes modul untuk Microsoft.PowerShell.* modul dan direktori yang diperlukan oleh Add-Type.

Microsoft.PowerShell.SDK paling cocok untuk:

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

Anda dapat menggunakan Microsoft.PowerShell.SDK sebagai target referensi untuk proyek .NET untuk membuat modul atau rakitan PowerShell yang dimuat oleh PowerShell yang bergantung pada API hanya ada di versi PowerShell tertentu. Rakitan yang diterbitkan untuk versi Microsoft.PowerShell.SDK tertentu hanya aman untuk dimuat dan digunakan dalam versi PowerShell tersebut. Untuk menargetkan beberapa versi PowerShell dengan API tertentu, diperlukan beberapa kompilasi, masing-masing menargetkan versi Microsoft.PowerShell.SDKtersendiri.

Nota

PowerShell SDK hanya tersedia untuk PowerShell v6 dan yang lebih tinggi. Untuk menyediakan fungsionalitas yang setara dengan Windows PowerShell, gunakan rakitan referensi Windows PowerShell yang dijelaskan nanti di artikel ini.

System.Management.Automation

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

Secara khusus, paket System.Management.Automation adalah yang disukai ketika:

  • Anda hanya ingin menggunakan fungsionalitas bahasa PowerShell dari System.Management.Automation.Language namespace, seperti pengurai PowerShell, AST, dan API pengunjung AST.
  • Anda hanya ingin menjalankan perintah tertentu dari modul Microsoft.PowerShell.Core dan dapat menjalankannya dalam status sesi yang dibuat dengan metode CreateDefault2 factory.

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

  • Anda ingin menargetkan API yang hanya ada dalam versi PowerShell tertentu
  • Anda tidak bergantung pada tipe yang terjadi di luar assembly System.Management.Automation, seperti tipe yang diekspor oleh Microsoft.PowerShell.* modul cmdlet.

Kumpulan referensi Windows PowerShell

Untuk Windows PowerShell versi 5.1 dan yang lebih lama, tidak ada SDK untuk menyediakan implementasi PowerShell, karena implementasi Windows PowerShell adalah bagian dari Windows. Sebagai gantinya, rakitan referensi Windows PowerShell menyediakan target referensi dan cara untuk menghosting ulang Windows PowerShell, bertindak sama seperti yang dilakukan PowerShell SDK untuk versi 6 dan yang lebih tinggi. Rakitan referensi Windows PowerShell memiliki paket yang berbeda untuk setiap versi Windows PowerShell:

  • PowerShell 5.1
  • PowerShell 4
  • PowerShell 3

Anda dapat menemukan informasi tentang cara menggunakan rakitan referensi Windows PowerShell di Windows PowerShell SDK.

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 menyediakan banyak pengalaman konsol PowerShell yang kaya, menargetkan PowerShell Standard sebagai dependensi, bukan versi PowerShell tertentu, dan menargetkan runtime .NET net461 dalam csproj.

PowerShell v6 (dan versi yang lebih tinggi) menyediakan rakitan shimnya sendiri yang memungkinkan DLL yang menargetkan runtime net461 berfungsi dengan lancar ketika dimuat. Shim ini menyederhanakan distribusi dan penataan modul PSReadLine. PowerShell Standard memastikan bahwa modul hanya menggunakan API yang tersedia di Windows PowerShell 5.1 dan PowerShell 6 (dan yang lebih tinggi), yang memungkinkan modul untuk dikirim hanya dengan satu rakitan.

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

Layanan Editor PowerShell

PowerShell Editor Services (PSES) adalah backend untuk ekstensi PowerShell untuk Visual Studio Code. Modul PowerShell ini dimuat oleh PowerShell dan kemudian mengambil alih proses tersebut untuk menghosting ulang PowerShell dalam dirinya sendiri, sekaligus menyediakan fitur Protokol Layanan Bahasa dan Adaptor Debug.

PSES menyediakan target implementasi konkret untuk netcoreapp2.1 guna memfokuskan pada PowerShell 6+ (karena runtime netcoreapp3.1 pada PowerShell 7 kompatibel secara mundur) dan net461 untuk menargetkan Windows PowerShell 5.1, tetapi sebagian besar logiknya terdapat dalam rakitan kedua yang menargetkan netstandard2.0 dan PowerShell Standard. Desain 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 PSES menargetkan PowerShell Standard, diperlukan implementasi runtime untuk diuji dengan benar. Untuk melakukan ini, pengujian xUnit PSES menggunakan Microsoft.PowerShell.SDK dan Microsoft.PowerShell.5.ReferenceAssemblies untuk menyediakan implementasi PowerShell di lingkungan pengujian.

Karena PSES tidak dapat mendukung .NET 4.6 dan yang lebih lama, PSES 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 untuk menggunakan PowerShellStandard serta menerapkan metode pengunjung AST untuk sintaks PowerShell yang lebih baru.

Sebagai gantinya, PSScriptAnalyzer menargetkan setiap versi PowerShell sebagai konfigurasi build dan menghasilkan DLL terpisah untuk setiap versi. Ini menambah ukuran dan kompleksitas build, tetapi memungkinkan:

  • Penargetan API khusus versi
  • Fungsi khusus versi yang akan diimplementasikan tanpa biaya runtime yang signifikan
  • Dukungan penuh untuk Windows PowerShell yang berjalan pada .NET Framework 4.5.2 dan yang lebih tinggi

Ringkasan

Artikel ini mencantumkan dan membahas paket NuGet yang dapat Anda targetkan dan alasan untuk menggunakan masing-masing paket. Rekomendasi umumnya adalah:

  • Modul PowerShell harus dikompilasi terhadap PowerShell Standard jika hanya memerlukan API-API yang sering digunakan dalam berbagai versi PowerShell.
  • PowerShell host dan aplikasi yang perlu menjalankan PowerShell secara internal harus menarget:
    • PowerShell SDK untuk PowerShell v6 dan yang lebih tinggi
    • 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. Gunakan sebagai rakitan referensi sehingga Anda tidak menerbitkan dependensi PowerShell.