lundi 14 février 2011

Execution de PowerShell 2.0 dans un site web ASP.NET

Dans ce nouvel article, nous allons voir comment utiliser PowerShell 2.0 dans un site web ASP.NET

L'exemple est volontairement le plus basique possible, nous l'étendrons dans les prochains articles.

Cet exemple utilise PowerShell 2.0 et IIS 7.0, mais devrait fonctionner avec IIS 6.0. Vous pouvez utiliser une version express de Visual Studio.

C'est parti!

Configuration du projet

Ouvrez Visual Studio, choisir Fichier > nouveau projet

tuto1_thumb1

Choisir projet web, Application ASP.NET. Choisir un framework cible, 2.0 jusqu'à 4.0 (cet exemple s'appuie sur .NET 4.0 mais fonctionne avec les autres versions du framework)

tuto2_thumb3

Une fois le projet créé, ajouter la réference à la librairie PowerShell appelée "System.Management.Automation". Faire un clic droit sur References et choisir "Ajouter une référence..."

tuto3_thumb2

Choisir "Parcourir...":

C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0

ou

C:\Programmes\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0

Pour les systèmes x86

tuto4_thumb2

Nous pouvons maintenant construire l'IHM

Création de l'IHM

Notre IHM va être super basique: une textbox pour fournir le code PowerShell, un bouton exécuter, une textbox pour le résultat :

tuto5

Voici le code ASP.NET pour la page Default.aspx

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PowerShellCall._Default" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title></title>
   8: </head>
   9: <body>
  10:  
  11:     <form id="form1" runat="server">
  12:     <center>
  13:         <div>
  14:         <table>
  15:             <tr><td><h1>PowerShell Test</h1></td></tr>
  16:             <tr><td><h3>PowerShell Code</h3></td></tr>
  17:  
  18:             <tr><td>
  19:                 <asp:TextBox ID="PowerShellCodeBox" runat="server" TextMode="MultiLine" Width=700 Height=100></asp:TextBox>
  20:             </td></tr>
  21:  
  22:             <tr><td>
  23:                 <asp:Button ID="ExecuteCode" runat="server" Text="Execute" Width=200 onclick="ExecuteCode_Click" 
  24:                      />
  25:             </td></tr>
  26:  
  27:             <tr><td><h3>Result</h3></td></tr>
  28:         
  29:             <tr><td>
  30:                 <asp:TextBox ID="ResultBox" TextMode="MultiLine" Width=700 Height=200 runat="server"></asp:TextBox>
  31:             </td></tr>
  32:         </table>
  33:         </div>
  34:     </center>
  35:     </form>
  36:  
  37: </body>
  38: </html>

Objectif : quand l'utilisateur clique sur "Execute", nous voulons lancer le code PowerShell de la textbox du haut et afficher le résultat dans la textbox du bas.

Voyons de plus près le code C# derrière Default.aspx

Appel de PowerShell 2.0 dans le code behind

Comme vous pouvez le voir dans la page aspx, nous avons un évènement "onclick" sur le bouton. Cette méthode fait appel à la méthode "ExecuteCode_Click" présente dans le fichier .cs

Voici le code de cette méthode :

   1: protected void ExecuteCode_Click(object sender, EventArgs e)
   2:         {
   3:             // Clean the Result TextBox
   4:             ResultBox.Text = string.Empty;
   5:  
   6:             // Initialize PowerShell engine
   7:             var shell = PowerShell.Create();
   8:  
   9:             // Add the script to the PowerShell object
  10:             shell.Commands.AddScript(PowerShellCodeBox.Text);
  11:             
  12:             // Execute the script
  13:             var results = shell.Invoke();
  14:  
  15:             // display results, with BaseObject converted to string
  16:             // Note : use |out-string for console-like output
  17:             if (results.Count > 0)
  18:             {
  19:                 // We use a string builder ton create our result text
  20:                 var builder = new StringBuilder();
  21:                 
  22:                 foreach (var psObject in results)
  23:                 {
  24:                     // Convert the Base Object to a string and append it to the string builder.
  25:                     // Add \r\n for line breaks
  26:                     builder.Append(psObject.BaseObject.ToString() + "\r\n");
  27:                 }
  28:                 
  29:                 // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
  30:                 ResultBox.Text = Server.HtmlEncode(builder.ToString());
  31:             }
  32:  
  33:         }

L'exécution de code PowerShell est très simple en C#, nous avons besoin uniquement des étapes suivantes :

1) Création de l'objet PowerShell

Cette objet est l'objet de base pour PowerShell en C#, il permet entre autre d'exécuter des commandes, instancier les runspaces, récupérer les résultats, les erreurs, etc...

2) Création d'un runspace

Ici nous créons un runspace pour exécuter le code PowerShell. Il y a différent moyen de configurer un runspace en C#, mais nous resterons sur la méthode la plus simple pour cet article.

3) Ouverture du runspace.

L'ouverture du runspace est obligatoire pour pouvoir y injecter notre code

4) Add the script

Ici, nous ajoutons notre script dans notre runspace.

5) Execute script

Enfin, nous appelons la méthode Invoke() qui exécute nos commandes dans un pipeline. Cette méthode retourne un collection de PSObject (objet de base retournée par PowerShell)

6) Affichage du résultat

Ensuite, nous parcourons la collection retournée par notre Runspace pour afficher le résultat. Notez que nous appelons la propriété "BaseObject" pour chaque PSObject, cette propriété contient l'objet d'origine avant sa décoration en PSObject par PowerShell.

tuto5

Et voilà ! nous avons créer notre projet, nous allons maintenant pouvoir afficher le résultat d'un script dans notre textbox.

Il nous reste à présent à publier ce site web, et voir comment spécifier un compte spécifique pour l'exécution.

Publier le site web

Maintenant que notre exemple fonctionne, nous allons publier le site web sur IIS et spécifier l'identité du compte de service.

Allez dans "Génerer > Publier...

tuto6

Choisir une destination (Inetpub/wwwroot est le repertoire par défaut pour la publication IIS, mais vous pouvez publier votre site dans n'importe quel repertoire du moment que les droits appropriés sont configurés sur le dossier)

tuto7

Après cela, ouvrir la console de gestion IIS, faire un clic droit sur le site web par défault et selectionner "Ajouter une application"

Note : vous pouvez aussi créer un nouveau site web sous IIS, ou remplacer le site web par défaut pour créer le votre. Créer une application vous permet d'accéder à celle-ci par son nom comme suit: http://localhost/MyApplication

tuto8

Donner un nom a l'application et cliquer sur OK

tuto9

Maintenant que l'application est prête, nous pouvons choisir une identité spécifique pour l'exécution de nos commandes. Il y a de nombreuses façon de configurer une identité d'exécution pour un site web, nous couvrirons ici les plus basiques.

Authentification anonyme

Cette méthode est la plus simple. Nous allons choisir l'authentification anonyme (l'utilisateur ne sera pas identifié) et spécifier un compte de service pour l'exécution du site web. C'est facile, mais gare :

Dans ce contexte, n'importe qui peut accéder au site web et exécuter les actions avec l'identité du compte de service fourni ! Il y a toujours possibilité de filtrer l'accès par les droits au niveau fichiers (restreindre l'accès au repertoire), mais ceci n'est pas la méthode la plus sûre, vous êtes prévenus :)

Sélectionner l'application, faire un clic droit sur "Authentification"

tuto10

Faire un clic droit sur "Authentifcation anonyme" et choisir "Activer", puis Edition

tuto11

Choisir "Utilisateur spécifique" et cliquer sur "Choisir..."tuto12

Remplir le formulaire avec les informations du compte et cliquer sur OK

tuto13

Voilà : votre site va s'exécuter avec l'identité de ce compte de service.

Utiliser un Pool d'application

Dans des scenarii plus évolués, vous pouvez désactiver l'authentification anonyme et continuer à utiliser un compte de service pour votre site. Pour cela, il faut définir l'identité au niveau du pool d'application.

Les pools d'application peuvent être vu comme un contexte d'exécution pour vos sites webs (pour faire simple). Nous n'irons pas dans le détail ici, mais l'idée est de permettre de définir un accès en authentification windows ou formulaire, puis de faire appel à l'identité du pool d'application pour l'exécution des actions dans votre code.

Nous allons créer un pool d'application dédié pour notre projet de test.

Premèrement, faire un double clic sur "Pools d'application" dans la console IIS et choisir "Ajouter un pool d'application"

tuto30

Nommer le pool, choisir le framework approprié et cliquer sur "OK"

tuto31

Selectionner ensuite le pool d'application, et cliquer sur "Paramètres avancés" dans le menu à droite.

tuto32

Choisir Identité et cliquer sur le bouton "..."

tuto21

Choisir "Compte spécifique et cliquer sur "Définir..."
tuto22

Remplir le formulaire et cliquer sur OK

tuto23

A présent, cliquer sur le site web et cliquer sur "Paramètre de base":

tuto33

Cliquer sur "Sélectionner" et choisir Pool d'application

tuto34

Si tout va bien, vous devriez pouvoir afficher l'idendité de votre compte de service avec le code PowerShell suivant :

tuto25

Les sources sont disponibles ici :



Dans le prochain article, nous verrons comment authentifier les utilisateurs et utiliser les données d'un formulaire ASP.NET pour exécuter un script externe.

mardi 1 février 2011