vendredi 16 mai 2008

PowerShell et ASP.NET Part 1

English Version Available here

Comme nous l'avons vu, PowerShell permet de créer des interfaces graphiques en passant par les winforms .NET. Ainsi, nous pouvons créer des interfaces pour piloter nos scripts. C'est un vrai plus, d'autant que des outils comme AdminScriptEditor rendent cela particulièrement simple.

Dans mes peregrinations, une question m'est revenue assez souvent :

comment pourrait-on intégrer facilement PowerShell avec une page web ?

A juste titre, utiliser un portail web plutôt que des winforms "clients lourds" apporte plusieurs avantages indéniables :

· Pas besoin d'installer PowerShell ou des Snapins sur l'ensemble des postes d'admins pour utiliser des scripts (je pense par exemple aux interfaces de provisioning Active Directory, un gestionnaire de machines virtuelles, etc... )

· ... Donc pouvoir centraliser et déléguer l'administration facilement

· Filtrer l'accès et l'utilisation de Powershell dans l'entreprise (tout s'exécute du serveur et non du poste)

· Traçabilité : d'un point unique, on peut savoir qui fait quoi, et potentiellement gérer le CTRL+Z salvateur

· Peut s'implémenter sur le portail d'entreprise (Sharepoint ou autre)

Tout ceci serait formidable, mais ne va pas sans quelques inconvenients, du moins au premier abord pour qui n'a jamais touché un site ASP.NET :

· Développer en asp.net et C# s'éloigne résolument du scripting.
· Les exemples de méthodes d'invocation de PowerShell via C# ne donne pas forcément envie à un profil infra de se lancer dans le bain.
· On peut alors plutôt s'orienter sur du developpement C# pour arriver au résultat......
· Or il faut avoir la chance d'avoir un developpeur .NET pur et dur sous la main.

C'est pourquoi je vous soumet ici un premier exemple d'interaction très simple entre une page ASP.NET et du script Powershell, qui prend le problème sous un angle plus "InfraPeople-Compliant". Pour rendre les choses plus digestes, nous allons séparer les choses :

· ASP.NET et C# pour gérer uniquement l'interface utilisateur
· Appel de code powershell pur et non de bloc dans du code C#
· Dialogue entre l'output de PowerShell et le site web pour suivre la progression des commandes.

Ceci permet de bien séparer les 2 aspects du portail, et de garder ainsi PowerShell comme moteur de traitement tels qu'on a l'habitude de l'utiliser en scripting classique.

Comme nous allons le voir au cours de ce tutorial, le code est plutôt simple et la page très légère : et pourtant avec ceci nous allons pouvoir effectuer des commandes complexes et riches grâce à PowerShell.

update : Voici une petite vidéo de l'exemple pour vous donner une idée



Je ne vais pas faire ici un cours sur ASP.NET, car d'une part je ne suis pas le mieux placé pour le faire, d'autre part comme vous allez le voir nous n'allons utiliser que les fondamentaux pour arriver à nos fins.

Reste quelques notions de bases indispensables pour pouvoir saisir la suite :

Quelques bases ASP.NET

Pour parler très schématiquement avec une bonne dose de simplification, on peut concevoir une site ASP.NET comme une page HTML qui pourrait faire exécuter du code .NET côté serveur, et non uniquement via le browser côté poste client.

Voici un exemple qui va être notre premier projet. Notez que nous pouvons (et allons!) utiliser la version gratuite de Visual Studio pour le web : Visual Studio Web developper Express Edition que je vous invite à télécharger. Cette version est tout à fait adaptée à nos besoins et nous permettra de prendre en charge l'ensemble du développement, ne nous privons pas. Vous aurez aussi besoin des Ajax Control Toolkit et library à télécharger ici .

Un site ASP.NET à minima est composé des éléments suivants :

Une page ASP.NET (par défaut ici : default.aspx) : c'est elle qui heberge le code de l'interface e la page (les boutons, cases et autres joyeusetés), au format html et ASP. On y trouve aussi souvent du javascript, mais ceci n'est pas important ni utilisé pour notre exemple.

Un fichier .cs correspondant à la page ASPX (ici : default.aspx.cs) : c'est ce fichier qui contient ce que l'on appelle le "code-behind". C'est le code côté serveur qui sera invoqué par l'interaction entre l'utilisateur et la page. Ce code est dans un langage .NET (C# ou VB.NET). Dans notre cas nous allons utiliser C# qui est proche de PowerShell dans sa structure.

web.config : fichier de configuration du site web. Pour faire simple, on y trouve la configuration du site asp, méthode d'authentification, invocation des DLL (dans notre cas celles qui permettent d'exécuter le code PowerShell), etc..

Bien sûr, l'outil de developpement nous facilite la tâche, et tout est pré-configuré quand vous créez un nouveau projet. Avant de rentrer concrètement sur la création de notre page ASP.NET, voici la technique utilisée pour faire appel à nos scripts d'un formulaire :

La stratégie d'invocation de PowerShell

Le schéma ci-dessous présente la stratégie utilisée pour cet exemple d'invocation de PowerShell par ASP.NET, que nous allons décrire en détail dans la seconde partie de ce tutorial :


Notre site comporte 2 textbox, une pour taper un script, l'autre pour récupérer le retour eventuel généré par ce script, et un bouton pour lancer l'exécution : le tour est joué. Comme vous le voyez, côté interface on est plutôt dans quelque chose de basique.

Le principe est assez simple, nous allons y revenir en détail dans la partie 2 de ce tutorial, mais voici les bases :

Quand on clique sur le bouton "Executer" voici ce qu'il se passe:

On active un Timer (1), je reviendrai sur ce point plus tard, mais disons pour le moment qu'il s'agit d'un mécanisme qui exécute du code en boucle à une fréquence donnée (d'où le nom de Timer d'ailleurs).

Dans le même temps, le code-behind invoque un runspace et un pipeline PowerShell en asynchrone, prend le contenu de la première Textbox et l'exécute dans le pipeline (2).

Toute les secondes, notre timer vérifie la sortie du pipeline (3) et inscrit ce qu'il trouve dans une variable spéciale dites "de session" (4) (on verra pourquoi dans la seconde partie).

On rafraichit la Textbox de sortie avec le contenu de la variable de session (5). Le timer repart jusqu'à la liberation du pipeline (6).

L'utilisation du Timer nous permet d'avoir une vue relativement temps réel de la sortie du script, du moins toute les secondes. Notez que le script n'est pas obligé d'avoir une sortie : comme tout script PowerShell, il peut se passer plein de choses sans rien voir dans la console, donc prenez garde a ce que vous codez ;).

J'ai gardé le code le plus simple possible pour vous permettre d'identifier les différentes fonctions facilement. Nous enrichirons plus tard notre interface une fois que nous aurons vu la composition du code dans la seconde partie de ce tutorial.

Notez toutefois que nous utilisons un peu d'AJAX pour gérer la seconde boite de dialogue : Ajax nous permet ici de rafraichir la boite seule sans rafraichir toute la page. Nous verrons dans la seconde partie qu'intégrer ce type de composant AJAX avec ASP.NET est très facile, des composants prêt à l'emploi sont fournis sans avoir à coder la moindre ligne de javascript ni d'XML.

Pour le moment vous pouvez déjà tester ce site en ouvrant tout simplement le projet en pièce jointe à cet article avec Web developper Express.

Tapez votre script dans la textbox du haut, le résultat s'affichera en bas.

Note : le script s'exécute côté serveur (ici si vous faites un test en local, c'est sur votre machine que le script s'exécute.) Notez que nous récupérons la sortie "objet" de PowerShell : c'est pour cela que j'utilise dans cet exemple le cmdlet "out-string" pour afficher en sortie ce qui apparaitrait dans la console.

vous pouvez bien sûr lancer n'importe quelle commande Powershell (attention donc aux fausses manips :) ). Le site est "light" pour vous permettre de bien saisir le code : point de contrôle d'erreurs ni fioritures côté interface.

Nous verrons dans la seconde partie comment est articulé le code, comment piloter un script avec un formulaire et les questions relatives à la sécurité.

Voici la source : PowerShellASP.zip , n'hésitez pas à poser vos questions en commentaire !

mardi 8 avril 2008

Mindmap PowerShell avec Silverlight

English version available here

Michael S. Scherotter propose sur son blog synergist une application permettant de convertir des mindmap créés avec MindManager en silverlight.

C'est amusant, facile à utiliser et très inspirant pour l'intégration de Silverlight et du mindmapping dans notre vie de développeurs infrastructure de tous les jours :)

Pour illustrer ceci, je vous ai mis ci-dessous un exemple de mindmap avec différentes ressources sur PowerShell. Blogger me limitant un peu sur la taille de la zone de texte, n'hésitez pas à utiliser le bouton "full screen" en haut à droite du contrôle silverlight. Les liens sont bien sûr utilisables.

lundi 7 avril 2008

PowerShell et SCCM Part 2

PowerShell et SCCM Part 2

English Version available here

Intégration de l'ordinateur dans une collection spécifique

Ok, notre ordinateur est inscrit dans SCCM, voyons maintenant comment l'inscrire dans une collection spécifique. Que nous dit le SDK ? l'exemple VBScript est le suivant :

' Add the computer to the all systems collection.
set collection = connection.Get("SMS_Collection.CollectionID='SMS00001'")
set collectionRule=connection.Get("SMS_CollectionRuleDirect").SpawnInstance_
collectionRule.ResourceClassName="SMS_R_System"
collectionRule.ResourceID= outParams.ResourceID
collection.AddMembershipRule collectionRule

Qu'on peut organiser comme suit pour plus de facilité de compréhension :

set collectionRule=connection.Get("SMS_CollectionRuleDirect").SpawnInstance_ collectionRule.ResourceClassName="SMS_R_System" collectionRule.ResourceID= outParams.ResourceID

set collection = connection.Get("SMS_Collection.CollectionID='SMS00001'")
collection.AddMembershipRule collectionRule

L'exemple nous parle de la collection "All Systems", mais comme nous l'avons vu, le fait de déclarer un ordinateur dans SCCM l'inscrit par défaut dans cette collection. Par contre, cet exemple nous donne tout les éléments utiles : il nous montre qu'il faut créer un objet de type "SMS_CollectionRuleDirect", le paramétrer, puis invoquer la méthode AddMemberShiprule avec cet objet en paramètre.

Allons y donc tranquillement, étape par étape

Créer un objet issue de la classe SMS_CollectionRuleDirect

Pour instancier une classe WMI en PowerShell, on peut utiliser la syntaxe suivante :

$objColRuledirect = [WmiClass]"\\$Computer\ROOT\SMS\site_001:SMS_CollectionRuleDirect"

On voit qu'en passant par les psbase.properties les 3 propriétés de l'objet :

Nous avons vu dans l'exemple du SDK que deux propriétés sont à renseigner :

  • ResourceClassName avec la valeur "SMS_R_System"
  • ResourceID avec la propriété ResourceID de l'objet ordinateur créé précédemment

Soit en PowerShell :

$objColRuleDirect.psbase.properties["ResourceClassName"].value = "SMS_R_System"
$objColRuleDirect.psbase.properties["ResourceID"].value = $objCMComputer.resourceID

On voit ci dessous les propriétés de l'objet ordinateur créé comme dans la Part 1 et notre objet CollectionRuleDirect proprement configuré :

Il ne nous reste plus à présent qu'à utiliser cet objet avec la classe SMS_Collection

Utiliser la méthode AddMemberShipRule de la classe SMS_Collection

Qui dit méthode WMI, dit petit coup d'oeil dans WmiExplorer pour avoir notre exemple pré-maché (qui a dit feignant ?) :

Ce qu'il nous faut en paramètre, c'est l'ID de la collection cible. Alors ici 2 options : soit utiliser en dur l'ID de la collection que l'on trouve dans la console SCCM (pas sport), ou déterminer l'ID de la collection par son nom (sport)

Soyons sportif, allons à la pêche à l'ID avec Powershell !

C'est ici très simple, créons "classiquement" une connexion à la classe SMS_Collection, et filtrons sur le nom de notre collection (ici dans mon exemple "PowerShell Collection")

$Collection = gwmi -computer $computer -namespace "root\sms\site_001" -class "SMS_Collection" $PoshCollec = $collectionwhere{$_.Name -eq "PowerShell Collection"}

Il ne nous reste plus qu'à adapter le code de WmiExplorer avec comme CollectionID l'ID issu de cet objet, et comme CollectionRule, l'objet que l'on a créé à l'étape précédente :

$Class = "SMS_Collection"
$Method = "AddMembershipRule"
$CollectionID = $PoshCollec.CollectionID
$filter="CollectionID = '$CollectionID'"
$MC = Get-WmiObject $class -computer $Computer -Namespace "ROOT\SMS\site_001" -filter $filter
$InParams = $mc.psbase.GetMethodParameters($Method)
$InParams.collectionRule = $objColRuleDirect
$inparams.PSBase.properties select name,Value Format-Table
$R = $mc.PSBase.InvokeMethod($Method, $inParams, $Null)

Voilà le travail : notre ordinateur est à présent inscrit dans la collection "PowerShell Collection".

Avec un peu de recherche, et la bonne compréhension des techniques expliquées dans ce message, vous devriez pouvoir créer tout type de script PowerShell autour de SCCM. Notez aussi que la plupart des codes sont aussi utilisable dans SMS ;)

Ci-dessous un exemple complet des différents extraits :

**************************************************************************

## Nom : Script d'import de machine dans SCCM
## Auteur : Antoine Habert
devinfra@gmail.com

### Variables
$strTargetMac = "0A:0B:0C:0D:0E:0F"
$strTargetComputerAccount = "NomDeMachine"
$computer = "."
$strTargetCollection = "La collection cible"

# Create computer in SCCM
$Class = "SMS_Site"
$Method = "ImportMachineEntry"
$MC = [WmiClass]"\\$Computer\ROOT\SMS\site_001:$Class"
$InParams = $mc.psbase.GetMethodParameters($Method)
$InParams.MACAddress = $strTargetMac
$InParams.NetbiosName = $strTargetComputerAccount
$InParams.OverwriteExistingRecord = $true
$inparams.PSBase.properties select name,Value Format-Table
$objCMComputer = $mc.PSBase.InvokeMethod($Method, $inParams, $Null)

# Create Collection Rule Direct
$objColRuledirect = [WmiClass]"\\$Computer\ROOT\SMS\site_001:SMS_CollectionRuleDirect"
$objColRuleDirect.psbase.properties["ResourceClassName"].value = "SMS_R_System"
$objColRuleDirect.psbase.properties["ResourceID"].value = $objCMComputer.resourceID


# Target Collection connection
$Collection = gwmi -computer $computer -namespace "root\sms\site_001" -class "SMS_Collection"
$PoshCollec = $collectionwhere{$_.Name -eq $strTargetCollection}

# Add Computer to Target Collection
$Class = "SMS_Collection"
$Method = "AddMembershipRule"
$CollectionID = $PoshCollec.CollectionID
$filter="CollectionID = '$CollectionID'"
$MC = Get-WmiObject $class -computer $Computer -Namespace "ROOT\SMS\site_001" -filter $filter
$InParams = $mc.psbase.GetMethodParameters($Method)
$InParams.collectionRule = $objColRuleDirect

$inparams.PSBase.properties select name,Value Format-Table

$R = $mc.PSBase.InvokeMethod($Method, $inParams, $Null)

**************************************************************************

vendredi 4 avril 2008

Webcast PowerShell en ligne

Les webcasts des techdays sont en ligne !

Hormis le fameux et implacable "demo effect" venu titiller la douce quiétude du déroulement de la session, vous y trouverez normalement quelques infos interessantes sur PowerShell et les solutions infrastructure Microsoft Retrouvez notre présentation ici

Une "Charentaise Edition", mitonnée à la maison (enfin disons sur mon lieu de travail) est disponible sur le site de Neos-SDI, plus complète.

Je vais poster différents tutoriaux liés à cette session (le premier est déjà disponible sous ce message)

N'hésitez pas à me laisser des commentaires ou des demandes d'infos ici.

Sur ce, bon film !

PowerShell et SCCM Part 1

PowerShell et SCCM (Part 1)

ENGLISH version available here

Introduction

Contrairement à SCVMM ou Exchange 2007, SCCM ne propose pas nativement de cmdlets... Par contre, joie, SCCM expose l’ensemble de ses fonctionnalités via WMI. Nous allons voir ensemble comment utiliser les classes, méthodes et propriétés de SCCM avec PowerShell (Ceci est aussi valable pour SMS).

Avant de commencer

Pour vous faciliter la vie, 2 téléchargements sont nécessaires :
  • Premièrement, téléchargez le SDK de SCCM fraichement
    disponible ici

  • Prenez aussi le WMI Explorer de MOW qui va vous faciliter le
    code pour SCCM comme nous allons le voir plus loin
Premier script

Il y a quelques subtilités à connaitre pour pouvoir exploiter les méthodes WMI exposées par SCCM.

Commençons par découvrir les namespaces, Lancez wmiexplorer sur votre serveur SCCM
Un namespace "ROOT\SMS" est présent, au deuxième niveau, vous verrez «ROOT\SMS\inv_schema » que nous allons ignorer pour le moment, et en dessous un namespace normé "ROOT\SMS\site_nomdusite"

Double-cliquez sur l’instance d’un site pour faire apparaitre les classes :

Les 570 (!) classes exposées vont apparaitre en bas à gauche. Oui ça fait du monde, mais rassurez vous nous allons pouvoir faire le tri facilement en fonction de notre besoin.

Pour notre premier exemple, nous allons créer un script pour ajouter un ordinateur à une collection. Dans un premier temps, jetons un œil au SDK pour trouver la classe qui nous intéresse.


Ici, on voit à droite que l’ajout d’un ordinateur passe par la méthode « ImportMachineEntry » de la classe SMS_Site. Le SDK montre généralement des exemples de code VB/C# ou vbs, mais la syntaxe PowerShell diffère comme nous allons le voir plus loin. L’important ici pour nous est d’identifier la classe et la méthode utilisée pour accomplir la tâche.

Dans l’exemple vbscript du SDK, on constate qu’il faut passer par un connection.get pour instancier la classe, puis faire un spawnInstance de la méthode, charger les paramètres requis (macaddress, netbiosname…) puis utiliser ExecMethod..

' Connect
Set siteClass = connection.Get("SMS_Site")
Set inParams = siteClass.Methods_("ImportMachineEntry"). _
inParameters.SpawnInstance_()

' Add the input parameters.
inParams.Properties_.Item("MACAddress") = macAddress
inParams.Properties_.Item("NetbiosName") = netBiosName
inParams.Properties_.Item("OverwriteExistingRecord") = False
inParams.Properties_.Item("SMBIOSGUID") = smBiosGuid

' Add the computer
Set outParams = connection.ExecMethod("SMS_Site", "ImportMachineEntry", inParams)

La question qui nous brûle le clavier est donc :

comment faire la même chose en PowerShell ?
Utilisons wmiExplorer de MoW pour trouver la réponse :

On double clique sur la classe SMS_Site pour inventorier les propriétés et méthodes de la classe. Vous constaterez qu’à droite, il existe effectivement une méthode appelée « ImportMachineEntry »

Double Cliquez sur cette méthode. L’intérêt du WmiExplorer de MoW est qu’il permet d’obtenir des exemples d’utilisation des méthodes WMI :

Comble du raffinement, il donne un exemple de script et énumère les différents paramètres à renseigner avec leur type (string, booléen,etc..)... Concrètement, il ne nous reste plus qu’à renseigner cet exemple avec les paramètres nécessaires :
  • MacAddress (addresse MAC de la machine à importer)
  • NetbiosName (Nom de la machine dans l’inventaire SCCM), etc…
Détaillons un peu ce script pour comprendre le fonctionnement de l’invocation de méthode de cette classe :

Quand on créé notre connexion à la classe SMS_Site et qu’on liste comme ci-dessus l’objet $mc, on voit qu’il n’affiche que « SMS_Site »

En faisant un Get_Member, on constate qu’il n’y a pas de méthode « ImportMachineEntry » d’exposée. Cela vient du formatage des objets propres à PowerShell. Pour avoir accès aux propriétés et méthodes de cette classe, il faut passer par la méthode psbase de powershell pour avoir un accès « RAW » à l’objet (Plus d’info sur psbase ici) :



On voit ici que $mc.psbase nous propose effectivement "Methods" et "Properties". Listons maintenant les méthodes :



On retrouve effectivement notre méthode ImportMachineEntry. Dans l’exemple vbscript du SDK, on voit qu’il faut faire un spawnInstance pour définir les paramètres de la méthode :

Set inParams = siteClass.Methods_("ImportMachineEntry"). _
inParameters.SpawnInstance_()

inParams.Properties_.Item("MACAddress") = macAddress
inParams.Properties_.Item("NetbiosName") = netBiosName
inParams.Properties_.Item("OverwriteExistingRecord") = False
inParams.Properties_.Item("SMBIOSGUID") = smBiosGuid

Pour faire la meme chose en PowerShell, regardons l’exemple du script généré par l’outil de MoW :

$InParams = $mc.psbase.GetMethodParameters(“ImportMachineEntry”)

$InParams.MACAddress = [string]
$InParams.NetbiosName = [string]
$InParams.OverwriteExistingRecord = [boolean]
$InParams.SMBIOSGUID = [string]

Comme vous pouvez le constater, le code est plutôt simple en PowerShell : ici le GetMethodParameters équivaut au inParameters.SpawnInstance_() du vbscript.

Détaillons un peu ce $InParams :
On voit effectivement nos 4 propriétés MacAddress, NetbiosName, OverwriteExistingRecord, SMBIOSGUID qui sont vides. Notez au passage que le type est bien exposé dans la colonne définition (OverwriteExistingRecord est de type System.Boolean, string pour les autres), et qu’on peut lire et écrire (get;set)

Bien, renseignons les 3 propriétés voulues (contrairement à ce qui est indiqué, la propriétéMSBIOSGUID n’est pas obligatoire pour ajouter une machine : c’est soit la MacAddress, soit le GUID… Seule l’experience permet de le savoir :) )


En affichant $InParams après avoir renseigné les propriétés, on voit bien que l’objet est chargé.

Reste à exécuter la méthode. L’exemple Vbscript donnait :

Set outParams = connection.ExecMethod("SMS_Site", "ImportMachineEntry", inParams)

En PowerShell, l’execution se gère comme suit (toujours en suivant simplement l’exemple généré par l’outil de MoW)

$mc.PSBase.InvokeMethod($Method, $inParams, $Null)

Voila notre machine importée dans SCCM, pour l’instant uniquement dans All Systems.
Image Hosted by ImageShack.us
Reste la troisième étape indiquée par le SDK : Ajouter cette machine à une autre collection.

Nous verrons cela dans la seconde partie de ce post.

Rejouissez-vous ! Vous savez à présent où trouver les différentes tâches liées à SCCM et les convertir en PowerShell.

lundi 17 mars 2008

SDK SCCM V4 disponible

la v4 (et première release hors Beta) du SDK de SCCM est dispo en téléchargement, juste sorti du four à cette adresse :

http://www.microsoft.com/downloads/details.aspx?FamilyId=064A995F-EF13-4200-81AD-E3AF6218EDCC&displaylang=en

j'upload prochainement avec la sortie du webcast de notre session techdays (normalement fin de semaine ou semaine prochaine) des exemples pour créer des cmdlets pour SCCM basés sur ce SDK.

à dans quelques jours !

lundi 4 février 2008

Techdays 2008

Nous serons présents aux Techdays 2008, avec à la clé une présentation sur PowerShell V1/V2 avec System Center et Windows Server 2008.

Au programme :
  • Interface de gestion déléguée pour SCCM
  • Gestion de projet pour SCVMM
  • Génération de rapports Word de statistiques Exchange 2007
  • Gestion asynchrone et remote de PowerShell 2.0

Et pleins d'autres petites astuces en tout genre :)

http://galilee.microsoft.fr/TechDays2008/Session.aspx?CellID=44c2cfea-881f-4f83-bfc9-254bd2b0dfd3

Je posterai ici des exemples tirés de cette présentation. Nous serons aussi présent sur le stand NEos-SDI dans le village infrastructure pour répondre à toute vos questions.