Visual Basic Script

Version de VBScript : à partir de la 5.6. Systèmes d'exploitation concernés : Windows XP, Windows 7 (pourquoi pas Vista)

 

accueil | console | VBScript | PowerShell | php | MySQL | documentation | formation  | trucs et astuces | exemples | glossaire

 

 

 

 

 

Généralités

La gestion d'erreurs dans l'environnement VBScript

Programmation de la gestion des erreurs dans un script VBScript

Error Handler en environnement VBScript

Journalisation des erreurs en environnement VBScript

 

 

I - GENERALITES

 

Visual Basic, Scripting Edition (en abrégé VBScript) est un moteur de scripts interprété qui permet une gestion puissante de Windows, beaucoup plus complète que ne le permettait (et le permet encore) la Console de lignes de commandes.

 

La syntaxe de VBScript est très semblable à Visual Basic, avec quelques limitations, dont notamment l'absence (à notre avis regrettable) de l'instruction GOTO et de la capacité de connaître le numéro d'une ligne en cours d'exécution (l'un étant probablement une conséquence de l'autre).

 

VBScript est puissant car il dispose d'un interface immédiat et relativement facile à programmer vers le Windows Management Instrumentation (WMI), infrastructure de gestion de Windows orientée objets, avec laquelle on peut pratiquement tout faire, en local ou sur une machine distante.

 

Remarque : Pour tout ce qui suit, une connaissance minimum de VBScript est supposée être acquise, notamment pour ce qui concerne la différence entre l'utilisation des moteurs wscript et cscript.

 

[début]


 

II - LA GESTION D'ERREURS DANS L'ENVIRONNEMENT VBScript

 

La gestion des erreurs avec VBScript est simplissime (d'où la création de ce site, doit-on le répéter).

 

Soit on n'en veut pas, on ne fait rien de spécial dans le script et celui-ci s'arrête dès la première erreur, soit on en veut et on utilise l'instruction :

 

On Error Resume Next

 

L'instruction On Error Resume Next crée de façon interne un objet Err dont l'une des propriétés, Err.Number, contiendra le numéro de l'erreur s'il en survient une, puis indique à l'interpréteur de scripts d'ignorer purement et simplement toute erreur rencontrée et de passer à la ligne suivante.

 

L'annulation de l'action de On Error Resume Next se fait par l'instruction :

 

On Error goto 0

 

Exemple :

 

oern.vbs

 

' démonstration de l'utilisation de On Error Resume Next (en abrégé OERN)

Option Explicit                       'toutes les variables doivent être définies

Wscript.Echo vbcrlf & "1. Activation de OERN"
On Error Resume next                  'les erreurs doivent être ignorées
Wscript.Echo "2. Production d'une erreur volontaire (variable myVar non définie)"
Wscript.Echo myVar                    'erreur car myVar n'est pas définie
Wscript.Echo "** Il y a eu une erreur mais c'est pas grave"

Wscript.Echo vbcrlf & "3. Désactivation de OERN"
On Error goto 0                       'annulation de l'action de OERN
Wscript.Echo "4. Production d'une erreur volontaire (variable myVar non définie)"
Wscript.Echo myVar                    'erreur car myVar n'est pas définie
Wscript.Echo "** Le script n'exécutera jamais cette ligne"

Wscript.Quit

 

Résultat :

 

C:\vbs>oern

1. Activation de OERN
2. Production d'une erreur volontaire (variable myVar non définie)
** Il y a eu une erreur mais c'est pas grave

3. Désactivation de OERN
4. Production d'une erreur volontaire (variable myVar non définie)
C:\vbs\oern.vbs(14, 1) Erreur d'exécution Microsoft VBScript: Variable non définie: 'myVar'

C:\vbs>

 

[début]


 

III - PROGRAMMATION DE LA GESTION DES ERREURS DANS UN SCRIPT VBScript

 

Les scripts VBScript (en abrégé VBS) exécutés depuis la console (par les programmes wscript.exe ou cscript.exe) doivent porter l'extension .vbs. Ils ne peuvent contenir que des instructions spécifiques au langage Visual Basic Script. Ce langage est interprété, ce qui signifie que d'éventuelles erreurs de syntaxe ou de programmation sont détectées au lancement du script juste avant son exécution.

 

 

a) Un script VBS retourne à la console la valeur param dans la variable ERRORLEVEL selon l'instruction finale suivante :

 

wscript.quit param

 

 

b) Un script VBS renvoie à la console dans la variable ERRORLEVEL la valeur 1 si une erreur de syntaxe se produit au moment de son interprétation

 

Exemple :

 

syntax_error.vbs

 

a = 0
if a = 0 wscript.quit   ' "Then" est manquant

 

Résultat :

 

C:\vbs>cscript /nologo syntax_error.vbs
C:\vbs\syntax_error.vbs(2, 10) Erreur de compilation Microsoft VBScript : 'Then' attendu
C:\vbs>echo %errorlevel%
1

 

Remarque 1 : Les erreurs de syntaxe ne sont pas gérables par la fonction on error resume next (ni par rien d'autre, soit dit en passant)

 

Remarque 2 : L'interpréteur indique entre parenthèses le numéro de la ligne et le quantième du premier caractère où a été détectée l'erreur. On utilisera avantageusement l'outil Line_Numbers.vbs pour numéroter les lignes d'un grand fichier source.

 

 

c) Un script VBS renvoie dans la variable système Err.Number un numéro VBS unique d'erreur au moment de son exécution si l'on a programmé la gestion des erreurs au moyen de l'instruction on error resume next, sinon le script s'arrête avec un code retour positionné à 1 (en savoir plus sur l'utilisation de l'instruction on error resume next ici.)

 

Exemple :

 

runtime_error.vbs

 

on error resume next
set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "%windir%\notepad " & toto.txt          'la commande attend une variable, pas un nom
wscript.echo "Erreur      : " & err.number
wscript.echo "Description : " & err.description
wscript.echo "Source      : " & err.source
wscript.quit

 

Résultat :

 

C:\vbs>cscript /nologo runtime_error.vbs
Erreur      : 424
Description : Objet requis
Source      : Erreur d'exécution Microsoft VBScript

 

 

d) Un script VBS renvoie des informations complémentaires sur une erreur si l'on a utilisé un appel au Windows Management Instrumentation (WMI) via la commande

 

Set WMI_Error = CreateObject("WbemScripting.SwbemLastError")

 

Exemple :

 

wmi_error_demo.vbs

 

set objWMIService = getObject("winmgmts:root\CIMV2")
on error resume next
set objShare = objWMIService.Get("Win32_Printer.DeviceID='TestPrinter'") ' n'existe pas
if err.number <> 0 then         ' (la syntaxe if err <> 0 est également valable)
   ern = err.number and &HFFFF& ' supprime les 4 premiers bits inutilisés (en savoir plus)
   wscript.echo "WSH Error      : " & ern             & vbcrlf & _
                "WSH Error (Hex): " & Hex(err.number) & vbcrlf & _
                "WSH Description: " & err.description & vbcrlf & _
                "WSH Source     : " & err.source
   set WMI_Error = CreateObject("WbemScripting.SwbemLastError")
   Wscript.Echo "WMI Operation  : " & WMI_Error.Operation     & vbcrlf & _
                "WMI Parameter  : " & WMI_Error.ParameterInfo & Vbcrlf & _
                "WMI Provider   : " & WMI_Error.ProviderName
end if
wscript.quit

 

Résultat :

 

C:\vbs>cscript /nologo wmi_error_demo.vbs

WSH Error      : 4098
WSH Error (Hex): 80041002
WSH Description: Non trouvé
WSH Source     : SWbemServicesEx
WMI Operation  : GetObject
WMI Parameter  : Win32_Printer.DeviceID="TestPrinter"
WMI Provider   : CIMWin32

 

 

e) L'instruction on error resume next placée en début de script couvre intégralement celui-ci sauf les fonctions et les subroutines. Si l'on veut aussi (et c'est hautement souhaitable) gérer les erreurs d'exécution qui pourraient advenir dans le code d'une fonction ou d'une subroutine, celles-ci doivent également commencer chacune par activer l'objet Err au moyen de l'instruction on error resume next (en savoir plus sur l'objet Err ici.)

 

 

f) Chaque exécution d'un code de gestion d'erreur doit se terminer par la remise à zéro de ce code, sinon - puisque c'est un objet et non une simple variable -, les propriétés de cet objet sont conservées pendant toute la durée de son instanciation (de son activation, si vous ne parlez pas OOP :-) Cette remise à zéro se fait avec l'instruction Err.Clear

 

Exemple :

 

On Error Resume Next

Err.Raise 6                         ' Raise an overflow error.

MsgBox "Error # " & Err.Number & " " & Err.Description

Err.Clear                           ' Clear the error.

 

 

g) L'objet Err conserve ses propriétés dans une fonction et une subroutine. C'est ce que l'on appelle avoir un scope global. Une variable déclarée dans une fonction ou une subroutine, elle, n'est pas définie dans le programme principal qui l'a appelée. Elle a un scope local. L'objet Err ayant un scope global, il n'est pas nécessaire de passer la variable Err.Number comme paramètre à une fonction ou à une subroutine de gestion d'erreurs.

 

Exemple :

 

On Error Resume Next
strComputer = "fictional"
strPrinter = "TestPrinter"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
If Err = 0 Then                     'same as "if Err.Number = 0" because default value for object Err
  WScript.Echo "No error binding to " & strComputer
  strPrinter = "TestPrinter"
  Set objPrinter = objWMIService.Get ("Win32_Printer.Name='" & strPrinter & "'")
  If Err = 0 Then
    WScript.Echo "No error connecting to " & strPrinter
  Else
    call DisplayErrorInfo
  End If
Else
  call DisplayErrorInfo
End If

'******************************************************************************
Sub DisplayErrorInfo

  WScript.Echo "Error:      : " & Err
  WScript.Echo "Error (hex) : &H" & Hex(Err)
  WScript.Echo "Source      : " & Err.Source
  WScript.Echo "Description : " & Err.Description
  Err.Clear

End Sub

 

Remarque : Pour tout ce dont on parle ici, il faut garder à l'esprit (ou apprendre) qu'un script exécuté avec succès en local sur une machine - non membre d'un domaine Microsoft Windows et à partir d'un compte doté de privilèges d'administrateur -, ne peut s'exécuter (avec le même succès) à distance sur une autre machine non membre d'un domaine que si l'utilisateur possède le même compte avec le même mot de passe et les mêmes droits sur la machine distante. Si les machines source et destination sont membres d'un domaine (pas nécessairement le même), il suffit de se connecter à distance avec un compte administrateur pour contourner cette difficulté (en savoir plus).

 

[début]


 

IV - ERROR HANDLER EN ENVIRONNEMENT VBScript

 

Il n'existe que deux instructions qui concernent la gestion des erreurs avec VBScript : On Error Resume Next et On Error goto 0. Malheureusement, il n'y a pas la possibilité de gérer des erreurs de façon asynchrone, c'est-à-dire avec des instructions de type On Error gosub XYZ ou On Error goto XYZ qui n'existent pas.

 

Donc la gestion d'un Error Handler n'en sera que plus simple. On écrit un code de traitement des erreurs dans une subroutine, on place une instruction

 

On Error Resume Next

 

au début du script pour désactiver la gestion des erreurs par le moteur de script (donc s'il en advient, le script passe à la ligne suivante sans sourciller), on teste systématiquement la variable système Err (ou Err.Number, c'est pareil) et on appelle la subroutine de gestion d'erreur si cette variable est différente de zéro. C'est ce qui a été montré dans l'exemple ci-dessus, § g.

 

Une subroutine de Error Handler peut être beaucoup plus intéressante - au niveau de l'information retournée -, dans l'environnement VBScript que dans l'environnement de la console de lignes de commande, car la variable Err est en réalité un objet. Cet objet est doté de deux méthodes et cinq propriétés (en savoir plus).

 

Les deux méthodes de l'objet Err (actions possibles sur l'objet Err) sont :

 

Err.Raise               'génère une erreur Run Time

Err.Clear               'reset de l'objet Err

 

Les cinq propriétés de l'objet Err sont :

 

Err.Number              'numéro de l'erreur

Err.Description         'texte descriptif associé

Err.Source              'émetteur de l'erreur (origine)

Err.HelpFile            'spécification complète du nom d'un fichier d'aide éventuel

Err.HelpContext         'clé d'accès à la rubrique du fichier d'aide, si spécifié

 

La méthode Raise n'a pas sa place ici, car nous parlons actuellement d'un Error Handler appelé juste après qu'une erreur est survenue. Le numéro d'erreur sera donc celui renvoyé par l'émetteur de l'erreur et non un numéro choisi par le programmeur.

 

La méthode Clear peut être utile pour remettre les propriétés de l'objet Err à zéro si on ne sort pas de la subroutine de gestion des erreurs par un Wscript.Quit 1 (erreur fatale). Sinon elle est inutile.

 

Parmi les cinq propriétés de l'objet Err, les deux dernières sont rarement utilisées car le type de fichier d'aide ici est l'ancien système, inutilisé depuis Windows XP (fichiers .HLP). Aujourd'hui, les fichiers d'aide sont des fichiers HTML (fichiers .CHM) qui ne sont pas accessibles par la combinaison Err.HelpFile et Err.HelpContext.

 

Voici un exemple de Error Handler synchrone :

 

errmgt.vbs

 

'------------------------------------------------------------------------
'+
' errmgt.vbs
'
' Error handling management routine to be added at the end of a VBscript.
'
' Usage: call errmgt(action,severity)
'
' Two params should be defined in the caller source: the action performed and the severity level.
' If error is not fatal, calling code execution is resumed, otherwise procedure stops.
'
' Note: caller script should be called via Cscript instead of Wscript.
'
' x1.0-0 15-oct-2010 DTL Didier.Morandi at gmail dot com
'-
sub errmgt(WshAction,severity)

if err.number < 0 then
  err_nr = Hex(err.number)
else
  err_nr = err.number
end if

if WshAction = "" then WshAction = "[missing]"
err_desc = err.description
if err_desc = "" then err_desc = "[missing]"
err_src = err.source
if err_src = "" then err_src = "[missing]"

if err_nr <> 0 then
  wscript.echo "WSH>> Error occurred"
  if severity = 0 then                           'information only
    exit sub
  else
    if severity = 1 then                         'warning only
      exit sub
    else
      if severity = 2 then                       'non fatal error, script may continue
        wscript.echo "WSH Action : " & WshAction
        wscript.echo "WSH Error : " & err_nr
        wscript.echo "WSH Descript.: " & err_desc
        wscript.echo "WSH Source : " & err_src
      else
        if severity = 4 then                     'fatal error, script should stop
          wscript.echo "WSH Action : " & WshAction
          wscript.echo "WSH Fatal error: " & err_nr
          wscript.echo "WSH Description: " & err_desc
          wscript.echo "WSH Source : " & err_src
          wscript.quit 1
        else
          wscript.echo "Invalid Severity parameter passed to Error Handler" & vbcrlf
        end if
      end if
    end if
  end if
end if
end sub
'------------------------------------------------------------------------
'eof errmgt.vbs

 

 

Exemple d'utilisation

 

Dans l'exemple qui suit, un script wmi_printer_error.vbs lit les caractéristiques d'une imprimante inexistante sur un ordinateur inexistant. L'ordinateur étant inaccessible, l'erreur est fatale et le Error Handler est appelé une seule fois :

 

c:\vbs>wmi_printer_error toto titi

* Bind to WMI provider on computer 'TOTO'...
WMI>> GetObject failed
WSH>> Error occurred
WSH Action     : GetObject
WSH Fatal error: 462
WSH Description: Le serveur distant n'existe pas ou n'est pas disponible
WSH Source     : Erreur d'exécution Microsoft VBScript

Abort.

c:\vbs>

 

 

Ensuite, on lit les caractéristiques d'une imprimante existante sur un ordinateur existant. L'accès à cette imprimante se fait tout d'abord via son DeviceID. Tout se passe bien. Mais ensuite il est fait par son nom, ce qui n'est pas autorisé. WSH renvoie donc une erreur et appelle SWbemLastError pour en savoir plus. Malheureusement, cet objet n'est pas accessible dans ce contexte et WSH renvoie une deuxième erreur afin d'informer l'exploitant, puis termine le script :

 

c:\vbs>wmi_printer_error . samsung

* Bind to WMI provider on computer 'PCDIDIER'...
* Bind successful
* Get printer 'SAMSUNG' characteristics by DeviceID

Default              : Vrai
DriverName           : Samsung CLP-310 Series
Horizontal Resolution: 600
Network connection   : Faux
Port Name            : USB001

* Get printer 'SAMSUNG' characteristics by Name
WSH>> Error occurred
WSH Action     : GetService
WSH Error nr   : 8004103A
WSH Description: Chemin de l’objet non valide
WSH Source     : SWbemServicesEx
WMI>> Error context follows:
[WMI> creating SwbemLastError object]
WMI>> SwbemLastError CreateObject failed
WSH>> Error occurred
WSH Action     : CreateObject
WSH Error nr   : 80004005
WSH Description: [missing]
WSH Source     : [missing]

c:\vbs>

 

 

Pour télécharger le source du script wmi_printer_error.vbs, cliquer ici.

 

Pour lire une étude détaillée du script wmi_printer_error.vbs et de son Error Handler, cliquer là.

 

[début]


 

V - JOURNALISATION DES ERREURS EN ENVIRONNEMENT VBScript

 

Pour journaliser les erreurs d'un script, nous allons tout naturellement modifier notre Error Handler de façon appropriée.

Voici les lignes qui lui ont été ajoutées ici et là :

 

Dim strLogfile, strData, objFSO, outFile, i
Dim strLine(4)
Const ForAppending = 8
strLogfile = "c:\vbs\log\log.txt"
set objFSO = CreateObject("Scripting.FileSystemObject")
set outFile = objFSO.OpenTextFile(strLogfile, ForAppending, True)

for i = 0 to 4
  strData = now & " - " & Wscript.ScriptName & " - " & strLine(i)
  outFile.WriteLine(strData)
  wscript.echo strLine(i)
next
outFile.Close

 

 

Voyons ce qu'elles signifient.

 

strLogfile

c'est la variable qui contient le nom du fichier de log.

 

strData

c'est la variable qui contient la ligne à écrire dans le fichier de log

 

objFSO

c'est la variable qui sert à instancier l'objet File System

 

outFile

c'est la variable qui sert à exécuter la méthode d'ouverture du fichier de log

 

i

c'est l'indice de boucle de chargement d'une matrice de texte


strLine(4)

c'est une matrice de texte qui contient les données à écrire dans le fichier de log


Const ForAppending = 8

Cette constante permet de préciser à l'ouverture du fichier de log que l'on veut faire un Append


strLogfile = "c:\vbs\log\log.txt"

cette variable contient maintenant la spécification complète du fichier de log

 

set objFSO = CreateObject("Scripting.FileSystemObject")

c'est l'instanciation du File System
 

set outFile = objFSO.OpenTextFile(strLogfile, ForAppending, True)

c'est l'ouverture en mode Append du fichier de log. L'indicateur booléen True signifie que si le fichier n'existe pas il doit être créé.


for i = 0 to 4
  strData = now & " - " & Wscript.ScriptName & " - " & strLine(i)
  outFile.WriteLine(strData)
  wscript.echo strLine(i)
next

Cette boucle crée une ligne de données composée du groupe date/heure (GDH) de l'évènement, suivi du nom de la procédure, suivi d'un texte informatif renseigné dans le Error Handler. Ensuite on écrit dans le fichier de log et enfin on affiche un résumé des données sur l'écran (sans le GDH et sans le nom du script).


outFile.Close

cette instruction ferme le fichier de log afin d'éviter de le verrouiller si une autre procédure souhaite y écrire en même temps.

 

Résultat :

 

Log.txt

 

03/11/2010 16:07:14 - WMI_printer_error_v2.vbs - WSH Action : GetObject
03/11/2010 16:07:14 - WMI_printer_error_v2.vbs - WSH Fatal error: 462
03/11/2010 16:07:14 - WMI_printer_error_v2.vbs - WSH Description: Le serveur distant n'existe pas ou n'est pas disponible
03/11/2010 16:07:14 - WMI_printer_error_v2.vbs - WSH Source : Erreur d'exécution Microsoft VBScript
03/11/2010 16:07:14 - WMI_printer_error_v2.vbs - Procedure terminated abnormally.
03/11/2010 16:07:33 - WMI_printer_error_v2.vbs - WSH Action : GetPrinter
03/11/2010 16:07:33 - WMI_printer_error_v2.vbs - WSH Error nr : 80041002
03/11/2010 16:07:33 - WMI_printer_error_v2.vbs - WSH Description: Non trouvé
03/11/2010 16:07:33 - WMI_printer_error_v2.vbs - WSH Source : SWbemServicesEx
03/11/2010 16:07:33 - WMI_printer_error_v2.vbs -
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Action : GetPrinter
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Error nr : 8004103A
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Description: Chemin de l’objet non valide
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Source : SWbemServicesEx
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs -
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Action : CreateObject
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Fatal error: 80004005
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Description: [text missing]
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - WSH Source : [text missing]
03/11/2010 16:08:01 - WMI_printer_error_v2.vbs - Procedure terminated abnormally

 

Pour télécharger le source du script errmgt.vbs, cliquer ici (clic droit > enregistrer la cible du lien sous)

 

[début]


 

accueil | console | VBScript | PowerShell | documentation | formation  | trucs et astuces | exemples | glossaire