Wie erstelle ich einen benutzerdefinierten Typ in Powershell für meine Skripte zu benutzen?

StackOverflow https://stackoverflow.com/questions/59819

  •  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?

War es hilfreich?

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.

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

erstellen
function 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top