about_Classes_and_DSC
Deskripsi singkat
Menjelaskan bagaimana Anda dapat menggunakan kelas untuk dikembangkan di PowerShell dengan Desired State Configuration (DSC).
Deskripsi panjang
Mulai Windows PowerShell 5.0, bahasa ditambahkan untuk menentukan kelas dan jenis lain yang ditentukan pengguna, dengan menggunakan sintaks formal dan semantik yang mirip dengan bahasa pemrograman berorientasi objek lainnya. Tujuannya adalah untuk memungkinkan pengembang dan profesional TI merangkul PowerShell untuk berbagai kasus penggunaan yang lebih luas, menyederhanakan pengembangan artefak PowerShell seperti sumber daya DSC, dan mempercepat cakupan permukaan manajemen.
Skenario yang didukung
Skenario berikut didukung:
- Tentukan sumber daya DSC dan jenis terkaitnya dengan menggunakan bahasa PowerShell.
- Tentukan jenis kustom di PowerShell dengan menggunakan konstruksi pemrograman berorientasi objek yang sudah dikenal, seperti kelas, properti, metode, dan pewarisan.
- Jenis debug dengan menggunakan bahasa PowerShell.
- Hasilkan dan tangani pengecualian dengan menggunakan mekanisme formal, dan pada tingkat yang tepat.
Menentukan sumber daya DSC dengan kelas
Selain perubahan sintaksis, perbedaan utama antara sumber daya DSC yang ditentukan kelas dan penyedia sumber daya DSC cmdlet adalah item berikut:
- File Management Object Format (MOF) tidak diperlukan.
- Subfolder DSCResource di folder modul tidak diperlukan.
- File modul PowerShell dapat berisi beberapa kelas sumber daya DSC.
Membuat penyedia sumber daya DSC yang ditentukan kelas
Contoh berikut adalah penyedia sumber daya DSC yang ditentukan kelas yang disimpan sebagai modul, MyDSCResource.psm1. Anda harus selalu menyertakan properti kunci di penyedia sumber daya DSC yang ditentukan kelas.
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
}
}
Membuat manifes modul
Setelah membuat penyedia sumber daya DSC yang ditentukan kelas, dan menyimpannya sebagai modul, buat manifes modul untuk modul. Untuk membuat sumber daya berbasis kelas tersedia untuk mesin DSC, Anda harus menyertakan DscResourcesToExport
pernyataan dalam file manifes yang menginstruksikan modul untuk mengekspor sumber daya. Dalam contoh ini, manifes modul berikut disimpan sebagai MyDscResource.psd1.
@{
# 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 = ''
}
Menyebarkan penyedia sumber daya DSC
Sebarkan penyedia sumber daya DSC baru dengan membuat folder MyDscResource di $pshome\Modules
atau $env:SystemDrive\ProgramFiles\WindowsPowerShell\Modules
.
Anda tidak perlu membuat subfolder DSCResource. Salin file manifes modul dan modul (MyDscResource.psm1 dan MyDscResource.psd1) ke folder MyDscResource.
Dari titik ini, Anda membuat dan menjalankan skrip konfigurasi seperti yang Anda lakukan dengan sumber daya DSC apa pun.
Buat skrip konfigurasi DSC
Setelah menyimpan file kelas dan manifes dalam struktur folder seperti yang dijelaskan sebelumnya, Anda dapat membuat konfigurasi yang menggunakan sumber daya baru. Konfigurasi berikut mereferensikan modul MyDSCResource. Simpan konfigurasi sebagai skrip, MyResource.ps1.
Untuk informasi tentang cara menjalankan konfigurasi DSC, lihat Gambaran Umum Konfigurasi Status yang Diinginkan Windows PowerShell.
Sebelum Anda menjalankan konfigurasi, buat C:\test.txt
. Konfigurasi memeriksa apakah file ada di c:\test\test.txt
. Jika file tidak ada, konfigurasi menyalin file dari C:\test.txt
.
Configuration Test
{
Import-DSCResource -ModuleName MyDscResource
FileResource file
{
Path = "C:\test\test.txt"
SourcePath = "C:\test.txt"
Ensure = "Present"
}
}
Test
Start-DscConfiguration -Wait -Force Test
Jalankan skrip ini seperti yang Anda lakukan pada skrip konfigurasi DSC apa pun. Untuk memulai konfigurasi, di konsol PowerShell yang ditingkatkan, jalankan hal berikut:
PS C:\test> .\MyResource.ps1
Pewarisan di kelas PowerShell
Mendeklarasikan kelas dasar untuk kelas PowerShell
Anda dapat mendeklarasikan kelas PowerShell sebagai jenis dasar untuk kelas PowerShell lain, seperti yang ditunjukkan dalam contoh berikut, di mana buah adalah jenis dasar untuk apel.
class fruit
{
[int]sold() {return 100500}
}
class apple : fruit {}
[apple]::new().sold() # return 100500
Mendeklarasikan antarmuka yang diimplementasikan untuk kelas PowerShell
Anda dapat mendeklarasikan antarmuka yang diimplementasikan setelah jenis dasar, atau segera setelah titik dua (:
) jika tidak ada jenis dasar yang ditentukan. Pisahkan semua nama jenis dengan menggunakan koma. Ini mirip dengan sintaks C#.
class MyComparable : system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
class MyComparableTest : test, system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
Konstruktor kelas dasar panggilan
Untuk memanggil konstruktor kelas dasar dari subkelas, tambahkan base
kata kunci, seperti yang ditunjukkan dalam contoh berikut:
class A {
[int]$a
A([int]$a)
{
$this.a = $a
}
}
class B : A
{
B() : base(103) {}
}
[B]::new().a # return 103
Jika kelas dasar memiliki konstruktor default (tanpa parameter), Anda dapat menghilangkan panggilan konstruktor eksplisit, seperti yang ditunjukkan.
class C : B
{
C([int]$c) {}
}
Memanggil metode kelas dasar
Anda dapat mengambil alih metode yang ada dalam subkelas. Untuk melakukan penimpaan, nyatakan metode dengan menggunakan nama dan tanda tangan yang sama.
class baseClass
{
[int]days() {return 100500}
}
class childClass1 : baseClass
{
[int]days () {return 200600}
}
[childClass1]::new().days() # return 200600
Untuk memanggil metode kelas dasar dari implementasi yang ditimpa, transmisikan ke kelas ([baseclass]$this)
dasar saat pemanggilan.
class childClass2 : baseClass
{
[int]days()
{
return 3 * ([baseClass]$this).days()
}
}
[childClass2]::new().days() # return 301500
Semua metode PowerShell bersifat virtual. Anda dapat menyembunyikan metode .NET non-virtual dalam subkelas dengan menggunakan sintaks yang sama seperti yang Anda lakukan untuk penimpaan: menyatakan metode dengan nama dan tanda tangan yang sama.
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
Batasan saat ini dengan pewarisan kelas
Batasan dengan pewarisan kelas adalah bahwa tidak ada sintaks untuk mendeklarasikan antarmuka di PowerShell.
Menentukan jenis kustom di PowerShell
Windows PowerShell 5.0 memperkenalkan beberapa elemen bahasa.
Kata kunci kelas
Mendefinisikan kelas baru.
Kata class
kunci adalah jenis .NET Framework yang benar.
Anggota kelas bersifat publik.
class MyClass
{
}
Kata kunci dan enumerasi Enum
Dukungan untuk enum
kata kunci ditambahkan dan merupakan perubahan yang melanggar. Pemisah enum
saat ini adalah baris baru. Solusi sementara bagi mereka yang sudah menggunakan enum
adalah menyisipkan ampersand (&
) sebelum kata. Batasan saat ini: Anda tidak dapat menentukan enumerator dalam hal itu sendiri, tetapi Anda dapat menginisialisasi enum
dalam hal yang lain enum
, seperti yang ditunjukkan dalam contoh berikut:
Tipe dasar saat ini tidak dapat ditentukan. Jenis dasar selalu [int].
enum Color2
{
Yellow = [Color]::Blue
}
Nilai enumerator harus berupa konstanta waktu penguraian. Nilai enumerator tidak dapat diatur ke hasil perintah yang dipanggil.
enum MyEnum
{
Enum1
Enum2
Enum3 = 42
Enum4 = [int]::MaxValue
}
Enum
mendukung operasi aritmatika, seperti yang ditunjukkan dalam contoh berikut:
enum SomeEnum { Max = 42 }
enum OtherEnum { Max = [SomeEnum]::Max + 1 }
Kata kunci tersembunyi
Kata hidden
kunci, yang diperkenalkan di Windows PowerShell 5.0, menyembunyikan anggota kelas dari hasil defaultGet-Member
. Tentukan properti tersembunyi seperti yang diperlihatkan dalam baris berikut:
hidden [type] $classmember = <value>
Anggota tersembunyi tidak ditampilkan dengan menggunakan penyelesaian tab atau IntelliSense, kecuali penyelesaian terjadi di kelas yang menentukan anggota tersembunyi.
Atribut baru, System.Management.Automation.HiddenAttribute, ditambahkan, sehingga kode C# dapat memiliki semantik yang sama dalam PowerShell.
Untuk informasi selengkapnya, lihat [about_Hidden[(/powershell/module/microsoft.powershell.core/about/about_hidden).
Import-DscResource
Import-DscResource
sekarang menjadi kata kunci dinamis yang sebenarnya. PowerShell mengurai modul akar modul yang ditentukan, mencari kelas yang berisi atribut DscResource.
Properti
Bidang baru, ImplementingAssembly
, ditambahkan ke ModuleInfo
. Jika skrip mendefinisikan kelas, atau rakitan yang dimuat untuk modul ImplementingAssembly
biner diatur ke rakitan dinamis yang dibuat untuk modul skrip. Ini tidak diatur ketika ModuleType = Manifest.
Refleksi pada ImplementingAssembly
bidang menemukan sumber daya dalam modul. Ini berarti Anda dapat menemukan sumber daya yang ditulis dalam PowerShell atau bahasa terkelola lainnya.
Bidang dengan penginisialisasi.
[int] $i = 5
Statis didukung dan berfungsi seperti atribut, mirip dengan batasan jenis, sehingga dapat ditentukan dalam urutan apa pun.
static [int] $count = 0
Jenis bersifat opsional.
$s = "hello"
Semua anggota bersifat publik. Properti memerlukan garis baru atau titik koma. Jika tidak ada jenis objek yang ditentukan, jenis properti adalah Objek.
Konstruktor dan instansiasi
Kelas PowerShell dapat memiliki konstruktor yang memiliki nama yang sama dengan kelasnya. Konstruktor dapat kelebihan beban. Konstruktor statis didukung.
Properti dengan ekspresi inisialisasi diinisialisasi sebelum menjalankan kode apa pun dalam konstruktor. Properti statis diinisialisasi sebelum isi konstruktor statis, dan properti instans diinisialisasi sebelum isi konstruktor non-statis. Saat ini, tidak ada sintaks untuk memanggil konstruktor dari konstruktor lain seperti sintaks C#: ": this()")
. Solusinya adalah menentukan metode Init umum.
Berikut ini adalah cara membuat instans kelas:
Membuat instans dengan menggunakan konstruktor default. Perhatikan bahwa
New-Object
tidak didukung dalam rilis ini.$a = [MyClass]::new()
Memanggil konstruktor dengan parameter .
$b = [MyClass]::new(42)
Meneruskan array ke konstruktor dengan beberapa parameter
$c = [MyClass]::new(@(42,43,44), "Hello")
Untuk rilis ini, nama jenis hanya terlihat secara leksikal, yang berarti tidak terlihat di luar modul atau skrip yang menentukan kelas . Fungsi dapat mengembalikan instans kelas yang ditentukan dalam PowerShell, dan instans berfungsi dengan baik di luar modul atau skrip.
Parameter Get-Member
Statis mencantumkan konstruktor, sehingga Anda dapat melihat kelebihan beban seperti metode lainnya. Performa sintaks ini juga jauh lebih cepat daripada New-Object
.
Metode pseudo-static bernama baru berfungsi dengan jenis .NET, seperti yang ditunjukkan dalam contoh berikut. [hashtable]::new()
Sekarang Anda dapat melihat kelebihan beban konstruktor dengan Get-Member
, atau seperti yang ditunjukkan dalam contoh ini:
[hashtable]::new
OverloadDefinitions
-------------------
hashtable new()
hashtable new(int capacity)
hashtable new(int capacity, float loadFactor)
Metode
Metode kelas PowerShell diimplementasikan sebagai ScriptBlock yang hanya memiliki blok akhir. Semua metode bersifat publik. Berikut ini menunjukkan contoh mendefinisikan metode bernama DoSomething.
class MyClass
{
DoSomething($x)
{
$this._doSomething($x) # method syntax
}
private _doSomething($a) {}
}
Pemanggilan metode
Metode yang kelebihan beban didukung. Metode yang kelebihan beban dinamai sama dengan metode yang ada tetapi dibedakan oleh nilai yang ditentukan.
$b = [MyClass]::new()
$b.DoSomething(42)
Invokasi
Lihat Pemanggilan metode.
Atribut
Tiga atribut baru ditambahkan: DscResource
, , DscResourceKey
dan DscResourceMandatory
.
Jenis yang ditampilkan
Jenis pengembalian adalah kontrak. Nilai yang dikembalikan dikonversi ke jenis yang diharapkan. Jika tidak ada jenis pengembalian yang ditentukan, jenis pengembalian akan batal. Tidak ada streaming objek dan objek yang tidak dapat ditulis ke alur baik secara sengaja atau tidak sengaja.
Pencakupan leksikal variabel
Berikut ini menunjukkan contoh cara kerja pencakupan leksikal dalam rilis ini.
$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
Contoh: Membuat kelas kustom
Contoh berikut membuat beberapa kelas kustom baru untuk mengimplementasikan Html Dynamic Stylesheet Language (DSL). Contoh menambahkan fungsi pembantu untuk membuat jenis elemen tertentu sebagai bagian dari kelas elemen, seperti gaya judul dan tabel, karena jenis tidak dapat digunakan di luar lingkup modul.
# 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 }
Lihat juga
Membangun Sumber Daya Konfigurasi Status yang Diinginkan PowerShell Kustom
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk