Détecter une erreur

Signaler
Messages postés
76
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
8 septembre 2006
-
Messages postés
69
Date d'inscription
jeudi 6 novembre 2003
Statut
Membre
Dernière intervention
3 octobre 2006
-
Bonjour à tous,

   Voilà je fais un p'tit dev en VB6. Celui-ci a pour but de lancer l'exécution d'un exécutable. Je n'ai pas accès aux sources de cet exécutable.
   Le problème est que cet exécutable tombe parfois dans l'erreur suivante:


             Erreur d'exécution '-2147417848 (80010108)':

             Erreur Automation
             L'objet invoqué s'est déconnecté de ses clients.

   Mon but: détecter le déclenchement de cette erreur, tuer le processus et le relancer.
Jusqu'ici, je procédait de la manière suivante: un timer vient régulièrement vérifier la mémoire utilisée par ce processus. Si celle ci reste à la même valeur trop longtemps, le processus est considéré comme planté et je le tue.
   Sauf que ce test sur la mémoire n'et pas fiable. La mémoire utilisée peut être stable pendant un fonctionnement normal... Donc il faut que je trouve autre chose et c'est là que j'ai besoin de vous...
Connaissez vous une API capable de détecter une erreur d'un prcessus externe???
Ou alors je peut peut-être me baser sur l'occupation du CPU mais je ne sais pas remonter cet info...
Ou alors je suis ouvert à toute autre proposition...
Merci d'avance à la bête de VB qui me solutionnera!

7 réponses

Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
49
salut,

tu ne peux pas gérer directement lors de l'arrivée de cette erreur?
cad si erreur Erreur Automation
             L'objet invoqué s'est déconnecté de ses clients.
alors etc... ?

Prenez un instant pour répondre à ce sondage svp
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
Un prog qui plante, on le vire mais on ne l'utilise pas comme base pour un futur dev.

ciao...
BruNews, MVP VC++
Messages postés
76
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
8 septembre 2006

Hey Mr Brunews le grand admin! Tu n'est pas très constructif! (c'est mal)
Croyez moi, si j'utilise ce prog, c'est parce que j'y suis obligé, et pour répondre à PCPT, je n'ai pas accès aux sources de l'appli qui plante. je le lance juste par un "Shell(<Ligne de commande>)". 
Mon éditeur ne veut rien y faire. Donc moi je fait mon petit dev pour palier au problème et pour relancer le soft. Kapich???

Ce qu'il me faudrait, c'est une API capable de remonter l'état d'erreur d'un processus, ou un truc du genre...
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
Je ne pouvais pas deviner que tu es obligé de le faire, sinon je maintiens.

ciao...
BruNews, MVP VC++
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
49
umm...
avec un peu (beaucoup) de bol l'appli ou windows écrit un petit truc utile dans le journal des évènements...

çà peut être une piste
++
Prenez un instant pour répondre à ce sondage svp
Messages postés
69
Date d'inscription
jeudi 6 novembre 2003
Statut
Membre
Dernière intervention
3 octobre 2006

Salut,

Il est possible de faire ce que tu demande avec les api suivantes:

    - CreateProcess
    - WaitForSingleObject
    - GetExitCodeProcess
    - CloseHandle
Ces api sont dans Kernel.dll

Le principe: au lieu de lancer la commande par shell on le fait avec CreateProcess et on récupère le handle du process (la procédure CreateProcess est assez compliqué, il y a quelques structures à déclarer et à renseigner avant de l'exécuter). Puis on execute dans une boucle WaitForSingleObject avec un DoEvents jusqu'à que la commande se termine. En sortie de boucle on lance GetExitCodeProcess pour récupérer le code erreur du process, et enfin on ferme le process par CloseHandle.

Si le code erreur correspond, alors on relance tout le processus jusqu'a l'obtention  d'un code retour correcte.  Cependant si ton  exécutable part systématiquement en erreur automation,  il  faut prévoir une porte  de sortie, sinon ton  prog va tourner éternèlement.

J'ai déjà utilisé ces api dans le temps, Si je le retrouve dans mes sources je t'envairai un exemple à l'occasion.
Messages postés
69
Date d'inscription
jeudi 6 novembre 2003
Statut
Membre
Dernière intervention
3 octobre 2006

Trouvé ! Voici un exemple de code mettant en pratique les api pré-citées:

Option Explicit

Private Const STARTF_USESTDHANDLES = &H100&
Private Const STARTF_USESHOWWINDOW = &H1
Private Const WAIT_TIMEOUT = &H102
Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type
Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Byte
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type
Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type
Private Enum enPriority_Class
    NORMAL_PRIORITY_CLASS = &H20
    IDLE_PRIORITY_CLASS = &H40
    HIGH_PRIORITY_CLASS = &H80
End Enum

'Api de création d'un process
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" _
    (ByVal lpApplicationName As String, _
    ByVal lpCommandLine As String, _
    lpProcessAttributes As SECURITY_ATTRIBUTES, _
    lpThreadAttributes As SECURITY_ATTRIBUTES, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, _
    lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION) As Long
   
'Verification de l'état d'un process
Private Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long

'Fermeture d'un handle
Private Declare Function CloseHandle Lib "kernel32" (ByVal hHandle As Long) As Long

'Api pour vérifier le code Exit du process aprés exécution
Private Declare Function GetExitCodeProcess Lib "kernel32" _
    (ByVal hProcess As Long, lpExitCode As Long) As Long

Public Function ExecuteProg(ProgPath) As Long
    Dim RetCode               As Long
    'Structure pour CreateProcess
    Dim Startup             As STARTUPINFO
    Dim Secur               As SECURITY_ATTRIBUTES
    Dim ProcInfo           As PROCESS_INFORMATION
    ' Code Exit du process
    Dim mExitCode       As Long
   
  'Renseignement de la structure SECURITY_ATTRIBUTES
    Secur.nLength = Len(Secur)
    Secur.bInheritHandle = 1&
    Secur.lpSecurityDescriptor = 0&

  'Renseignement de la structure STARTUPINFO
    Startup.cb = Len(Startup)
    Startup.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
 
  'Création du process (Exécution du prog)
    If CreateProcess(ProgPath, 0&, Secur, Secur, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, Startup, ProcInfo) <> 1 Then
        MsgBox "Executable non trouvé.", vbCritical
        Exit Function
    End If
   
    'Boucle d'attente de fin du programme
    Do
        RetCode = WaitForSingleObject(ProcInfo.hProcess, 0&)
        DoEvents
    Loop While RetCode = WAIT_TIMEOUT

  'Obtention du code Exit du process
    RetCode = GetExitCodeProcess(ProcInfo.hProcess, mExitCode)
   
  'Fermeture des Handles du process créé
    RetCode = CloseHandle(ProcInfo.hProcess)
    RetCode = CloseHandle(ProcInfo.hThread)
   
    'Renvoie du code Exit
    ExecuteProg = mExitCode
End Function

Ce code est à mettre dans un module. La fonction ExecuteProg execute le programme donnée en paramêtre et renvoie son code Exit aprés exécution.

Voilà ! En espérant que ce petit source puisse t'aider...