jzu

Aller au contenu | Aller au menu | Aller à la recherche

JScript

Vous savez peut-être que Windows est un système d'exploitation assez répandu.

Et j'ai dû me poser récemment la question : comment écrire des scripts sous Windows ? Deux manières traditionnelles se complètent assez bien. Cmd d'une part, héritier direct de command.com, pour les tâches simples, voire simplistes vu sa grammaire et son vocabulaire terriblement limités ; et VBS, descendant de Visual Basic, pour accéder aux API Microsoft et véritablement programmer (mais sa syntaxe me fait vomir). On peut aussi citer la pléiade d'outils .Net ainsi que Power Shell mais ils ne sont installés que sur des versions récentes de Windows.

Il existe un autre langage de script pour Windows, JScript, dérivé de Javascript alias ECMAscript. Méconnu, peu documenté, déviant de la « norme » par de nombreux points, il s'agit pourtant d'un vrai langage, lisible, dont la microsoftisation permet d'exploiter les ressources du système sous toutes ses versions depuis XP. Il souffre de maux bizarres parfois, il faut se faire à ses spécificités, mais on arrive presque toujours à ses fins.

Par exemple, pour lire un fichier, il faut d'abord instancier un objet permettant de discuter avec le système de fichiers.

var fso = new ActiveXObject ("Scripting.FileSystemObject");

On peut ensuite ouvrir le fichier, y lire des lignes de texte et le fermer.

fi = fso.OpenTextFile (input, 1);
while (!fi.AtEndOfStream) {
  text = fi.ReadLine();
}
fi.close();

On ne peut exploiter que des données texte. Pas de binaire, ou alors par des biais horribles. Les explications d'Eric Lippert sur son blog MSDN sont tellement absurdes (cf. son deuxième commentaire) qu'on a peine à croire que des développeurs aussi capables puissent se fourvoyer à ce point. Voilà donc un des maux bizarres dont je parlais plus haut.

Consultez MSDN pour la liste des méthodes disponibles pour FileSystemObject, ainsi que pour les autres API. Parfois, les exemples ne sont fournis que pour VBScript, C++ et C#, JScript étant considéré comme un langage de deuxième ordre pour Microsoft. À l'utilisateur de chercher ces exemples sur Google.

Autre objet utile, WScript.Shell.

var shl = new ActiveXObject ("WScript.Shell");

shl.run ("msinfo32.exe /report msinfo.txt");
WScript.Echo ("%TEMP%=" + shl.ExpandEnvironmentStrings ("%TEMP%"));
WScript.Echo ("Desktop=" + shl.SpecialFolders ("Desktop"));

On peut même utiliser WMI (Windows Management Instrumentation) pour, entre autres, lire les Event Log de Windows.

var wmi = GetObject ("winmgmts:{impersonationLevel=impersonate,(Backup)}!\\\\.\\root\\CIMV2");

var evts = wmi.ExecQuery 
            ("select * from Win32_NTEventLogFile 
                      where LogFileName like 'App%' 
                         or LogFileName like 'Sys%'");
var evt = new Enumerator (evts);
for (evt.moveFirst(); !evt.atEnd(); evt.moveNext()) {
  var evtName = evt.item().LogFileName;
  var strBackupLog = evt.item().BackupEventLog (evtName+".evt")
}

Il n'y a pas de mécanisme à la #include. C'est historique : les fichiers Javascript sont généralement lus depuis une page HTML. Et puis VBS ne connaît pas non plus ce mécanisme, alors... alors on se débrouille avec eval().

eval ((new ActiveXObject 
  ("Scripting.FileSystemObject")).OpenTextFile ("lib.js",1).ReadAll ());

On peut même se payer le luxe d'une inclusion conditionnelle. Il suffit de définir un objet dans lib.js

var lib = new Object ();

et de faire précéder le eval() d'un test

if (typeof lib == "undefined")
eval ((new ActiveXObject 
  ("Scripting.FileSystemObject")).OpenTextFile ("lib.js",1).ReadAll ());

ce qui permet d'imbriquer les inclusions sans se poser de question.

Les méthodes et les attributs présents dans le fichier lib.js seront directement ajoutés au namespace courant, implicitement self, sauf si on précise un namespace différent, comme dans la déclaration

function lib.print (str) {

mais, là, on sort du domaine du scripting pour entrer dans celui de la programmation objet plus traditionnelle et JScript n'est peut-être plus le langage à employer.

On peut envoyer un mail :

var msg  = new ActiveXObject ("CDO.Message");   
var cfg  = new ActiveXObject ("CDO.Configuration");

msg.Subject = "Test";
msg.From = "me@example.com";
msg.To = "you@example.com";
msg.TextBody = "Hello world";

msg.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;   
msg.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.example.com");
msg.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25;
msg.Configuration.Fields.Update ();   

msg.Send();

Et lire ou écrire une clef de registre :

var shl = WScript.CreateObject ("WScript.Shell");

var bKey = shl.RegRead ("HKCU\\Software\\SimonTatham\\PuTTY\\Sessions\\wfl\\BellOverloadS");

Dernier luxe par rapport à VBS et son pathétique On Error, JScript peut gérer les erreurs par un mécanisme de try/catch :

try {
  fso.CopyFile (from, to);
  WScript.Echo ("Ok");
}
catch (e) {
  WScript.Echo ("KO - " + e);
}

Aha, j'oubliais, comment lance-t-on un programme ? La commande wscript, celle qui est lancée par défaut quand on invoque directement un programme en .js, affiche les WScript.Echo() dans des petis dialogues, alors que cscript lance le script en mode console, idéal pour logger efficacement ce qui se passe ou pour rediriger les sorties console vers NUL:.

Les moyens de debug sont extrêmement limités ; restent WScript.Echo() et, pour les problèmes vraiment incompréhensibles, les Sysinternals.

NB : Les exemples de code sont mal affichés mais un copier-coller restitue le formatage d'origine.

nxv - networked xv

Je suis un vieux con.

Un vieil Unixien (depuis System III en 1983) qui a du mal à perdre ses habitudes.

Un des programmes installés par les premières Slackware, vers 1994, s'appelait xv et permettait de visualiser des images, et d'effectuer des manipulations de base, le tout en quelques touches et quelques clics de souris. L'espace pris sur le "screen estate" restait minimal. Comparé à display, dont il est impossible de sortir par une action au clavier, à gqview et ses widgets inutiles, xv est un rêve d'ergonomie - l'ergonomie étant, pour un vieux con, idéalement définie par un programme comme vi : une action, une touche. :-)

Mais xv est vieux, lui aussi. Il ne gère pas les formats de fichiers modernes. Il se comporte bizarrement avec certains window managers (l'option -nolimits ne fonctionne pas sous Gnome, Sawfish refuse les actions previous-workspace et next-workspace vers un espace où une image est maximisée). Il n'est plus maintenu que par une petite communauté d'utilisateurs qui diffusent des patchs malheureusement incompatibles : je n'ai jamais réussi à accepter en même temps le PNG et les différents formats JPEG. Alors que display accepte les URL en argument, xv ne gère que les fichiers locaux.

C'est probablement la paresse de m'habituer à un autre visualisateur d'images qui m'a poussé à passer plusieurs heures sur un wrapper donnant à xv la fonctionnalité qui me manquait le plus : l'accès par le réseau. Le processus de téléchargement dans un fichier temporaire a donné aussi la possibilité de convertir les formats « difficiles » vers des formats connus de xv, de PNG vers GIF et de JPEG vers JPEG. Il y aurait sûrement plus propre et plus rapide que ma manière de faire mais, au moins, ça marche. Le script nxv attaché en pièce jointe est le résultat de mes élucubrations. S'il lui faut une licence, qu'elle soit BSD. Ou WTFPL.

Edit: Le système de pièces jointes de Dotclear est borké. Voici le lien direct : nxv