| Jacques's profilejanelPhotosBlogLists | Help |
|
July 30 Bienvenue à mes lecteurs du monde entier!Il y a environ deux mois j’ai installé une carte ClustrMaps sur la page d’accueil de mon blog.
Cette carte permet de voir en un clin d’œil de quel pays viennent mes visiteurs, voire de quelle partie d’un pays si sa taille permet une telle distinction. Evidemment, ce blog étant en français, la majorité des visites viennent de France, mais dès le début j’ai pu constater quelques visites d’autres pays européens, d’Amérique du Nord (Etats-Unis et Canada) et même d’Australie.
Plus récemment j’ai vu apparaître des visiteurs d’Amérique Centrale (Nicaragua il me semble) et des Maldives.
Et aujourd’hui je vois apparaître deux visiteurs venant de continents qui ne s’étaient pas encore manifestés sur ma carte : l’un vient d’Afrique (à priori du Sénégal si j’en crois la position du point rouge) et l’autre vient de Corée du Sud – certes, les Maldives sont également en Asie, mais la Corée du Sud représente une autre partie de l’Asie qu’on appelle l’Extrême-Orient, et j’ai tendance à considérer l’Extrême-Orient comme un continent à part entière !
Il ne me reste plus qu’à avoir un ou deux visiteurs d’Amérique du Sud et je pourrai affirmer que mon blog est lu sur tous les continents ! J Satisfaction très futile, j’en conviens. Mais alors que la mondialisation bat son plein et que dans mon propre travail je suis fréquemment en contact avec des chinois, des japonais, des américains, des irlandais ou des argentins, j’arrive encore à ressentir une petite émotion à l’idée que des hommes et des femmes à l’autre bout du monde tombent sur ce site et passent quelques minutes à le parcourir, voire le lisent assidument.
Certes, j’ai conscience qu’un certain nombre de mes lecteurs ne lisent pas ou mal le français et qu’ils se contentent de glaner quelques exemples de scripts en PowerShell – et c’est parfait ainsi – mais tout de même, à vous qui comprenez le français et aux autres qui ne liront pas ce billet exempt de toute ligne de code : bienvenue !
Janel July 27 Une introduction sur PowerShell en françaisLe contenu disponible en français sur PowerShell continue de s’étoffer. Au hasard de mes recherches je viens de trouver ce document Word qui constitue une bonne introduction à Windows PowerShell :
Si vous êtes un utilisateur assidu, vous n’apprendrez peut-être pas grand-chose à la lecture de ce document. Encore que, certains exemples vous ouvriront peut-être des horizons. Mais surtout, si vous souhaitez sensibiliser vos collègues et/ou amis, ce document pourra se révéler une source intéressante d’arguments et d’exemples concrets.
Principal défaut de ce document : la section Références (en fin de document) ne mentionne pas ce blog… Quelle lacune ! J
Bonne lecture,
Janel Un coup de fouet au (re-)démarrage de PowerShellSi les quelques secondes que met une session PowerShell pour démarrer vous exaspèrent, ou encore si vous tapez du pied en attendant qu’une session PowerShell en cours se réveille lorsque vous y revenez après un certain temps d’inactivité, vous trouverez sans doute beaucoup de plaisir et un confort accru après l’exécution de cette série de commandes :
set-alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
sort -descending LastWriteTime
)[0].FullName
[AppDomain]::CurrentDomain.GetAssemblies() | %{ngen $_.Location}
Il suffit de faire cela une fois pour toutes sur votre installation de PowerShell.
Si vous utilisez Windows Vista, ouvrez une session PowerShell avec élévation de privilèges pour pouvoir exécuter ces commandes correctement.
La commande ngen.exe génère une « image native » d’un assembly et des fichiers dont il dépend. Pour plus d’infos sur cette commande fournie avec le .NET Framework :
Bon vent,
Janel
July 21 Importer un fichier INI dans un tableau sous PowerShellS’il vous arrive encore de manipuler des fichiers INI, vous vous êtes peut-être déjà demandé comment récupérer leur contenu dans un script PowerShell. Il existe peut-être des API du Framework réutilisables avec PowerShell, mais je n’ai pas eu le courage de faire une recherche sur le sujet.
Pour l’heure, voici un petit script, très imparfait mais qui devrait marcher dans la plupart des cas. Ce script ajoute les couples « nom=valeur » dans un tableau de hachage, avec en prime un premier niveau de hachage correspondant à la section, ce qui permet de différencier les valeurs portant un même nom dans des sections différentes :
--- import-ini.ps1 ---
param ($file)
$ini = @{} switch -regex -file $file { "^\[(.+)\]$" { $section = $matches[1] $ini[$section] = @{} } "(.+)=(.*)" { $name, $value = $matches[1..2] $ini[$section][$name] = $value } } $ini (édité le 22 juillet pour modifier la 2e expression régulière suite à une suggestion de Kiron - la modification permet de prendre en compte des éventuelles valeurs vides)
Prenons comme exemple le fichier INI fictif suivant :
--- servers.ini ---
[ExchangeServer]
server1=srv-msg-01 server2=srv-msg-02 server3=srv-msg-03 [DomainController]
server1=srv-dc-01 server2=srv-dc-02 server3=srv-dc-03 On pourra utiliser le script ainsi :
PS> $servers = import-ini servers.ini
PS> $servers.Exchangeserver.Server1 srv-msg-01 PS> $servers["DomainController"]["Server1"] srv-dc-01 A noter, on peut utiliser indifféremment les deux syntaxes ci-dessus pour accéder aux sous-niveaux d’un tableau de hachage. A vous de voir celle qui vous convient le mieux. Personnellement, la première a ma préférence. Dans tous les cas, on pourra utiliser une variable en remplacement du nom de clé :
PS> $role = "ExchangeServer"
PS> $servers.$role
Name Value
---- -----
server2 srv-msg-02
server1 srv-msg-01
server3 srv-msg-03
Faites-en bon usage!
Janel July 18 Obtenir l'espace disque disponible sur une ou plusieurs machines avec PowerShellJe commencerai par rappeler l’existence de l’excellent site http://www.powershell-scripting.com. Ce site est le premier site francophone entièrement dédié à Windows PowerShell (en dehors de ce blog qui est quasi-exclusivement consacré à PowerShell depuis un peu plus d’un an). Arnaud et Robin, les deux administrateurs de PowerShell-Scripting, fournissent un travail remarquable notamment en animant un forum très vivant, en regroupant les scripts les plus utiles et en documentant des tutoriaux très complets.
C’est sur PowerShell-Scripting que j’ai posté il y a quelques jours un script visant à obtenir l’espace disponible sur tous les disques d’une machine locale ou distante. J’ai écrit ce script en réponse à un script déjà posté par Arnaud et à la fonctionnalité très proche. Le problème avec le script d’Arnaud, c’est qu’il ne jouait pas complètement le jeu de PowerShell. Alors qu’il récupérait bien les informations sur les disques sous la forme d’objets, il affichait les résultats sous la forme d’une chaîne de texte visant à assurer une lecture claire en mode interactif, mais interdisant (ou rendant inutilement compliquée) toute réutilisation de ces résultats.
Or, PowerShell offre la possibilité d’avoir une approche objet d’un bout à l’autre de la chaîne d’administration (si tant est que cette expression ait un sens ?...). Si nos scripts peuvent récupérer et manipuler des objets, pourquoi ne génèreraient-ils pas des objets eux aussi, de manière à pouvoir être une source pour d’autres scripts ?
Et si le problème que l’on veut régler est celui de l’affichage clair d’un résultat, pourquoi ne pas exploiter les commandelettes standard dédiées à la mise en forme des informations (format-*) ? Si l’affichage souhaité est trop complexe pour être simplement délégué à une commande externe, n’est-il pas possible de fournir par défaut un objet « brut » et en option un affichage plus sophistiqué pour une lecture immédiate ?
Mon script est une première et très basique illustration de ces propos. Je vous livre ici le texte complet de ma contribution au forum.
--- www.PowerShell-Scripting.com / Forum Contributions à la Communauté ---
Alors... Ce script est inspiré de celui qu'Arnaud avait posté dans la bibliothèque de scripts.
Principales différences avec l'original: * Je prends un nom d'ordinateur en paramètre, ce qui permet d'interroger cet ordinateur. On peut donc concevoir que ce script peut être utilisé tel quel pour parcourir tout un parc d'ordinateurs et retourner la place libre sur l'ensemble des ordinateurs. * Je retourne avec chaque objet le nom de l'ordinateur, le nom du disque et sa taille disponible, de manière à pouvoir traiter l'information en cas de requête sur plusieurs ordinateurs. * La sortie est faite sous la forme d'objets normalisés (un sous-ensemble avec select-object de ce que retourne WMI pour Win32_LogicalDisk) dont on peut traiter les résultats à volonté en-dehors du script. Voir les usages fournis à titre d'exemple après le code lui-même...
# get-freespace.ps1
param ($computer = ".", [switch]$total)
# récupérer tous les disques logiques de l'ordinateur:
get-wmiobject -computer $computer win32_logicaldisk |
tee-object -variable disques |
select-object @{e={$_.systemname};n="Système"},
@{e={$_.name};n="Disque"},
@{e={[math]::round($_.freespace/1GB,1)};n="Disponible (Go)"}
# afficher l'espace disponible total si demandé:
if ($total) {
"`nEspace Disponible Total sur $($disques[0].systemname): $([math]::round(($disques|measure-object freespace -sum).sum/1GB,1)) Go"
}
# Commençons par la machine locale:
PS> get-freespace
Système Disque Disponible (Go)
------- ------ ---------------
JANEL01 C: 2,1
JANEL01 D: 0
# Continuons avec une machine distante:
PS> get-freespace mce01 -total
Système Disque Disponible (Go)
------- ------ ---------------
MCE01 C: 1,8
MCE01 D: 0,6
etc.
Espace Disponible Total sur MCE01: 15,1 Go
# Terminons avec un changement de format:
PS> get-freespace mce01 | format-list
Système : MCE01
Disque : C:
Disponible (Go) : 1,8
Système : MCE01
Disque : D:
Disponible (Go) : 0,6
etc.
# récupération et affichage des espaces libres pour chaque ordinateur listé dans parc.txt:
PS> get-content parc.txt | foreach {get-freespace $_}
Système Disque Disponible (Go)
------- ------ ---------------
JANEL01 C: 2,1
JANEL01 D: 0
MCE01 C: 1,8
MCE01 D: 0,6
MCE01 E: 7,3
etc.
# Afficher quelques statistiques sur ce parc...
PS> $parc = get-content parc.txt | foreach {get-freespace $_}
# Commençons par le nombre de disques logiques par ordinateur:
PS> $parc | group système -noelement
Count Name
----- ----
2 JANEL01
9 MCE01
4 MCE02
# Continuons avec la taille libre totale (en Go) pour l'ensemble du parc:
PS> ($parc | measure-object dispo* -sum).sum
38
J'ai toujours en chantier un billet sur ce sujet pour mon blog, où je décrirai ce que j'estime être les bonnes pratiques pour une bonne citoyenneté des scripts et fonctions que l'on écrit sous PowerShell. Si je trouve le temps de le faire, je tiendrai ce forum informé. En espérant que tout cela vous sera utile, Janel --- fin de contribution --- Janel July 17 Associer les fichiers ps1 à PowerShellVous l’aurez noté, Windows PowerShell s’installe avec par défaut un certain nombre de garde-fous inhabituels et énervants pour l’utilisateur avancé et prudent que nous sommes tous. Parmi ces garde-fous, citons :
Le premier garde-fou est très facilement modifiable (d’ailleurs, PowerShell vous indique dès son premier démarrage comment modifier ce comportement avec la commande set-executionpolicy). Le second l’est également, mais n’ayant pas trouvé un intérêt vital à modifier ce comportement je me garderai bien de le faire.
Le troisième garde-fou est un peu plus compliqué à modifier. Si vous vous contentez d’utiliser l’Explorateur pour modifier l’application à utiliser pour ouvrir les fichiers de type .ps1, vous risquez fort d’être déçus. En effet, l’Explorateur indiquera à Windows de lancer PowerShell avec le nom du script en argument, mais les choses sont un peu plus compliquées. PowerShell demande que vous lui passiez une commande à exécuter sous ce format :
powershell.exe -command "& {commande}"
Si la commande est un script, à la place des accolades on mettra le chemin d’accès complet du script. Quand on ouvre un fichier à partir de l'Explorateur, ce chemin d’accès est fourni par l’Explorateur sous la forme de la variable %1.
Il ne reste plus qu’à indiquer à l’Explorateur qu’il lui faut utiliser %1 en argument du paramètre -command. Ca se fait dans la base de registre, et pourquoi pas utiliser PowerShell pour cela ?
new-item Registry::hkey_classes_root\microsoft.powershellscript.1\shell
new-item Registry::hkey_classes_root\microsoft.powershellscript.1\shell\open
new-item Registry::hkey_classes_root\microsoft.powershellscript.1\shell\open\command -value ('"' + $PSHOME + '\powershell.exe" -command "& ''%1''"')
Si vous utilisez Windows Vista, assurez-vous d’exécuter ces lignes dans une session élevée (non, ne me dîtes pas que vous avez désactivé l’UAC…).
La prise en compte de la modification est immédiate. Retournez dans l’Explorateur et double-cliquez sur un script, il devrait maintenant s’exécuter au lieu de s’ouvrir dans le Bloc-notes. S’il ne passe rien ou si vous apercevez un message d’erreur fugace, vérifiez que vous avez bien autorisé l’exécution de scripts (voir le premier garde-fou ci-dessus).
Avec tout ça, il ne me reste plus qu’à vous souhaiter bon vent !
Janel
July 06 Que ferez-vous ce 7 juillet 2007?La date est symbolique : 07/07/07. Evidemment, il y a déjà eu le 1er janvier 2001, et le 2 février 2002, etc. et il y aura un 8 août 2008 et ainsi de suite jusqu’au 12 décembre 2012 qui fermera la série pour ce siècle.
Alors, qu’a cette date d’un peu plus spécial que les autres ? Simplement qu’elle a été choisie pour célébrer l’urgence d’une prise de conscience mondiale sur la crise environnementale que connaît notre planète. Ce samedi 7 juillet 2007, de nombreux artistes (nettement plus que 7) se produiront sur les 7 continents : des concerts se relaieront en commençant à Sydney puis Shanghai, Tokyo, Kyoto, Johannesburg, Hambourg, Londres, New York et pour finir à Rio de Janeiro. L’évènement s’appelle Live Earth.
Vous pourrez peut-être regarder une partie de ces concerts à la télé, ou en écouter certains à la radio. Si vous voulez voir l’intégralité de ces concerts, soit en direct soit ultérieurement, un seul lien :
Rendez-vous le 7 juillet 2107 pour faire le bilan !
Janel
July 05 Exemple d'appel à un Service Web avec la commandelette invoke-webserviceNon, ne vous précipitez pas sur votre téléphone pour hurler dans les oreilles du support de Microsoft que votre installation de PowerShell n’a pas la commandelette invoke-webservice. Celle-ci est fournie avec PowerGadgets, une suite d’outils formidable pour l’affichage de données à partir de PowerShell. Si vous n’avez pas de licence PowerGadgets, j’ai entendu dire qu’il y avait des offres spéciales pour les MVP et autres populations d’ « influenceurs ». A vous de voir si vous rentrez dans cette définition !
Quoi qu’il en soit, voici un usage possible de cette commandelette, qui repose sur le service Web TemperatureConversions pour convertir une température Celsius en Fahrenheit et inversement:
# convert-temperature.ps1
#
# Converts a given temperature to either Celsius or Fahrenheit.
#
# Usage: convert-temperature [-temperature] <int32> [-ToCelsius | -ToFahrenheit]
#
param (
[int32]$temperature = $(throw "Temperature must be specified!"),
[switch]$ToCelsius,
[switch]$ToFahrenheit
)
$method = ""
($ToCelsius) -and ($method = "FahrenheitToCelcius") > $null
($ToFahrenheit) -and ($method = "CelciusToFahrenheit") > $null
if ($method -eq "")
{
throw "Either -ToCelsius or -ToFahrenheit must be specified!"
exit
}
$wsdl = "http://webservices.daelab.net/temperatureconversions/TemperatureConversions.wso?WSDL"
invoke-webservice -wsdl $wsdl -method $method $temperature
Pour votre culture, j’ai déniché ce service Web sur l’annuaire non exhaustif http://www.xmethods.net/. Vous noterez au passage que leurs méthodes orthographient Celcius au lieu de Celsius. Il me semble qu’il s’agit d’une faute d’orthographe (même en anglais), mais maintenant que le service est en production il me paraît improbable qu’ils corrigent cette faute.
Et… oui, si vous me le demandez, il est tout à fait possible de faire la même chose sans avoir besoin d’un service Web. La conversion d’une échelle à l’autre est une opération très simple qu’on pourrait par exemple écrire ainsi (en reprenant le même canevas que la version ci-dessus):
# convert-temperature.ps1
#
# Converts a given temperature to either Celsius or Fahrenheit.
#
# Usage: convert-temperature [-temperature] <int32> [-ToCelsius | -ToFahrenheit]
#
param (
[int32]$temperature = $(throw "Temperature must be specified!"),
[switch]$ToCelsius,
[switch]$ToFahrenheit
)
$method = ""
($ToCelsius) -and ($method = "(5/9)*($temperature-32)") > $null
($ToFahrenheit) -and ($method = "((9/5)*$temperature)+32") > $null
if ($method -eq "")
{
throw "Either -ToCelsius or -ToFahrenheit must be specified!"
exit
}
Invoke-expression $method
Bon, enfin, avec tout ça il fait toujours froid pour un 5 juillet… En tout cas par chez moi !
Janel |
|
|