Comment créer un type personnalisé dans PowerShell que mes scripts pourront utiliser ?

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

  •  09-06-2019
  •  | 
  •  

Question

J'aimerais pouvoir définir et utiliser un type personnalisé dans certains de mes scripts PowerShell.Par exemple, imaginons que j'ai besoin d'un objet ayant la structure suivante :

Contact
{
    string First
    string Last
    string Phone
}

Comment pourrais-je créer ceci pour pouvoir l'utiliser dans des fonctions telles que celles-ci :

function PrintContact
{
    param( [Contact]$contact )
    "Customer Name is " + $contact.First + " " + $contact.Last
    "Customer Phone is " + $contact.Phone 
}

Est-ce que quelque chose comme ça est possible, ou même recommandé dans PowerShell ?

Était-ce utile?

La solution

La création de types personnalisés peut être effectuée dans PowerShell.
Kirk Munro a en fait deux excellents articles qui détaillent en détail le processus.

Le livre Windows PowerShell en action par Manning dispose également d'un exemple de code pour créer un langage spécifique à un domaine afin de créer des types personnalisés.Le livre est excellent à tous points de vue, donc je le recommande vraiment.

Si vous cherchez simplement un moyen rapide de faire ce qui précède, vous pouvez créer une fonction pour créer l'objet personnalisé comme

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
}

Autres conseils

Avant PowerShell 3

Le système de types extensible de PowerShell ne vous permettait pas à l'origine de créer des types concrets que vous pouvez tester comme vous l'avez fait dans votre paramètre.Si vous n'avez pas besoin de ce test, vous pouvez utiliser l'une des autres méthodes mentionnées ci-dessus.

Si vous voulez un type réel vers lequel vous pouvez effectuer un cast ou une vérification de type, comme dans votre exemple de script...il ne peut pas être fait sans l'écrire en C# ou VB.net et sans compiler.Dans PowerShell 2, vous pouvez utiliser la commande « Add-Type » pour le faire assez simplement :

add-type @"
public struct contact {
   public string First;
   public string Last;
   public string Phone;
}
"@

Note historique:Dans PowerShell 1, c'était encore plus difficile.Il fallait utiliser CodeDom manuellement, il existe une fonction très ancienne nouvelle structure script sur PoshCode.org qui vous aidera.Votre exemple devient :

New-Struct Contact @{
    First=[string];
    Last=[string];
    Phone=[string];
}

En utilisant Add-Type ou New-Struct vous permettra de tester la classe dans votre param([Contact]$contact) et créez-en de nouveaux en utilisant $contact = new-object Contact et ainsi de suite...

Dans PowerShell 3

Si vous n'avez pas besoin d'une "vraie" classe vers laquelle vous pouvez caster, vous n'êtes pas obligé d'utiliser la méthode Add-Member qui Steven et d'autres ont démontré au-dessus de.

Depuis PowerShell 2, vous pouvez utiliser le paramètre -Property pour New-Object :

$Contact = New-Object PSObject -Property @{ First=""; Last=""; Phone="" }

Et dans PowerShell 3, nous avons la possibilité d'utiliser le PSCustomObject accélérateur pour ajouter un TypeName :

[PSCustomObject]@{
    PSTypeName = "Contact"
    First = $First
    Last = $Last
    Phone = $Phone
}

Vous n'obtenez toujours qu'un seul objet, vous devriez donc créer un New-Contact pour vous assurer que chaque objet sort de la même manière, mais vous pouvez maintenant facilement vérifier qu'un paramètre "est" de ce type en décorant un paramètre avec le PSTypeName attribut:

function PrintContact
{
    param( [PSTypeName("Contact")]$contact )
    "Customer Name is " + $contact.First + " " + $contact.Last
    "Customer Phone is " + $contact.Phone 
}

Dans PowerShell 5

Dans PowerShell 5, tout change et nous avons finalement obtenu class et enum comme mots-clés de langage pour définir les types (il n'y a pas struct mais ça va):

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
    }
}

Nous avons également une nouvelle façon de créer des objets sans utiliser New-Object: [Contact]::new() -- en fait, si vous gardez votre classe simple et ne définissez pas de constructeur, vous pouvez créer des objets en convertissant une table de hachage (bien que sans constructeur, il n'y aurait aucun moyen d'imposer que toutes les propriétés doivent être définies) :

class Contact
{
    # Optionally, add attributes to prevent invalid values
    [ValidateNotNullOrEmpty()][string]$First
    [ValidateNotNullOrEmpty()][string]$Last
    [ValidateNotNullOrEmpty()][string]$Phone
}

$C = [Contact]@{
   First = "Joel"
   Last = "Bennett"
}

Voici la méthode de raccourci :

$myPerson = "" | Select-Object First,Last,Phone

La réponse de Steven Murawski est excellente, mais j'aime l'objet de sélection plus court (ou plutôt simplement l'objet de sélection plus soigné au lieu d'utiliser la syntaxe d'ajout de membre) :

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
}

Surpris, personne n'a mentionné cette option simple (vs 3 ou version ultérieure) pour créer des objets personnalisés :

[PSCustomObject]@{
    First = $First
    Last = $Last
    Phone = $Phone
}

Le type sera PSCustomObject, mais pas un type personnalisé réel.Mais c’est probablement le moyen le plus simple de créer un objet personnalisé.

Il existe le concept de PSObject et Add-Member que vous pouvez utiliser.

$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"

Cela donne comme :

[8] » $contact

First                                       Last                                       Phone
-----                                       ----                                       -----
John                                        Doe                                        123-4567

L'autre alternative (à ma connaissance) consiste à définir un type en C#/VB.NET et à charger cet assembly dans PowerShell pour une utilisation directe.

Ce comportement est définitivement encouragé car il permet à d'autres scripts ou sections de votre script de fonctionner avec un objet réel.

Voici le chemin difficile pour créer des types personnalisés et les stocker dans une collection.

$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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top