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 !

4 commentaires:

Arnaud Petitjean a dit…

Bonjour Antoine,
Super tuto ! Je me posais justement la question de savoir comment faire. Maintenant je sais... ;-)

Longue vie à ton Blog.

Antoine Habert a dit…

Hello Arnaud,

Content que ça te soit utile, au plaisir !

Anonyme a dit…

Bonjour,

C'est exactement ce que je cherchais bravo pour le tuto Mais il y a un hic : la source est un projet empty...

Sébastien a dit…

Bonjour,
le fichier n'est plus disponible.
Pourriez-vous l'uploader à nouveau ?.
Merci