about_Classes_and_DSC
Rövid leírás
Ismerteti, hogyan fejleszthet osztályokat a PowerShellben a Desired State Configuration (DSC) használatával.
Hosszú leírás
A Windows PowerShell 5.0-s verziótól kezdődően a rendszer hozzáadta a nyelvet az osztályok és más, felhasználó által definiált típusok meghatározásához más objektumorientált programozási nyelvekhez hasonló formális szintaxis és szemantikák használatával. A cél az, hogy a fejlesztők és az informatikai szakemberek szélesebb körű használati esetekhez használhassák a PowerShellt, egyszerűbbé tegyék a PowerShell-összetevők, például a DSC-erőforrások fejlesztését, és felgyorsítsák a felügyeleti felületek lefedettségét.
Támogatott esetek
A következő forgatókönyvek támogatottak:
- A PowerShell-nyelv használatával definiálhatja a DSC-erőforrásokat és azok társított típusait.
- Egyéni típusok definiálása a PowerShellben ismerős objektumorientált programozási szerkezetek, például osztályok, tulajdonságok, metódusok és öröklés használatával.
- Típusok hibakeresése a PowerShell-nyelv használatával.
- A kivételek létrehozása és kezelése formális mechanizmusokkal és a megfelelő szinten.
DSC-erőforrások definiálása osztályokkal
A szintaxisváltozásokon kívül az osztály által definiált DSC-erőforrások és a DSC-erőforrás-szolgáltató parancsmagok közötti fő különbségek a következő elemek:
- Nincs szükség felügyeleti objektumformátumú (MOF) fájlra.
- A modulmappában nincs szükség DSCResource almappára.
- Egy PowerShell-modulfájl több DSC-erőforrásosztályt is tartalmazhat.
Osztályalapú DSC-erőforrás-szolgáltató létrehozása
Az alábbi példa egy osztály által definiált DSC-erőforrás-szolgáltató, amely a MyDSCResource.psm1 modulként van mentve. Mindig tartalmaznia kell egy kulcstulajdonságot egy osztály által definiált DSC-erőforrás-szolgáltatóban.
enum Ensure
{
Absent
Present
}
<#
This resource manages the file in a specific path.
[DscResource()] indicates the class is a DSC resource
#>
[DscResource()]
class FileResource
{
<#
This property is the fully qualified path to the file that is
expected to be present or absent.
The [DscProperty(Key)] attribute indicates the property is a
key and its value uniquely identifies a resource instance.
Defining this attribute also means the property is required
and DSC will ensure a value is set before calling the resource.
A DSC resource must define at least one key property.
#>
[DscProperty(Key)]
[string]$Path
<#
This property indicates if the settings should be present or absent
on the system. For present, the resource ensures the file pointed
to by $Path exists. For absent, it ensures the file point to by
$Path does not exist.
The [DscProperty(Mandatory)] attribute indicates the property is
required and DSC will guarantee it is set.
If Mandatory is not specified or if it is defined as
Mandatory=$false, the value is not guaranteed to be set when DSC
calls the resource. This is appropriate for optional properties.
#>
[DscProperty(Mandatory)]
[Ensure] $Ensure
<#
This property defines the fully qualified path to a file that will
be placed on the system if $Ensure = Present and $Path does not
exist.
NOTE: This property is required because [DscProperty(Mandatory)] is
set.
#>
[DscProperty(Mandatory)]
[string] $SourcePath
<#
This property reports the file's create timestamp.
[DscProperty(NotConfigurable)] attribute indicates the property is
not configurable in DSC configuration. Properties marked this way
are populated by the Get() method to report additional details
about the resource when it is present.
#>
[DscProperty(NotConfigurable)]
[Nullable[datetime]] $CreationTime
<#
This method is equivalent of the Set-TargetResource script function.
It sets the resource to the desired state.
#>
[void] Set()
{
$fileExists = $this.TestFilePath($this.Path)
if($this.ensure -eq [Ensure]::Present)
{
if(-not $fileExists)
{
$this.CopyFile()
}
}
else
{
if($fileExists)
{
Write-Verbose -Message "Deleting the file $($this.Path)"
Remove-Item -LiteralPath $this.Path -Force
}
}
}
<#
This method is equivalent of the Test-TargetResource script
function. It should return True or False, showing whether the
resource is in a desired state.
#>
[bool] Test()
{
$present = $this.TestFilePath($this.Path)
if($this.Ensure -eq [Ensure]::Present)
{
return $present
}
else
{
return -not $present
}
}
<#
This method is equivalent of the Get-TargetResource script function.
The implementation should use the keys to find appropriate
resources. This method returns an instance of this class with the
updated key properties.
#>
[FileResource] Get()
{
$present = $this.TestFilePath($this.Path)
if ($present)
{
$file = Get-ChildItem -LiteralPath $this.Path
$this.CreationTime = $file.CreationTime
$this.Ensure = [Ensure]::Present
}
else
{
$this.CreationTime = $null
$this.Ensure = [Ensure]::Absent
}
return $this
}
<#
Helper method to check if the file exists and it is correct file
#>
[bool] TestFilePath([string] $location)
{
$present = $true
$item = Get-ChildItem -LiteralPath $location -ea Ignore
if ($null -eq $item)
{
$present = $false
}
elseif( $item.PSProvider.Name -ne "FileSystem")
{
throw "Path $($location) is not a file path."
}
elseif($item.PSIsContainer)
{
throw "Path $($location) is a directory path."
}
return $present
}
<#
Helper method to copy file from source to path
#>
[void] CopyFile()
{
if(-not $this.TestFilePath($this.SourcePath))
{
throw "SourcePath $($this.SourcePath) is not found."
}
[System.IO.FileInfo]
$destFileInfo = new-object System.IO.FileInfo($this.Path)
if (-not $destFileInfo.Directory.Exists)
{
$FullName = $destFileInfo.Directory.FullName
$Message = "Creating directory $FullName"
Write-Verbose -Message $Message
#use CreateDirectory instead of New-Item to avoid code
# to handle the non-terminating error
[System.IO.Directory]::CreateDirectory($FullName)
}
if(Test-Path -LiteralPath $this.Path -PathType Container)
{
throw "Path $($this.Path) is a directory path"
}
Write-Verbose -Message "Copying $this.SourcePath to $this.Path"
#DSC engine catches and reports any error that occurs
Copy-Item -Path $this.SourcePath -Destination $this.Path -Force
}
}
Moduljegyzék létrehozása
Az osztály által definiált DSC-erőforrás-szolgáltató létrehozása és modulként való mentése után hozzon létre egy moduljegyzéket a modulhoz. Ha elérhetővé szeretne tenni egy osztályalapú erőforrást a DSC-motor számára, fel kell vennie egy DscResourcesToExport
utasítást a jegyzékfájlba, amely arra utasítja a modult, hogy exportálja az erőforrást. Ebben a példában a következő moduljegyzéket a rendszer MyDscResource.psd1 néven menti.
@{
# Script module or binary module file associated with this manifest.
RootModule = 'MyDscResource.psm1'
DscResourcesToExport = 'FileResource'
# Version number of this module.
ModuleVersion = '1.0'
# ID used to uniquely identify this module
GUID = '81624038-5e71-40f8-8905-b1a87afe22d7'
# Author of this module
Author = 'Microsoft Corporation'
# Company or vendor of this module
CompanyName = 'Microsoft Corporation'
# Copyright statement for this module
Copyright = '(c) 2014 Microsoft. All rights reserved.'
# Description of the functionality provided by this module
# Description = ''
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.0'
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
}
DSC-erőforrás-szolgáltató üzembe helyezése
Helyezze üzembe az új DSC-erőforrás-szolgáltatót egy MyDscResource mappa létrehozásával a vagy $env:SystemDrive\ProgramFiles\WindowsPowerShell\Modules
a $pshome\Modules
.
Nem kell DSCResource almappát létrehoznia. Másolja a modul- és moduljegyzékfájlokat (MyDscResource.psm1 és MyDscResource.psd1) a MyDscResource mappába.
Ettől a ponttól kezdve ugyanúgy hozhat létre és futtathat konfigurációs szkriptet, mint bármely DSC-erőforrás esetében.
DSC-konfigurációs szkript létrehozása
Miután mentette az osztály- és jegyzékfájlokat a mappastruktúrában a korábban leírtak szerint, létrehozhat egy konfigurációt, amely az új erőforrást használja. Az alábbi konfiguráció a MyDSCResource modulra hivatkozik. Mentse a konfigurációt szkriptként, MyResource.ps1.
A DSC-konfiguráció futtatásával kapcsolatos információkért lásd Windows PowerShell Desired State Configuration áttekintését.
A konfiguráció futtatása előtt hozza létre a következőt C:\test.txt
: . A konfiguráció ellenőrzi, hogy a fájl létezik-e a következő helyen c:\test\test.txt
: . Ha a fájl nem létezik, a konfiguráció innen másolja a fájlt C:\test.txt
.
Configuration Test
{
Import-DSCResource -module MyDscResource
FileResource file
{
Path = "C:\test\test.txt"
SourcePath = "C:\test.txt"
Ensure = "Present"
}
}
Test
Start-DscConfiguration -Wait -Force Test
Futtassa ezt a szkriptet ugyanúgy, mint bármely DSC-konfigurációs szkriptet. A konfiguráció elindításához futtassa a következőt egy emelt szintű PowerShell-konzolon:
PS C:\test> .\MyResource.ps1
Öröklés PowerShell-osztályokban
Alaposztályok deklarálása PowerShell-osztályokhoz
A PowerShell-osztályokat egy másik PowerShell-osztály alaptípusaként deklarálhatja, ahogy az alábbi példában látható, amelyben a gyümölcs az alma alaptípusa.
class fruit
{
[int]sold() {return 100500}
}
class apple : fruit {}
[apple]::new().sold() # return 100500
Implementált felületek deklarálása PowerShell-osztályokhoz
A implementált illesztőket alaptípusok után, vagy közvetlenül kettőspont (:
) után deklarálhatja, ha nincs megadva alaptípus. Az összes típusnevet vesszővel válassza el egymástól. Ez hasonló a C#-szintaxishoz.
class MyComparable : system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
class MyComparableTest : test, system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
Alaposztály konstruktorok hívása
Ha egy alosztályból szeretné meghívni az alaposztály konstruktorát, adja hozzá a base
kulcsszót az alábbi példában látható módon:
class A {
[int]$a
A([int]$a)
{
$this.a = $a
}
}
class B : A
{
B() : base(103) {}
}
[B]::new().a # return 103
Ha egy alaposztály alapértelmezett konstruktorsal rendelkezik (paraméterek nélkül), kihagyhat egy explicit konstruktorhívást az ábrán látható módon.
class C : B
{
C([int]$c) {}
}
Alaposztály metódusának hívása
Az alosztályokban meglévő metódusokat felülbírálhatja. A felülbíráláshoz deklaráljon metódusokat ugyanazzal a névvel és aláírással.
class baseClass
{
[int]days() {return 100500}
}
class childClass1 : baseClass
{
[int]days () {return 200600}
}
[childClass1]::new().days() # return 200600
Ha az alaposztály metódusait felül bírált implementációkból szeretné meghívni, a meghívás alapján az alaposztályba ([baseclass]$this)
kell állítva.
class childClass2 : baseClass
{
[int]days()
{
return 3 * ([baseClass]$this).days()
}
}
[childClass2]::new().days() # return 301500
Minden PowerShell-metódus virtuális. A nem virtuális .NET-metódusokat úgy rejtheti el egy alosztályban, hogy ugyanazt a szintaxist használja, mint a felülbírálás esetén: azonos nevű és aláírású metódusokat deklarálhat.
class MyIntList : system.collections.generic.list[int]
{
# Add is final in system.collections.generic.list
[void] Add([int]$arg)
{
([system.collections.generic.list[int]]$this).Add($arg * 2)
}
}
$list = [MyIntList]::new()
$list.Add(100)
$list[0] # return 200
Az osztályörökléssel kapcsolatos jelenlegi korlátozások
Az osztályörökléssel kapcsolatos korlátozás az, hogy a PowerShellben nincs szintaxis a felületek deklarálásához.
Egyéni típusok definiálása a PowerShellben
Windows PowerShell 5.0 számos nyelvi elemet vezetett be.
Osztály kulcsszó
Új osztályt definiál.
A class
kulcsszó egy valódi .NET-keretrendszer típus.
Az osztálytagok nyilvánosak.
class MyClass
{
}
Kulcsszó és enumerálások számbavétele
A kulcsszó támogatása enum
hozzá lett adva, és kompatibilitástörő változás. A enum
határoló jelenleg új vonal. Azok számára, akik már használják enum
, kerülő megoldásként beszúrhat egy és (&
) erősítőt a szó elé. Jelenlegi korlátozások: önmagában nem definiálhat enumerátort, de inicializálhat enum
egy másikat enum
, ahogy az alábbi példában látható:
Az alaptípus jelenleg nem adható meg. Az alaptípus mindig [int].
enum Color2
{
Yellow = [Color]::Blue
}
Az enumerátorértéknek elemzési időállandónak kell lennie. Az enumerátor értéke nem állítható egy meghívott parancs eredményére.
enum MyEnum
{
Enum1
Enum2
Enum3 = 42
Enum4 = [int]::MaxValue
}
Enum
az alábbi példában látható módon támogatja az aritmetikai műveleteket:
enum SomeEnum { Max = 42 }
enum OtherEnum { Max = [SomeEnum]::Max + 1 }
Rejtett kulcsszó
Az hidden
Windows PowerShell 5.0-s verzióban bevezetett kulcsszó elrejti az osztálytagokat az alapértelmezett Get-Member
eredmények elől. Adja meg a rejtett tulajdonságot az alábbi sorban látható módon:
hidden [type] $classmember = <value>
A rejtett tagok nem jelennek meg lapkiegészítés vagy IntelliSense használatával, kivéve, ha a befejezés a rejtett tagot meghatározó osztályban történik.
Egy új attribútum, a System.Management.Automation.HiddenAttribute lett hozzáadva, hogy a C#-kód ugyanazokkal a szemantikával rendelkezzen a PowerShellben.
További információ: [about_Hidden[(/powershell/module/microsoft.powershell.core/about/about_hidden).
Import-DscResource
Import-DscResource
A mostantól egy valódi dinamikus kulcsszó. A PowerShell elemzi a megadott modul gyökérmodulját, és megkeresi a DscResource attribútumot tartalmazó osztályokat.
Tulajdonságok
Új mező ImplementingAssembly
lett hozzáadva a programhoz ModuleInfo
. Ha a szkript osztályokat határoz meg, vagy a bináris modulok ImplementingAssembly
betöltött szerelvénye a szkriptmodulhoz létrehozott dinamikus szerelvényre van beállítva. A modultípus = jegyzékfájl esetén nincs beállítva.
A mező tükröződése ImplementingAssembly
egy modul erőforrásait deríti fel. Ez azt jelenti, hogy a PowerShellben vagy más felügyelt nyelveken írt erőforrásokat is felfedezhet.
Inicializálókkal rendelkező mezők.
[int] $i = 5
A statikus érték támogatott, és a típuskényszerekhez hasonló attribútumként működik, így bármilyen sorrendben megadható.
static [int] $count = 0
A típus megadása nem kötelező.
$s = "hello"
Minden tag nyilvános. A tulajdonságokhoz új vonal vagy pontosvessző szükséges. Ha nincs megadva objektumtípus, a tulajdonság típusa Objektum.
Konstruktorok és példányosítás
A PowerShell-osztályok olyan konstruktorokkal rendelkezhetnek, amelyek neve megegyezik az osztályuk nevével. A konstruktorok túlterhelhetők. A statikus konstruktorok támogatottak.
Az inicializálási kifejezésekkel rendelkező tulajdonságok inicializálva lesznek, mielőtt bármilyen kódot futtatnak egy konstruktorban. A statikus tulajdonságok inicializálása a statikus konstruktor törzse előtt, a példánytulajdonságok pedig a nem statikus konstruktor törzse előtt vannak inicializálva. Jelenleg nincs szintaxis egy konstruktor más konstruktorból való meghívásához, például a C#-szintaxishoz: ": this()")
. A kerülő megoldás egy közös Init-metódus definiálása.
Az osztályok példányosításának módjai a következők:
Példányosítás az alapértelmezett konstruktor használatával. Vegye figyelembe, hogy
New-Object
ez a kiadás nem támogatott.$a = [MyClass]::new()
Konstruktor meghívása paraméterrel.
$b = [MyClass]::new(42)
Tömb átadása több paraméterrel rendelkező konstruktornak
$c = [MyClass]::new(@(42,43,44), "Hello")
Ebben a kiadásban a típusnév csak lexikálisan látható, ami azt jelenti, hogy az osztályt definiáló modulon vagy szkripten kívül nem látható. A függvények a PowerShellben definiált osztály példányait is visszaadhatják, a példányok pedig jól működnek a modulon vagy a szkripten kívül.
A Get-Member
Statikus paraméter a konstruktorokat listázza, így a túlterheléseket bármely más módszerhez hasonlóan tekintheti meg. Ennek a szintaxisnak a teljesítménye is lényegesen gyorsabb, mint New-Object
a .
Az új nevű pszeudo-statikus metódus a .NET-típusokkal működik, ahogy az az alábbi példában látható. [hashtable]::new()
Most már láthatja a konstruktorok túlterhelését Get-Member
az alábbi példában látható módon:
[hashtable]::new
OverloadDefinitions
-------------------
hashtable new()
hashtable new(int capacity)
hashtable new(int capacity, float loadFactor)
Metódusok
A PowerShell-osztálymetódus szkriptblokkként van implementálva, amelynek csak egy végpontja van. Minden metódus nyilvános. Az alábbiakban egy DoSomething nevű metódus definiálására láthat példát.
class MyClass
{
DoSomething($x)
{
$this._doSomething($x) # method syntax
}
private _doSomething($a) {}
}
Metódushívás
A túlterhelt metódusok támogatottak. A túlterhelt metódusok neve megegyezik egy meglévő metódussal, de a megadott értékek megkülönböztetik őket.
$b = [MyClass]::new()
$b.DoSomething(42)
Könyörgése
Lásd a metódushívást.
Attribútumok
Három új attribútum lett hozzáadva: DscResource
, DscResourceKey
és DscResourceMandatory
.
Visszatérési típusok
A visszatérési típus szerződés. A visszaadott érték a várt típusra lesz konvertálva. Ha nincs megadva visszatérési típus, a visszatérési típus érvénytelen. Az objektumok és objektumok nem streamelhetők szándékosan vagy véletlenül a folyamatba.
Változók lexikális hatókörkezelése
Az alábbiakban egy példa látható a lexikális hatókörkezelés működésére ebben a kiadásban.
$d = 42 # Script scope
function bar
{
$d = 0 # Function scope
[MyClass]::DoSomething()
}
class MyClass
{
static [object] DoSomething()
{
return $d # error, not found dynamically
return $script:d # no error
$d = $script:d
return $d # no error, found lexically
}
}
$v = bar
$v -eq $d # true
Példa: Egyéni osztályok létrehozása
Az alábbi példa számos új, egyéni osztályt hoz létre egy HTML dinamikus stíluslapnyelv (DSL) implementálásához. A példa segédfüggvényeket ad hozzá adott elemtípusok létrehozásához az elemosztály részeként, például címsorstílusok és táblázatok részeként, mivel a típusok nem használhatók a modul hatókörén kívül.
# Classes that define the structure of the document
#
class Html
{
[string] $docType
[HtmlHead] $Head
[Element[]] $Body
[string] Render()
{
$text = "<html>`n<head>`n"
$text += $Head
$text += "`n</head>`n<body>`n"
$text += $Body -join "`n" # Render all of the body elements
$text += "</body>`n</html>"
return $text
}
[string] ToString() { return $this.Render() }
}
class HtmlHead
{
$Title
$Base
$Link
$Style
$Meta
$Script
[string] Render() { return "<title>$Title</title>" }
[string] ToString() { return $this.Render() }
}
class Element
{
[string] $Tag
[string] $Text
[hashtable] $Attributes
[string] Render() {
$attributesText= ""
if ($Attributes)
{
foreach ($attr in $Attributes.Keys)
{
$attributesText = " $attr=`"$($Attributes[$attr])`""
}
}
return "<${tag}${attributesText}>$text</$tag>`n"
}
[string] ToString() { return $this.Render() }
}
#
# Helper functions for creating specific element types on top of the classes.
# These are required because types aren't visible outside of the module.
#
function H1 {[Element] @{Tag = "H1"; Text = $args.foreach{$_} -join " "}}
function H2 {[Element] @{Tag = "H2"; Text = $args.foreach{$_} -join " "}}
function H3 {[Element] @{Tag = "H3"; Text = $args.foreach{$_} -join " "}}
function P {[Element] @{Tag = "P" ; Text = $args.foreach{$_} -join " "}}
function B {[Element] @{Tag = "B" ; Text = $args.foreach{$_} -join " "}}
function I {[Element] @{Tag = "I" ; Text = $args.foreach{$_} -join " "}}
function HREF
{
param (
$Name,
$Link
)
return [Element] @{
Tag = "A"
Attributes = @{ HREF = $link }
Text = $name
}
}
function Table
{
param (
[Parameter(Mandatory)]
[object[]]
$Data,
[Parameter()]
[string[]]
$Properties = "*",
[Parameter()]
[hashtable]
$Attributes = @{ border=2; cellpadding=2; cellspacing=2 }
)
$bodyText = ""
# Add the header tags
$bodyText += $Properties.foreach{TH $_}
# Add the rows
$bodyText += foreach ($row in $Data)
{
TR (-join $Properties.Foreach{ TD ($row.$_) } )
}
$table = [Element] @{
Tag = "Table"
Attributes = $Attributes
Text = $bodyText
}
$table
}
function TH {([Element] @{Tag="TH"; Text=$args.foreach{$_} -join " "})}
function TR {([Element] @{Tag="TR"; Text=$args.foreach{$_} -join " "})}
function TD {([Element] @{Tag="TD"; Text=$args.foreach{$_} -join " "})}
function Style
{
return [Element] @{
Tag = "style"
Text = "$args"
}
}
# Takes a hash table, casts it to and HTML document
# and then returns the resulting type.
#
function Html ([HTML] $doc) { return $doc }
Lásd még
Egyéni PowerShell-Desired State Configuration-erőforrások létrehozása
Visszajelzés
Visszajelzés küldése és megtekintése a következőhöz: