powershell.png
Petit sondage :
Qui travaille sous Microsoft Windows ?
- tout le monde ?
Qui a besoin de cmd.exe ?
- tout le monde (maven, scripting, etc.) ?
Qui trouve l'invite de commande facile à utiliser ?
- personne ?
C'est par ce rapide sondage qu'a commencé la démonstration de Cédric Rup sur la nouvelle console de Microsoft : le PowerShell.

En effet, en novembre 2006, Microsoft réagit en sortant la première version de sa nouvelle interface d'administration ultime. Il ne s'agit pas d'une interface graphique très recherchée, mais bien d'un nouvel interpréteur de commandes.

Pour télécharger la dernière version, vous devez posséder le framework .NET installé sur votre machine, et télécharger l'installation du PowerShell. Juste après cette installation, vous pourrez tester l'exécution de ces commandes bien connues :
dir
cd
ls
Surprise, les alias des commandes unix fonctionnent !
Pour avoir de l'aide en ligne sur la commande dir par exemple :
dir -?
Avec PowerShell, une commande s'appelle une commandlet. C'est l'unité de base du scripting. Il y en a 129 de base. La syntaxe est une convention : VERBE-NOM -argument param. Par exemple, la commande dir est un alias de : Get-ChildItem -Path ..

Fonctionnalités

  • Complétion sur les arguments (tab)
  • Trouver les alias d'une commande. Ex. : Get-Alias dir
  • Gestion des variables.
    Ex. :
    $dir = Get-Children
    $dir // évalue la variable
    
  • Tout est objet (là où tout est chaîne de caractère en shell unix.
    Ex. :
    $dir.* // <- utiliser la complétion pour lister les
              variables d'instance de l'objet (ses pro-
              priétés)
    $dir.getType() // on a bien affaire à un objet .NET
                      !!! avec l'accès a ses méthodes
  • Le pipe est un flux d'objets.
    Ex. :
    $dir | Get-Member // permet de lister les variables
                         d'instance de l'objet en les
                         faisant passer à travers le
                         pipe.
    // démarrer plusieurs instances de notepad
    Get-Process -Name no*
    (Get-Process -Name no*).Kill() // termine les pro-
                                      cessus notepad par
                                      appel de la mé-
                                      thode kill.
    Get-Process no* | Stop-Process // termine tous les
                                      processus notepad
                                      en passant par le
                                      pipe.
    
    Avantage : Le pipe crée un flux d'objets et n'attend pas que la liste soit totalement instanciée. Alors que l'instanciation d'une variable stocke l'objet en mémoire.
    On peut passer du code dans un pipe (inspiration perl) : c'est une méthode anonyme. Ex. :
    Get-ChildItem | Where-Object { $_.Length -gt 1Mb }
    // La variable $_ est l'object considéré lors de
       l'itération sur les résultats.
    
    On peut trier avec Sort-Object
    On peut grouper sur une propriété avec Group-Object Par exemple pour afficher les fichiers groupés par extension.
  • Il y a un certain nombre d'arguments en commun sur les objets .NET donc auquels on a naturellement accès par Power Shell:
    verbose, debug, ErrorAction (que faire en cas d'échec, voir la variable $ErrorActionPreference), ErrorVariable, WhatIf (simulation de l'éxécution, très utile), ? (aide), etc.
  • En regardant de plus près les possiblités des arguments de commande, on observe :
    • Une notion de position d'argument par défaut (si l'argument n'est pas spécifié, on présume que l'argument est daonné dans cette position dans la liste d'args)
    • Une notion d'acceptation d'argument paar le pipe...
    • Une notion de paramétrage de l'acceptaiton des wildcards.
  • La gestion des droits ext supportée par la commande : Get-Credentials. Elle permet d'acquérir une identité et de s'en servir pour l'éxécution sous une autre identité que celle du lanceur de la commande.
Pour toujours s'y retrouver, n'hésitez pas à utiliser ces commandlet "point d'entrée" : Get-Command, Get-Help, Get-Member. On peut aller plus loin en filtrant les résultats : Get-Command -Noun Item (cherche les commandes qui contiennent Item)

La puissance du Shell

On a accès à TOUT .NET. Notamment les classes du framework :
[TYPE] <- accès au type .NET
On peut donc accéder aux méthodes statiques d'une classe. Ex. :
[System.DateTime]::Now // La date actuelle.
Mais on peut aussi instancier un objet .NET. Ex:
$webclient = New-Object System.Net.Webclient // un client web !
$string = $webclient.DownloadString("http://eric.lemerdy.free.fr/dotclear/index.php?feed/atom") // on télécharge un flux rss...
$string.ToString() // ...qu'on peut afficher à l'écran !
Les variables non typées par défaut, on peut stocker un entier puis une chaîne par exemple :
$a = 12
$a.GetType()
$a = 'Eric'
$a.GetType()
Par contre, on peut forcer le typage d'une variable
[Int32]$x = 12
$x = 'YES' // Error
$x = 12 // ok
On peut donc "caster" notre chaîne xml :
[XML]$xml = $string
$xml.rss.channel.item | Select-Object title
Et accéder directement au contenu du XML !!! Ici, rss, channel et item sont des éléments (au sens XML) du contenu XML.

Extension du shell

On peut charger ses propres classes en constituant une assembly. C'est l'unité packagée de code éxécutable, l'équivalent d'un jar en java. Ex. :
[Reflexion.assembly]::loadFile(myfile)
Cette extensibilité permet de créer des API pour vos applications .NET et d'y accéder par PowerShell.
Pour ajouter des commandlet, on va constituer un snappin. C'est simplement une assembly qui contient des commandlets.
Pour l'installer : InstallUtil.exe. C'est un utilitaire également utilisé pour déclarer un service Windows.
Get-PSSnapin -Registered // les snapins installés
                   mais pas enregistrés
Add-PSSnapin  // enregistrer les snapins
On bénéficie donc des même services qu'une commandlet du package de base, comme la complétion sur les commandes par exemple.

Une uniformité fournie grâce aux providers et aux drives

Un provider est le moyen uniforme de parcourir des objets organisés hiérarchiquement. Depuis le début de l'article, on on travaille avec le provider du filesystem.
Pour connaître les providers disponibles :
Get-PSProvider // Variables d'environnement, filesystem, registre Windows, etc.
Alors que les drives sont les éléments parcourables par leur provider.
Pour connaître les drives disponibles :
Get-PSDrive // Env, C:, D:, HKLM (HKEY_LOCAL_MACHINE)
Chaque drive est donc associé à son provider. Il existe d'autre providers de la communauté : LDAP, S3 (amazon), etc.
Pour changer le drive courant :
Set-Location variable: // choisit le drive des variables
dir // liste les variables !

Instrumentation

L'instrumentation est fournie par WMI pour Windows Management Instrumentation. C'est l'équivalent de JMX sur la JVM. On peut tout savoir sur une machine : l'heure, les users loggés - en lecture/écriture ! On peut donc éditer un point de configuration du poste à partir de Powershell sans problème à condition d'avoir le niveau de droit suffisant.
Il est possible de lancer des service : Start-Service

Gestion des scripts

L'extension est : *.ps1.
Pour exécuter un script : Get-Cat | & .\out-grid.ps1
On peut appeler du Windows Forms dans powershell ce qui permet d'afficher un tableau d'objets dans une interface graphique en cinq lignes de code.
Bien-sûr, l'éxécution de scripts étant une fonctionalité convoitée par de nombreux virus, Microsoft était attendu sur l'aspect sécurité de la chose. Pour adresser ce besoin fort de sécurité, il existe la notion d' : Execution policy (politique d'éxécution).
Get-ExecutionPolicy
Set-ExecutionPolicy
Niveaux :
unrestricted : tous ok
all signed : tous signés
RemoteSigned : tous les scripts externes doivent être signés
Le niveau par défaut ne permet pas l'éxécution du tout !
Tout objet qui n'est pas "utilisé" (affectation dans une variable ou utilisé par une fonction) sort du script (console). Pour éviter ça, on redirige vers null : macommande >$null; Sinon, ça resort dans le pipe externe. Cela peut être un avantage car tout ce qui sort du pipe est traîté immédiatement par la commande suivante comme nous l'avons vu plus haut.

L'avenir

Microsoft semble prêt à ouvrir les API de ses logiciels serveurs à travers PowerShell (Exchange par exemple). Cela sera d'autant plus facilité si ces logiciels sont écris en .NET. En tant que développeurs d'applications .NET, il est aussi bénéficiable de profiter de cette ouverture qui peut faciliter la configuration et l'administration de son logiciel.
Le produit évolue. Les nouvelles fonctionnalités attendues sont : les aspects éxécution à distance, l'éxécution en parallèle, une nouvelle interface graphique, de nouveaux snappins.
Sous Linux, le projet Mono, le portage de .NET, permet à l'initiative "pwash" de ne pas repartir de zéro dans son intention de porter la ligne de commande sous Linux.
Au cours de cette petite démonstration des possibilités de la nouvelle console de Microsoft, nous avons tous été impressionés par l'expressivité de la platte-forme. Les concepts de pipe objet et d'accès à la platte-forme .NET sont des apports inconstestables à la productivité et l'efficacité du scripting.

Notons pour conclure que ce produit marque un tournant dans la démarche Microsoft qui constituait auparavant à tout doter en interfaces graphiques. Cédric nous a d'ailleurs révéllé que les développeurs de PowerShell n'avaient pas très bonne presse au sein des équipes Microsoft qui ne comprennaient pas alors le changement de stratégie de la société.
Ce changement permet à Microsoft d'élargir sa cible d'administrateurs Windows en adressant aussi les adeptes de la ligne de commande. C'est donc une attaque en règle des serveurs *nix en dotant son système d'exploitation d'une console plus puissante qu'un bash unix ?