Bölüm 10 - Betik modülleri

Aynı PowerShell tek satırlı veya betikleri sık sık kullanıyorsanız, bunları yeniden kullanılabilir araçlara dönüştürmek daha da önemlidir. İşlevlerinizi bir betik modülünde paketlemek, onlara daha profesyonel bir his verir ve destekleyip başkalarıyla paylaşmalarını kolaylaştırır.

Nokta kaynak oluşturma işlevleri

Önceki bölümde ele almadığımız şeylerden biri nokta kaynak oluşturma işlevleridir. Bir betikte işlev tanımladığınızda ancak modülün bir parçası olmadığınızda, bunu belleğe yüklemenin tek yolu dosyasını noktalı kaynak oluşturmaktır .ps1 .

Örneğin, aşağıdaki işlevi adlı Get-MrPSVersion.ps1bir dosyaya kaydedin.

function Get-MrPSVersion {
    $PSVersionTable
}

Betiği çalıştırdığınızda hiçbir şey olmuyor gibi görünür.

.\Get-MrPSVersion.ps1

İşlevin çağrılmaya çalışılması, belleğe yüklenmediğinden bir hatayla sonuçlanır.

Get-MrPSVersion
Get-MrPSVersion : The term 'Get-MrPSVersion' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and
try again.
At line:1 char:1
+ Get-MrPSVersion
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-MrPSVersion:String) [],
   CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

İşlevlerin belleğe yüklenip yüklenmediğini doğrulamak için İşlev: PSDrive'da bunların varlığını doğrulayabilirsiniz.

Get-ChildItem -Path Function:\Get-MrPSVersion
Get-ChildItem : Cannot find path 'Get-MrPSVersion' because it does not
exist.
At line:1 char:1
+ Get-ChildItem -Path Function:\Get-MrPSVersion
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-MrPSVersion:String) [Get
   -ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.Ge
   tChildItemCommand

İşlevi tanımlayan betiğin çalıştırılmasıyla ilgili sorun, onu Betik kapsamına yüklemesidir. Betik yürütmeyi tamamladığında, PowerShell kapsamı ve işlevi ortadan kaldırır.

Betik çalıştırıldıktan sonra işlevin kullanılabilir durumda kalması için Global kapsama yüklenmesi gerekir. Betik dosyasını noktalı kaynak kullanarak bunu gerçekleştirebilirsiniz. Bu amaç için göreli bir yol kullanabilirsiniz.

. .\Get-MrPSVersion.ps1

Ayrıca, nokta kaynağı kullanırken betiğin tam yolunu da kullanabilirsiniz.

. C:\Demo\Get-MrPSVersion.ps1

Yolun bir bölümü bir değişkende depolanıyorsa, bunu yolun geri kalanıyla birleştirebilirsiniz. Bunu yapmak için dize birleştirme kullanmaya gerek yoktur.

$Path = 'C:\'
. $Path\Get-MrPSVersion.ps1

Şimdi, PSDrive İşlevi'ni denetlerseniz işlevin Get-MrPSVersion kullanılabilir olduğunu görürsünüz.

Get-ChildItem -Path Function:\Get-MrPSVersion
CommandType     Name                                               Version
-----------     ----                                               -------
Function        Get-MrPSVersion

Senaryo modüller

PowerShell'de betik modülü, normal betik gibi ancak farklı bir .psm1 dosya uzantısına sahip bir veya daha fazla işlev içeren bir dosyadır.

Betik modülünü nasıl oluşturursunuz? gibi New-Moduleadlı bir komutla varsayabilirsiniz. Bu varsayım makul bir tahmindir, ancak bu komut aslında bir betik modülü değil dinamik bir modül oluşturur.

Bu senaryo, bir komut adı tam olarak ihtiyacınız olan gibi görünse bile yardım belgelerini her zaman okumak için iyi bir anımsatıcıdır.

help New-Module
NAME
    New-Module

SYNOPSIS
    Creates a new dynamic module that exists only in memory.


SYNTAX
    New-Module [-Name] <System.String> [-ScriptBlock]
    <System.Management.Automation.ScriptBlock> [-ArgumentList
    <System.Object[]>] [-AsCustomObject] [-Cmdlet <System.String[]>]
    [-Function <System.String[]>] [-ReturnResult] [<CommonParameters>]


DESCRIPTION
    The `New-Module` cmdlet creates a dynamic module from a script block.
    The members of the dynamic module, such as functions and variables, are
    immediately available in the session and remain available until you
    close the session.

    Like static modules, by default, the cmdlets and functions in a dynamic
    module are exported and the variables and aliases are not. However, you
    can use the Export-ModuleMember cmdlet and the parameters of
    `New-Module` to override the defaults.

    You can also use the **AsCustomObject** parameter of `New-Module` to return
    the dynamic module as a custom object. The members of the modules, such
    as functions, are implemented as script methods of the custom object
    instead of being imported into the session.

    Dynamic modules exist only in memory, not on disk. Like all modules,
    the members of dynamic modules run in a private module scope that is a
    child of the global scope. Get-Module cannot get a dynamic module, but
    Get-Command can get the exported members.

    To make a dynamic module available to `Get-Module`, pipe a `New-Module`
    command to Import-Module, or pipe the module object that `New-Module`
    returns to `Import-Module`. This action adds the dynamic module to the
    `Get-Module` list, but it does not save the module to disk or make it
    persistent.


RELATED LINKS
    Online Version: https://learn.microsoft.com/powershell/module/microsoft.
    powershell.core/new-module?view=powershell-5.1&WT.mc_id=ps-gethelp
    Export-ModuleMember
    Get-Module
    Import-Module
    Remove-Module
    about_Modules

REMARKS
    To see the examples, type: "Get-Help New-Module -Examples".
    For more information, type: "Get-Help New-Module -Detailed".
    For technical information, type: "Get-Help New-Module -Full".
    For online help, type: "Get-Help New-Module -Online"

Önceki bölümde işlevlerin onaylı fiiller kullanması gerektiği belirtildi. Aksi takdirde, Modül içeri aktarıldığında PowerShell bir uyarı oluşturur.

Aşağıdaki örnek New-Module , cmdlet'ini kullanarak bellekte dinamik bir modül oluşturur ve özellikle onaylı bir fiil kullanmadığınızda ne olacağını gösterir.

New-Module -Name MyModule -ScriptBlock {

    function Return-MrOsVersion {
        Get-CimInstance -ClassName Win32_OperatingSystem |
        Select-Object -Property @{Label='OperatingSystem';Expression={$_.Caption}}
    }

    Export-ModuleMember -Function Return-MrOsVersion

} | Import-Module
WARNING: The names of some imported commands from the module 'MyModule' include
unapproved verbs that might make them less discoverable. To find the commands with
unapproved verbs, run the Import-Module command again with the Verbose parameter. For a
list of approved verbs, type Get-Verb.

Önceki örnekte New-Module cmdlet ile çalışmış olmanıza rağmen, daha önce belirtildiği gibi PowerShell'de betik modülleri oluşturma komutu değildir.

Betik modülü oluşturmak için işlevlerinizi bir .psm1 dosyaya kaydedin. Örneğin, aşağıdaki iki işlevi adlı MyScriptModule.psm1bir dosyaya kaydedin.

function Get-MrPSVersion {
    $PSVersionTable
}

function Get-MrComputerName {
    $env:COMPUTERNAME
}

İşlevlerden birini çalıştırmayı deneyin.

Get-MrComputerName

İşlevi çağırdığınızda PowerShell'in bulamadığını belirten bir hata alırsınız. Daha önce olduğu gibi, İşlev: PSDrive'ın denetlenmesi, belleğe yüklenmediğini doğrular.

Get-MrComputerName : The term 'Get-MrComputerName' is not recognized as the
name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:1 char:1
+ Get-MrComputerName
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-MrComputerName:String) [
   ], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

İşlevi kullanılabilir hale getirmek için MyScriptModule.psm1 dosyasını cmdlet'i Import-Module kullanarak el ile içeri aktarabilirsiniz.

Import-Module C:\MyScriptModule.psm1

PowerShell, modül otomatik yüklemesini sürüm 3'te kullanıma sunulmuştur. Bu özelliğin avantajlarından yararlanmak için betik modülünün dosyayla aynı temel ada .psm1 sahip bir klasöre kaydedilmesi gerekir. Bu klasör, ortam değişkeninde $env:PSModulePath belirtilen dizinlerden birinde bulunmalıdır.

$env:PSModulePath

$env:PSModulePath çıktısını okumak zor.

C:\Users\mike-ladm\Documents\WindowsPowerShell\Modules;C:\Program Files\Wind
owsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules;C:\
Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\

Sonuçları daha okunabilir hale getirmek için, yolları noktalı virgül ayırıcıyla ayırıp her birini ayrı bir satıra yerleştirin.

$env:PSModulePath -split ';'

Listedeki ilk üç yol varsayılan modül konumlarıdır. SQL Server Management Studio, yüklediğinizde son yolu ekledi.

C:\Users\mike-ladm\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\system32\WindowsPowerShell\v1.0\Modules
C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\

Modül otomatik yüklemenin çalışması için, dosyayı MyScriptModule.psm1 adlı bir klasöre yerleştirmeniz ve bu klasörün listelenen yollardan birinin doğrudan içinde yer alması gerekir.
$env:PSModulePath.

Tüm bu yollar eşit derecede yararlı değildir. Örneğin, sistemimde bulunan şu anki kullanıcı yolu listedeki ilk yol değil. Bunun nedeni, PowerShell'i çalıştırmak için kullandığımdan farklı bir hesapla Windows'ta oturum açmamdır. Bu nedenle, kullanıcımın belgeler klasörüne işaret etmiyor.

İkinci yol, tüm modüllerimi depoladığım AllUsers yoludur.

Üçüncü yol, korumalı bir sistem konumunu gösterir C:\Windows\System32. İşletim sisteminin dizin yapısı altında yer alan modüller yalnızca Microsoft tarafından yerleştirilmelidir.

Dosyayı bu yollardan birinin içindeki uygun bir klasöre yerleştirdiğinizde .psm1 PowerShell, komutlarından birini ilk kez çağırdığınızda modülü otomatik olarak yükler.

Modül bildirimleri

Her modül, modülle ilgili meta verileri içeren bir dosya olan bir .psd1 modül bildirimi içermelidir. .psd1 Uzantı bildirimler için kullanılırken, tüm .psd1 dosyalar modül bildirimleri değildir. Bunları DSC'de ortam verilerini tanımlama gibi başka amaçlar için de kullanabilirsiniz
konfigürasyon.

cmdlet'ini New-ModuleManifest kullanarak bir modül bildirimi oluşturabilirsiniz. Tek gerekli parametre Path'dir, ancak modülün düzgün çalışması için RootModule parametresini de belirtmeniz gerekir.

Özellikle modülünüzü PowerShellGet kullanarak NuGet deposunda yayımlamayı planlıyorsanız Yazar ve Açıklama gibi değerleri eklemek en iyi yöntemdir. Bu alanlar bu senaryoda gereklidir.

Bir modülün bildiriminin eksik olup olmadığını anlamanın hızlı bir yolu, sürümünü denetlemektir.

Get-Module -Name MyScriptModule

sürüm numarası 0.0 , modülün bir bildirime sahip olmadığının açık bir işaretidir.

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        MyScriptModule                      {Get-MrComputer...

Modülünüzün iyi belgelendiğinden ve paylaşmaya veya yayımlamaya hazır olduğundan emin olmak için modül bildirimi oluştururken önerilen tüm ayrıntıları eklemeniz gerekir.

$moduleManifestParams = @{
    Path = "$env:ProgramFiles\WindowsPowerShell\Modules\MyScriptModule\MyScriptModule.psd1"
    RootModule = 'MyScriptModule'
    Author = 'Mike F. Robbins'
    Description = 'MyScriptModule'
    CompanyName = 'mikefrobbins.com'
}

New-ModuleManifest @moduleManifestParams

Modül bildirimini ilk oluştururken herhangi bir değeri atlarsanız, daha sonra cmdlet'ini Update-ModuleManifest kullanarak ekleyebilir veya güncelleştirebilirsiniz. Manifest dosyasını oluşturduktan sonra New-ModuleManifest ile yeniden oluşturmaktan kaçının; bunu yaptığınızda yeni bir GUID oluşturulur.

Genel ve özel işlevleri tanımlama

Modülünüz bazen kullanıcılara göstermek istemediğiniz yardımcı işlevleri içerebilir. Bu özel işlevler modüldeki diğer işlevler tarafından dahili olarak kullanılır ancak kullanıcılara sunulmaz. Bu senaryoyla ilgilenmenin birkaç yolu vardır.

En iyi yöntemleri kullanmıyorsanız ve yalnızca modül bildirimi olmayan bir .psm1 dosyanız varsa, tek seçeneğiniz cmdlet'ini Export-ModuleMember kullanarak görünürlüğü denetlemektir. Bu seçenek, betik modülü dosyasının içinden hangi işlevlerin .psm1 doğrudan kullanıma sunulacak olduğunu açıkça tanımlamanıza olanak tanır ve diğer her şeyi varsayılan olarak gizli tutar.

Aşağıdaki örnekte yalnızca Get-MrPSVersion işlevi modülünüzün kullanıcılarına sunulurken Get-MrComputerName , işlev modüldeki diğer işlevler için dahili olarak erişilebilir durumda kalır.

function Get-MrPSVersion {
    $PSVersionTable
}

function Get-MrComputerName {
    $env:COMPUTERNAME
}

Export-ModuleMember -Function Get-MrPSVersion

MyScriptModule modülünde hangi komutların genel olarak kullanılabilir olduğunu belirleyin.

Get-Command -Module MyScriptModule
CommandType     Name                                               Version
-----------     ----                                               -------
Function        Get-MrPSVersion                                    1.0

Modülünüze bir modül bildirimi eklerseniz, dışarı aktarmak istediğiniz işlevleri FunctionsToExport bölümünde açıkça listelemek en iyi yöntemdir. Bu seçenek, modül bildirim dosyasından kullanıcılara neleri açığa çıkarabileceğinizi .psd1 denetlemenizi sağlar.

FunctionsToExport = 'Get-MrPSVersion'

Hem Export-ModuleMember dosyasındaki .psm1 öğesini hem de modül bildirimindeki FunctionsToExport bölümünü kullanmanız gerekmez. Her iki yaklaşım da tek başına yeterlidir.

Özet

Bu bölümde, işlevlerinizi PowerShell'de bir betik modülüne dönüştürmeyi öğrendiniz. Ayrıca, meta verileri tanımlamak ve dışarı aktarılan komutları yönetmek için modül bildirimi eklemenin önemi de dahil olmak üzere betik modülleri oluşturmaya yönelik en iyi yöntemleri keşfettiniz.

Eleştiri

  1. PowerShell'de nasıl betik modülü oluşturursunuz?
  2. İşlev adlarınız için onaylı fiilleri kullanmak neden önemlidir?
  3. PowerShell'de modül bildirimini nasıl oluşturursunuz?
  4. Modülden yalnızca belirli işlevleri dışarı aktarmanın iki yolu nelerdir?
  5. Bir modülün komutlarından birini çalıştırdığınızda otomatik olarak yüklenmesi için hangi koşulların karşılanması gerekir?

Gözden geçirme sorularının yanıtları için bu kitabın Eki'ne bakın.

Kaynaklar