preloader
30 June 2011 / #.net #Powercli #Powershell

Création d’un cmdlet Powershell [Partie3]

post-thumb

Suite de l’article Création d’un cmdlet Powershell [Partie2]

Dans l’article précédent, nous avons vu l’interface entre les WebServices de PxeManager et notre code.

Dans ce billet, on détaillera un exemple de code relativement simple (il en faut forcement :p) et son utilisation en Powershell.

On va mettre l’exemple de code au début et on reviendra ligne par ligne ensuite en détaillant autant qu’on peut ^^ (à la manière du Master LucD).

Exemple de code et explication

Le code suivant correspond à la création d’un cmdlet Get-PXEInfo qui affichera la version de l’agent PxeManager installé sur le serveur passé en argument.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

namespace PSH_PxeManager
{
    [System.Management.Automation.Cmdlet( System.Management.Automation.VerbsCommon.Get,"PXEInfo")]
    public class Get_PXEInfo : System.Management.Automation.Cmdlet
    {
        [System.Management.Automation.Parameter(
            Position = 0,
            Mandatory = true,
            HelpMessage = "FQDN or IP of PxeManager Agent typed during install")]
        public string Server;

        protected override void BeginProcessing()
        {
            base.BeginProcessing();
        }

        protected override void EndProcessing()
        {
            base.EndProcessing();
        }

        protected override void ProcessRecord()
        {
            if (string.IsNullOrEmpty(this.Server))
            {
                this.WriteObject("HelpUsage");
            }
            else
            {
                vimpxe Svc = new vimpxe();
                Svc.Url = "https://" + Server + ":8733/vgpxe/vgpxe.asmx";
                this.WriteObject(Svc.About());
            }
        }
    }
}

On va découper le code en plusieurs parties et détailler chacune d’elles.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

Cette première partie est simplement la déclaration et l’import des assemblies qui seront utilisées dans le code. Pour le coup, cette déclaration est celle faite par défaut lors de la création d’une nouvelle classe et peut être complétée suivant les besoins.

Dans notre exemple, ces déclarations sont optionnelles vu que notre code ne comporte que très peu d’appel et ne nécessite pas d'assemblies supplémentaire.

Le lien officiel MSDN pour plus d’infos : http://msdn.microsoft.com/fr-fr/library/sf0df423.aspx

[System.Management.Automation.Cmdlet( System.Management.Automation.VerbsCommon.Get,"PXEInfo")]
public class Get_PXEInfo : System.Management.Automation.Cmdlet
{
}

Alors ici, en fait c’est une déclaration d’un nouvelle classe nommée Get_PXEInfo. Cette classe va hériter du type System.Management.Automation.Cmdlet. Cela permet de dire que notre classe servira pour créer un nouveau cmdlet Powershell. Vu que sur l’article précédent nous avons rajouté les références Powershell dans notre projet, le type System.Management.Automation.Cmdlet a une réelle existence et est bien interprété.

Là où c’est très fort, c’est que l’on va définir pour notre classe son trigger de réponse. C’est à dire que notre classe sera instanciée uniquement lors d’un certain appel, ici :

System.Management.Automation.Cmdlet( System.Management.Automation.VerbsCommon.Get,"PXEInfo")

Cet appel lui aussi hérite de System.Management.Automation.Cmdlet et correspond au cmdlet Get-PXEInfo (découpage du cmdlet avec le verbe System.Management.Automation.VerbsCommon.Get et le nom *PXEInfo*)

La encore, tout cela n’est possible que grâce aux ajouts de référence vu dans l’article précédent.

Pour des infos MSDN sur les concepts Powershell Verbe-Nom : http://msdn.microsoft.com/en-us/library/ms714428(v=VS.85).aspx

[System.Management.Automation.Parameter(
    Position = 0,
    Mandatory = true,
    HelpMessage = "FQDN or IP of PxeManager Agent typed during install")]
public string Server;

Cette partie déclare une variable nommée Server de type String. On associe cette variable à un paramètre de notre cmdlet Powershell via la déclaration System.Management.Automation.Parameter.

On retrouve au final la même configuration que l’on peu avoir dans un script Powershell dans la partie PARAM{} (Mandatory, HelpMessage, !)

On peut ainsi définir le comportement qu’aura ce paramètre dans une console Powershell et surtout permet la complétion du nom du paramètre (ie *Get-PXEInfo -S_TAB_* donnera *Get-PXEInfo -Server*).

protected override void BeginProcessing()
{
}

protected override void EndProcessing()
{
}

protected override void ProcessRecord()
{
}

On peut définir les 3 étapes de traitement tel qu’on peut le faire dans un script Powershell via les appels BEGIN{}; END{} et PROCESS{}. Cela permet de vraiment pouvoir contrôler dans notre classe tout le comportement de notre cmdlet.

protected override void ProcessRecord()
{
    if (string.IsNullOrEmpty(this.Server))
    {
        this.WriteObject("HelpUsage");
    }
    else
    {
        vimpxe Svc = new vimpxe();
        Svc.Url = "https://" + Server + ":8733/vgpxe/vgpxe.asmx";
        this.WriteObject(Svc.About());
    }
}

Cela correspond au code de notre cmdlet. Pour l’exemple, on vérifie juste l’existence de notre paramètre Server créé au-dessus.

Ensuite, si le paramètre Server existe et est renseigné, on instancie la classe vimpxe qui s’appuie au final sur les WebServices de PXE Manager comme vu dans l’article 2.

Ainsi, notre objet Svc est un objet de type vimpxe qui s’appuie sur les WebServices de PXE MAnager. On peut donc lui définir des propriétés, ici on définit la propriété Url pour la faire pointer vers l’adresse de l’agent PxeManager.

Cela permet ensuite d’afficher le résultat de la méthode About() qui affichera les informations concernant l’agent.

Génération de la classe en .dll

Une fois le code fini, et la déclaration de votre cmdlet terminée comme vous le voulez, il suffit de compiler votre projet pour générer un fichier .dll qui sera utilisé par la suite.

Pour cela, il suffit de cliquer sur le menu Build puis sur Build Projet :

ScreenShot149

Une fois terminé avec succès, il suffit d’aller chercher le fichier .dll dans le dossier du projet :

ScreenShot150

C’est ce fichier .dll qui sera utilisé dans la console Powershell pour importer notre cmdlet.

Import de la dll dans les modules cmdlet

Vous avez donc à ce niveau un fichier .dll qui contient le code de votre cmdlet préféré !

Le but final étant quan même de l’utiliser dans une console Powershell, on va maintenant l’importer dans les modules.

En Powershel v2, il y a la notion de modules qui correspondent à des extensions de code.

On trouvera donc des modules pour Exchange, SQL, DPM, Windows 2008 ServerManager, AD, !. et pourquoi pas PxeManager ! De base, pour afficher les modules chargés, il suffit d’exécuter dans une console Powershell la commande suivante :

Get-Module

ScreenShot152

Pour notre exemple, on va donc importer notre fichier .dll dans la console Powershell via la commande suivante :

Import-Module <chemin du .dll>

ScreenShot154

dans la colonne ExportedCommands

Utilisation des cmdlet créés

Une fois que le module est chargé, il suffit de lancer notre cmdlet pour voir le résultat en exécutant la commande suivante :

Get-PWEInfo -Server <agentPxe>

ScreenShot156

Et voilà notre premier cmdlet pour s’interfacer avec PxeManager !!!

Cependant, on voit que le retour par défaut n’est pas super user-friendly (nécessité d’étendre la propriété version pour voir tous les numéros de build) et on va essayer dans le dernier article de modifier le comportement par défaut de notre cmdlet pour en faire aussi ce que l’on veut ^^

Note : Si vous avez des erreurs liées à des certificats SSL untrusted de ce type :

ScreenShot157

il suffit soit d’avoir des certificats/chaines de certification valides, soit d’exécuter cette commande Powershell pour bypasser ce test (/mode roots on) :

[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}

> Frederic MARTIN