Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Nedávno jsem měl nápad na modul, který jsem chtěl implementovat jako binární modul. Ještě jsem žádný nevytvořil pomocí standardní knihovny PowerShellu, takže se to zdálo jako dobrá příležitost. Použil jsem průvodce Vytvoření binárního modulu pro různé platformy k vytvoření tohoto modulu bez jakýchkoli překážek. Projdeme stejným procesem a přidám k tomu trochu dalšího komentáře během toho.
Poznámka
původní verze tohoto článku se objevila na blogu napsaného @KevinMarquette. Tým PowerShellu děkujeme Kevinovi za sdílení tohoto obsahu s námi. Prosím, podívejte se na jeho blog na PowerShellExplained.com.
Co je standardní knihovna PowerShellu?
Standardní knihovna PowerShellu umožňuje vytvářet moduly pro různé platformy, které fungují v PowerShellu i v prostředí Windows PowerShell 5.1.
Proč binární moduly?
Při psaní modulu v jazyce C# se vzdáváte snadného přístupu k cmdletům a funkcím PowerShellu. Pokud ale vytváříte modul, který nezávisí na mnoha dalších příkazech PowerShellu, může být přínos výkonu významný. PowerShell byl optimalizovaný pro správce, ne pro počítač. Přepnutím na C# se zbavíte režie přidané prostředím PowerShell.
Máme například kritický proces, který hodně pracuje s JSON a hashtables. Optimalizovali jsme PowerShell tak, jak jsme mohli, ale dokončení procesu trvá 12 minut. Modul už obsahoval hodně powershellového stylu jazyka C#. Díky tomu je převod na binární modul čistý a jednoduchý. Převodem na binární modul jsme zkrátili dobu procesu z více než 12 minut na méně než čtyři minuty.
Hybridní moduly
Binární rutiny můžete kombinovat s pokročilými funkcemi PowerShellu. Všechno, co víte o skriptových modulech, platí stejným způsobem. Prázdný soubor psm1 je zahrnutý, abyste mohli později přidat další funkce PowerShellu.
Téměř všechny zkompilované rutiny, které jsem vytvořili, začaly jako funkce PowerShellu jako první. Všechny naše binární moduly jsou skutečně hybridní moduly.
Vytváření skriptů
Nechal jsem tady jednoduchý skript sestavení. Obvykle používám velký Invoke-Build skript jako součást řetězce CI/CD. Dělá více magie, jako je spouštění testů Pester, spouštění PSScriptAnalyzer, správa verzí a publikování do PSGallery. Jakmile jsem začal používat skript sestavení pro moduly, byl jsem schopen najít spoustu věcí, které do něj přidat.
Plánování modulu
Plánem pro tento modul je vytvořit src složku pro kód jazyka C# a strukturovat zbytek jako pro modul skriptu. To zahrnuje použití skriptu sestavení ke kompilaci všeho do Output složky. Struktura složek vypadá takto:
MyModule
├───src
├───Output
│ └───MyModule
├───MyModule
│ ├───Data
│ ├───Private
│ └───Public
└───Tests
Začínáme
Nejprve potřebuji vytvořit složku a vytvořit úložiště Git. Používám $module jako zástupný symbol pro název modulu. V případě potřeby byste měli tyto příklady snadněji použít.
$module = 'MyModule'
New-Item -Path $module -Type Directory
Set-Location $module
git init
Potom vytvořte složky na kořenové úrovni.
New-Item -Path 'src' -Type Directory
New-Item -Path 'Output' -Type Directory
New-Item -Path 'Tests' -Type Directory
New-Item -Path $module -Type Directory
Nastavení binárního modulu
Tento článek se zaměřuje na binární modul, takže začneme. Tato část čerpá příklady z průvodce Vytvoření binárního modulu pro různé platformy. Pokud potřebujete další podrobnosti nebo máte nějaké problémy, projděte si tuto příručku.
První věc, kterou chceme udělat, je zkontrolovat verzi dotnet core SDK, kterou jsme nainstalovali. Používám verzi 2.1.4, ale před pokračováním byste měli mít verzi 2.0.0 nebo novější.
PS> dotnet --version
2.1.4
Pracujem mimo složku src pro tuto část.
Set-Location 'src'
Pomocí příkazu dotnet vytvořte novou knihovnu tříd.
dotnet new classlib --name $module
Tím se projekt knihovny vytvořil v podsložce, ale nechci tuto další úroveň vnoření. Tyto soubory přesunu o úroveň výš.
Move-Item -Path .\$module\* -Destination .\
Remove-Item $module -Recurse
Nastavte verzi sady .NET Core SDK pro projekt. Mám sadu SDK 2.1, takže specifikuji 2.1.0.
Pokud používáte sadu SDK 2.0, použijte 2.0.0.
dotnet new globaljson --sdk-version 2.1.0
Do projektu přidejte balíček NuGet standardní knihovny PowerShellu . Ujistěte se, že používáte nejnovější verzi dostupnou pro požadovanou úroveň kompatibility. Ve výchozím nastavení bych měl nejnovější verzi, ale nemyslím si, že tento modul využívá žádné funkce novější než PowerShell 3.0.
dotnet add package PowerShellStandard.Library --version 7.0.0-preview.1
Měli bychom mít složku src, která vypadá takto:
PS> Get-ChildItem
Directory: \MyModule\src
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/14/2018 9:51 PM obj
-a---- 7/14/2018 9:51 PM 86 Class1.cs
-a---- 7/14/2018 10:03 PM 259 MyModule.csproj
-a---- 7/14/2018 10:05 PM 45 global.json
Teď jsme připraveni do projektu přidat vlastní kód.
Sestavení binárního příkazu cmdlet
Potřebujeme aktualizovat src\Class1.cs, aby obsahoval tento úvodní příkaz:
using System;
using System.Management.Automation;
namespace MyModule
{
[Cmdlet( VerbsDiagnostic.Resolve , "MyCmdlet")]
public class ResolveMyCmdletCommand : PSCmdlet
{
[Parameter(Position=0)]
public Object InputObject { get; set; }
protected override void EndProcessing()
{
this.WriteObject(this.InputObject);
base.EndProcessing();
}
}
}
Přejmenujte soubor tak, aby odpovídal názvu třídy.
Rename-Item .\Class1.cs .\ResolveMyCmdletCommand.cs
Pak můžeme vytvořit náš modul.
PS> dotnet build
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 18.19 ms for C:\workspace\MyModule\src\MyModule.csproj.
MyModule -> C:\workspace\MyModule\src\bin\Debug\netstandard2.0\MyModule.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.19
Můžeme zavolat Import-Module na novou knihovnu DLL a načíst nový cmdlet.
PS> Import-Module .\bin\Debug\netstandard2.0\$module.dll
PS> Get-Command -Module $module
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Resolve-MyCmdlet 1.0.0.0 MyModule
Pokud se import ve vašem systému nezdaří, zkuste aktualizovat .NET na verzi 4.7.1 nebo novější. Průvodce Vytvoření binárního modulu pro různé platformy obsahuje další podrobnosti o podpoře a kompatibilitě rozhraní .NET pro starší verze .NET.
Manifest modulu
Je skvělé, že můžeme importovat knihovnu DLL a mít funkční modul. Chci s ním dál pokračovat a vytvořit manifest modulu. Potřebujeme manifest, pokud budeme chtít publikovat do PSGallery později.
V kořenovém adresáři projektu můžeme tento příkaz spustit a vytvořit manifest modulu, který potřebujeme.
$manifestSplat = @{
Path = ".\$module\$module.psd1"
Author = 'Kevin Marquette'
NestedModules = @('bin\MyModule.dll')
RootModule = "$module.psm1"
FunctionsToExport = @('Resolve-MyCmdlet')
}
New-ModuleManifest @manifestSplat
Také vytvořím prázdný kořenový modul pro budoucí funkce PowerShellu.
Set-Content -Value '' -Path ".\$module\$module.psm1"
To mi umožňuje kombinovat normální funkce PowerShellu i binární rutiny ve stejném projektu.
Sestavení celého modulu
Zkompiluji všechno dohromady do výstupní složky. K tomu potřebujeme vytvořit skript sestavení. Normálně bych to přidal do Invoke-Build skriptu, ale pro tento příklad to můžeme zachovat jednoduché. Přidejte ji do build.ps1 v kořenovém adresáři projektu.
$module = 'MyModule'
Push-Location $PSScriptRoot
dotnet build $PSScriptRoot\src -o $PSScriptRoot\output\$module\bin
Copy-Item "$PSScriptRoot\$module\*" "$PSScriptRoot\output\$module" -Recurse -Force
Import-Module "$PSScriptRoot\Output\$module\$module.psd1"
Invoke-Pester "$PSScriptRoot\Tests"
Tyto příkazy sestaví knihovnu DLL a umístí ji do složky output\$module\bin. Potom zkopíruje ostatní soubory modulu na místo.
Output
└───MyModule
├───MyModule.psd1
├───MyModule.psm1
└───bin
├───MyModule.deps.json
├───MyModule.dll
└───MyModule.pdb
V tomto okamžiku můžeme modul importovat se souborem psd1.
Import-Module ".\Output\$module\$module.psd1"
Odtud můžeme složku .\Output\$module umístit do našeho adresáře $Env:PSModulePath a příkaz se automaticky načte, kdykoli ho potřebujeme.
Aktualizace: dotnet new PSModule
Naučil jsem se, že nástroj dotnet má šablonu PSModule.
Všechny kroky, které jsem popsal výše, jsou stále platné, ale tato šablona mnohé z nich vynechává. Je to stále poměrně nová šablona, která se ještě vylepšuje. Očekávejte, že se odsud bude lépe zlepšovat.
Takhle nainstalujete a použijete šablonu PSModule.
dotnet new -i Microsoft.PowerShell.Standard.Module.Template
dotnet new psmodule
dotnet build
Import-Module "bin\Debug\netstandard2.0\$module.dll"
Get-Module $module
Tato minimální realizovatelná šablona se postará o přidání sady .NET SDK, standardní knihovny PowerShellu a vytvoření ukázkové třídy v projektu. Můžete ho sestavit a hned ho spustit.
Důležité podrobnosti
Než tento článek ukončíme, tady je několik dalších podrobností, které stojí za zmínku.
Uvolňování knihoven DLL
Jakmile se načte binární modul, nemůžete ho odstranit. Soubor DLL je uzamčen, dokud ho nenačtete. To může být nepříjemné při vývoji, protože pokaždé, když uděláte změnu a chcete jej sestavit, soubor je často uzamčen. Jediným spolehlivým způsobem, jak tento problém vyřešit, je zavřít relaci PowerShellu, která načetla knihovnu DLL.
Akce opětovného načtení okna VS Code
Většinu práce s vývojem PowerShellu dělám v VS Code. Při práci na binárním modulu (nebo modulu s třídami) jsem se dostal do zvyku znovu načíst VS Code při každém sestavení.
ctrl+Shift+P zobrazí příkazové okno a Reload Window je vždy v horní části seznamu.
Vnořené relace PowerShellu
Jednou z dalších možností je mít dobré pokrytí testu Pester. Potom můžete upravit build.ps1 skript, který spustí novou relaci PowerShellu, provede sestavení, spustí testy a relaci zavře.
Aktualizace nainstalovaných modulů
Toto uzamčení může být nepříjemné při pokusu o aktualizaci místně nainstalovaného modulu. Pokud má některá relace tento obsah načtený, musíte ji najít a zavřít. To je méně problém při instalaci z PSGallery, protože správa verzí modulu umístí nový do jiné složky.
Můžete nastavit místní PSGallery a jako součást sestavení do něj publikovat. Pak proveďte lokální instalaci z této PSGallery. To zní jako spousta práce, ale může to být stejně jednoduché jako spuštění kontejneru Dockeru. Způsob, jak to udělat, popisuji ve svém příspěvku na Použití serveru NuGet pro PSRepository.
Konečné myšlenky
Nedotkl jsem se syntaxe jazyka C# pro vytváření cmdletů, ale v sadě Windows PowerShell SDKje k dispozici spousta dokumentace. Určitě je to něco, s čím stojí za to experimentovat jako odrazový můstek do vážnější práce s C#.