Wie erstelle ich einen benutzerdefinierten Typ in Powershell für meine Skripte zu benutzen?
-
09-06-2019 - |
Frage
Ich möchte in der Lage sein, einen benutzerdefinierten Typ in einigen meiner Powershell-Skripts zu definieren und zu verwenden. Zum Beispiel, lassen Sie sich so tun, als ich ein Bedürfnis für ein Objekt hatte die folgende Struktur hatte:
Contact
{
string First
string Last
string Phone
}
Wie würde ich mich darüber zu schaffen, so dass ich es in der Funktion wie folgt verwenden:
function PrintContact
{
param( [Contact]$contact )
"Customer Name is " + $contact.First + " " + $contact.Last
"Customer Phone is " + $contact.Phone
}
Ist so etwas wie dies möglich ist, oder auch in Powershell zu empfehlen?
Lösung
Erstellen von benutzerdefinierten Typen können in Powershell ausgeführt werden.
Kirk Munro hat eigentlich zwei große Beiträge, die detailliert den Prozess gründlich.
- Naming Benutzerdefinierte Objekte
- Definieren von Standardeigenschaften für benutzerdefinierte Objekte
Das Buch Windows Powershell in der Aktion von Manning auch ein Codebeispiel hat eine domänenspezifische Sprache für die Erstellung von benutzerdefinierte Typen zu erstellen. Das Buch ist rundum ausgezeichnet, so dass ich es wirklich nur empfehlen.
Wenn Sie nur für einen schnellen Weg suchen, um die oben genannten zu tun, könnten Sie eine Funktion erstellen, das benutzerdefinierte Objekt wie
erstellenfunction New-Person()
{
param ($FirstName, $LastName, $Phone)
$person = new-object PSObject
$person | add-member -type NoteProperty -Name First -Value $FirstName
$person | add-member -type NoteProperty -Name Last -Value $LastName
$person | add-member -type NoteProperty -Name Phone -Value $Phone
return $person
}
Andere Tipps
Vor der Powershell 3
Powershell Extensible Type System ursprünglich nicht lassen Sie konkrete Typen erstellen Sie gegen die Art und Weise testen, können Sie in Ihrem Parameter haben. Wenn Sie nicht diesen Test benötigen, sind Sie mit einer der anderen oben genannten Verfahren in Ordnung.
Wenn Sie eine tatsächliche Art wollen, den Sie oder werfen können Typ-Check mit, wie in Ihrem Beispiel Skript ... es nicht , ohne es zu schreiben in C # oder VB.net erfolgen und Kompilieren . In Powershell 2 können Sie den "Add-Type" Befehl verwenden, es zu tun recht simmple:
add-type @"
public struct contact {
public string First;
public string Last;
public string Phone;
}
"@
Historische Anmerkung : In Powershell 1 war es noch schwieriger. Sie mussten manuell CodeDom verwenden, gibt es eine sehr alte Funktion ist new-Struktur Skript auf PoshCode.org die helfen. Ihr Beispiel wird:
New-Struct Contact @{
First=[string];
Last=[string];
Phone=[string];
}
Mit Add-Type
oder New-Struct
lassen Sie tatsächlich die Klasse in Ihrem param([Contact]$contact)
testen und neue zu verwenden $contact = new-object Contact
machen und so weiter ...
In Powershell 3
Wenn Sie nicht eine „echte“ Klasse benötigen, die Sie werfen können, müssen Sie nicht die Add-Member Art und Weise verwenden, die a href <= "https://stackoverflow.com/a/59980/ 8718" > Steven und andere haben oben gezeigt .
Da Powershell 2 Sie den -Property Parameter für New-Object verwenden:
$Contact = New-Object PSObject -Property @{ First=""; Last=""; Phone="" }
Und in Powershell 3, wir haben die Fähigkeit, den PSCustomObject
Beschleuniger zu verwenden, um einen Type-Namen hinzuzufügen:
[PSCustomObject]@{
PSTypeName = "Contact"
First = $First
Last = $Last
Phone = $Phone
}
Sie sind immer noch nur ein einzelnes Objekt bekommen, so dass Sie eine New-Contact
Funktion sicherstellen sollen, dass jedes Objekt aus dem gleichen kommt, aber Sie können nun einfach einen Parameter überprüfen „ist“ ein jene Art von einem Parameter Dekoration mit dem PSTypeName
Attribute:
function PrintContact
{
param( [PSTypeName("Contact")]$contact )
"Customer Name is " + $contact.First + " " + $contact.Last
"Customer Phone is " + $contact.Phone
}
In Powershell 5
In Powershell 5 alles verändert, und wir haben schließlich class
und enum
als Sprache Schlüsselwörter für Typen definieren (es gibt keine struct
aber das ist ok):
class Contact
{
# Optionally, add attributes to prevent invalid values
[ValidateNotNullOrEmpty()][string]$First
[ValidateNotNullOrEmpty()][string]$Last
[ValidateNotNullOrEmpty()][string]$Phone
# optionally, have a constructor to
# force properties to be set:
Contact($First, $Last, $Phone) {
$this.First = $First
$this.Last = $Last
$this.Phone = $Phone
}
}
Wir haben auch eine neue Möglichkeit, Objekte zu erstellen, ohne New-Object
: [Contact]::new()
- in der Tat, wenn Sie Ihre Klasse einfach gehalten und nicht definieren einen Konstruktor, können Sie Objekte erstellen, indem eine Hash-Tabelle Gießen (wenn auch ohne einen Konstruktor, gäbe es keine Möglichkeit, erzwingen, dass alle Eigenschaften eingestellt werden müssen):
class Contact
{
# Optionally, add attributes to prevent invalid values
[ValidateNotNullOrEmpty()][string]$First
[ValidateNotNullOrEmpty()][string]$Last
[ValidateNotNullOrEmpty()][string]$Phone
}
$C = [Contact]@{
First = "Joel"
Last = "Bennett"
}
Dies ist die Abkürzung Methode:
$myPerson = "" | Select-Object First,Last,Phone
Steven Murawski Antwort ist groß, aber ich mag das kürzere (oder besser gesagt nur das sauberere select-Objekt anstelle von Add-Mitglied Syntax):
function New-Person() {
param ($FirstName, $LastName, $Phone)
$person = new-object PSObject | select-object First, Last, Phone
$person.First = $FirstName
$person.Last = $LastName
$person.Phone = $Phone
return $person
}
überraschte niemand diese einfache Möglichkeit erwähnt (vs 3 oder höher) zum Erstellen von benutzerdefinierten Objekten:
[PSCustomObject]@{
First = $First
Last = $Last
Phone = $Phone
}
Der Typ PSCustomObject sein wird, nicht ein tatsächlicher benutzerdefinierter Typ though. Aber es ist wahrscheinlich der einfachste Weg, um ein benutzerdefiniertes Objekt zu erstellen.
Es ist das Konzept der PSObject und Add-Member, die Sie verwenden können.
$contact = New-Object PSObject
$contact | Add-Member -memberType NoteProperty -name "First" -value "John"
$contact | Add-Member -memberType NoteProperty -name "Last" -value "Doe"
$contact | Add-Member -memberType NoteProperty -name "Phone" -value "123-4567"
Das gibt wie:
[8] » $contact
First Last Phone
----- ---- -----
John Doe 123-4567
Die andere Alternative (das ich kenne) ist eine Art in C # / VB.NET zu definieren und diese Baugruppe in Powershell für den Einsatz direkt geladen werden.
Dieses Verhalten wird auf jeden Fall empfohlen, weil es andere Skripte oder Abschnitte der Skripts Arbeit mit einem tatsächlichen Objekt ermöglicht.
Hier ist der harte Weg benutzerdefinierte Typen zu erstellen und speichern sie in einer Sammlung.
$Collection = @()
$Object = New-Object -TypeName PSObject
$Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail')
Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "John"
Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe"
Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "123-4567"
$Collection += $Object
$Object = New-Object -TypeName PSObject
$Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail')
Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "Jeanne"
Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe"
Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "765-4321"
$Collection += $Object
Write-Ouput -InputObject $Collection