IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

Comment récupérer le code de sortie d'un service ?


Sujet :

Windows

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut Comment récupérer le code de sortie d'un service ?
    Bonjour, et meilleurs vœux pour cette nouvelle année.

    Je développe un service à l'aide de Visual Studio 2008, en VB.net.

    Il s'agit d'un service qui exécute diverses actions sur lancement avec passage de paramètres. J'utilise pour celà, par le biais d'un formulaire tier également développé en VB.net, la classe ServiceController, qui me permet de lancer mon service en lui passant des arguments via un tableau ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Public ServiceAlias As New System.ServiceProcess.ServiceController
    TabArgs(0) = "verifie"
    TabArgs(1) = "quelquechose"
    ServiceAlias.MachineName = "."
    ServiceAlias.ServiceName = "Alias"
    ServiceAlias.Start(TabArgs)
    Mon service, avec un Select Case, fait des tests, et je souhaite renvoyer un code de sortie selon le résultat de mon test. Pour celà, j'utilise la procédure OnStop() du service.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Protected Overrides Sub OnStop()
            Me.ExitCode = 1250
        End Sub
    Ma question est la suivante : comment faire pour obtenir ce code de sortie depuis mon application qui a lancé le service, sachant que la classe ServiceController n'inclut pas la propriété ExitCode ?

    Pour information, lorsque je lance mon service à l'aide de SC, ça me retourne ceci :
    ---------------------
    SERVICE_NAME: alias
    TYPE : 10 WIN32_OWN_PROCESS
    STATE : 2 START_PENDING
    (NOT_STOPPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE : 0 (0x0)
    SERVICE_EXIT_CODE : 0 (0x0)

    CHECKPOINT : 0x0
    WAIT_HINT : 0x7d0
    PID : 1444
    FLAGS :
    ---------------------


    Je vous remercie par avance de vos réponses.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Ce que tu veux faire n'a pas de sens car la philosophie d'un service est qu'il ne s'arrête jamais (sauf crash, action utilisateur et arrêt de la machine) donc c'est probablement pour cela qu'il n'existe pas de moyen pour récupérer le code de fin de service.

    Il va falloir trouver un autre moyen.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    En effet, j'aurais préféré que le service reste lancé perpétuellement, mais le lancement avec paramètres est le seul moyen que j'ai trouvé pour transmettre des données au service.

    Par exemple, si je souhaite vérifier l'existence d'un fichier dans %WINDIR%\system32, répertoire auquel l'utilisateur lambda n'a pas les droits d'accès, je souhaite faire faire cette vérification par mon service fonctionnant sous le compte SYSTEM.

    Concrètement, j'envoie à mon service deux arguments :
    1) Quelle action ? => Tester l'existence
    2) Quelle donnée ? => Le fichier C:\WINDOWS\system32\calc.exe

    Le seul moyen que j'ai trouvé est donc le lancement avec paramètres, via la classe ServiceController.

    Il existe bien une méthode ExecuteCommands dans ctete même classe, mais on ne peut transmettre qu'un seul entier en paramètre.

    Je suis donc preneur d'une solution alternative pour pallier ce problème, sachant que mon application faisant appel au service est restreinte par les droits très limités de l'utilisateur qui la lance (pas le droit d'écrire dans le registre par exemple).

    Cordialement.

    Edit : j'ai consulté ça
    http://www.developpez.net/forums/d53...rvice-windows/
    et ça
    http://www.developpez.net/forums/d46...laircissement/
    sans succès :-(

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Une idée comme cela :
    Un service lancé en permanence qui écoute sur un pipe nommé et qui ne s'arrête jamais.
    Un programme utilisateur qui communique avec le service par le biais du pipe nommé et envoie des commandes au service.
    Le service reçoit les commandes, les exécute et retourne le résultat dans le pipe
    Le client reçoit le résultat dans le pipe et affiche/traite le résultat.

    A toi de définir maintenant le protocole entre le client et le service porté par le pipe.

    Attention aux droits sur le pipe, ils doivent être compatibles entre le service qui a des privilèges systeme et le client qui a priori a des droits restreints.

    Attention aussi à la sécurité, ce que tu veux faire permet à un utilisateur lambda d'e faire faire des choses avec des droits étendus et ce n'est pas forcémment une bonne idée, c'est comme cela qu'un utilisateur lambda peut devenir administrateur de la machine.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Merci pour cette piste qui va me diriger vers de belles recherches, car j'ignore complètement ce concept de pipe (disons que je sais que c'est un tunnel bidirectionnel mais je l'ai toujours utilisé en environnement Linux pour faire communiquer deux programmes, par exemple ps aux | grep unprocessus, mais en développement, aucune idée !).

    Pour la sécurité, j'imagine effectivement que le risque est grand mais mon service a vraiment des fonctionnalités limitées, lesquelles sont de toutes façons imbriquées dans un Select Case.

    Je m'en vais rechercher un tuto pour les pipes :-)

    Merci !

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 217
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par CleM_71 Voir le message
    [...]Je m'en vais rechercher un tuto pour les pipes :-)
    Oui, les named pipes sont certainement adaptés à votre problématique. Un tutoriel vous aidera sans doute à démarrer rapidement.

    Vous avez aussi cette ressource Microsoft qu'il peut être utile de lire, si vous êtes en framework 3.x :

    http://msdn.microsoft.com/fr-fr/library/ms752253.aspx

    Bonne suite.

    'HTH

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    J'ai cherché un peu de partout et j'ai eu beaucoup de mal à trouver quelque chose de simple à mettre en œuvre.

    Du coup, je me suis tourné vers ça http://www.codeproject.com/KB/vb/AsyncNamedPipes.aspx

    Je vais tâcher de faire une mini-appli utilisant cette référence tierce, pour comprendre comment ça marche, et je me plongerai dans la source de la référence pour en analyser le fonctionnement.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Mes recherches se poursuivent, et mon projet avance ! Avec la référence que je vous présentais précédemment, je suis parvenu à faire communiquer mon service et mon application, parfaitement, enfin presque ...

    Mon application envoie à mon service un message, codé en octets, de type texte à l'origine.

    En l'occurrence, voici le code permettant, après ouverture du pipe nommé, d'écrire dans le pipe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ' Message est un tableau d'octets, de taille 2048
    ' La fonction suivante convertit la chaîne de caractères en octets
    ' LeBouton.Tag contient un chemin absolu local de type "C:\Repertoire\Fichier.exe"
    Message = System.Text.Encoding.Unicode.GetBytes("verifie?" + LeBouton.Tag)
    ' Ecriture du message dans le pipe nommé
    StreamAlias.Write(Message, 0, Message.Length)
    Du côté du service, je lis le message par l'intermédiaire d'une boucle Do Until ...
    Voici la ligne me permettant, à priori, de récupérer le texte que j'ai envoyé dans le pipe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ' MesssageTexte est déclaré en String
     MessageTexte = System.Text.Encoding.Unicode.GetString(Tampon, 0, Tampon.Length)
    Çà marche à merveille, sauf qu'il manque un guillemet à la fin !
    Dans la fenêtre des variables locales, avec le visualiseur de type texte, voici le contenu de MessageTexte après affectation :

    "verifie?C:\Program Files\7-Zip\7zFM.exe

    Il manque donc un guillemet à la fin ! Ou bien il y en a un de trop au début ?

    En vrac, voici ce que j'ai essayé :
    - utilisation abusive de la fonction ToString() lors de l'affectation de MessageTexte
    - essai de la fonction Insert() pour insérer un guillemet à la fin, et ce avec le code ASCII Chr(34) ou le caractère en lui même """"
    - Essai de la fonction Replace() pour remplacer le guillemet du début par rien du tout : aucun guillemet n'est remplacé ...
    - Essai de la fonction Remove() pour enlever le premier caractère : c'est la première mettre qui disparaît ...

    J'en viens donc à vous pour tenter de trouver une solution pour que ma chaîne en soit une vraie ...

    J'ai trouvé une solution, très lourde ...
    Déclarer un tableau de Char de taille 2048, et avec un Foreach, traiter chaque caractère de la chaîne pour les concaténer dans une variable String. Ca marche mais c'est très loin de m'arranger, dans un soucis de clarté du code, et d'optimisation des traitements ...

    Merci d'avance

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Je m'auto-réponds.

    Mon problème venait du troisième argument de la fonction de conversation en String depuis les octets : je lisais la totalité du tampon au lieu de ne lire que la partie utilisée.

    Par ailleurs, je suis parvenu à effectuer ce que je souhaitais avec les Pipes Nommés. J'ai commencé par faire tout ce dont j'avais besoin dans un Windows Form classique, plus facile à débuguer qu'un service ...

    Lorsque j'ai migré mon code dans le service, la communication entre le "listener" et le "client" ne s'établit pas.

    J'en viens à me demander, et donc, à VOUS demander, si un service fonctionnant avec le compte LocalSystem n'est pas enfermé dans une sorte de "sandbox", ce qui l'empêcherait de recevoir les connexions initiées par mon application tierce.

    Merci

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Pour les tubes nommés, je sais qu'il y a un paramètre à régler dans la base de registre ou plutôt dans les group policies, indiquant les noms des pipes auxquels le commun des mortels a le droit de se connecter.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Voilà une piste sympa !

    J'ai commencé à éplucher le gpedit.msc, et je suis tombé sur une règle :

    "Accès réseau : les canaux nommés qui sont accessibles de manière anonyme"

    Il s'agit d'une liste de noms séparés par des virgules. J'y ai ajouté le nom de mon canal, mais le problème reste identique.

    Pour info, je trouve ça dans "Configuration ordinateur", "Paramètres Windows", "Paramètres de sécurité", "Stratégies locales", "Options de sécurité".

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Bon ... Point mort ...

    Dans gpedit.msc j'ai bien rajouté mon pipe dans la liste de ceux qui peuvent être appelés anonymement.

    J'ai redémarré le poste, le service, constaté que le pipe était bien accessible anonymement (j'ai regardé dans la base de registre).

    J'ai téléchargé un outil (http://www.beyondlogic.org/solutions...ec/pipesec.htm) permettant de consulter et d'éditer les droits sur le pipe.

    Je l'ai rendu accessible en tous droits par tout le monde (le temps d'un test, bien sûr) et je ne parviens toujours pas à me connecter à mon pipe ...

    J'ai parcouru la référence que j'ai téléchargée (http://www.codeproject.com/KB/vb/AsyncNamedPipes.aspx) pour éplucher les propriétés du listenner, et constater tout est OK.

    Je commence à être bien bloqué.

    Quelqu'un a-t-il un mini code à me faire tester pour un connexion client-serveur avec un pipe nommé ?



    _________

    Edit et complément d'information :

    mon client dispose d'une propriété isConnected. Celle ci est bien à True après l'appel de la méthode Connect.

    Il semble donc que la connexion soit bonne, mais que c'est du côté du service que l'évènement ClientConnected déconne.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Désolé pour mon acharnement, mais je crois avoir trouvé le souci.

    J'ai posé un timer avec un délai de 1000 ms. Dans l'évènement Tick() j'ai fait ça en sorte d'écrire un fichier texte sur mon disque.

    Rien ne se passe ...

    Il semble donc qu'aucun évènement ne fonctionne sur le service ...

    Y a-t-il quelque chose à faire pour activer les évènements ??

Discussions similaires

  1. [VB 2005] Comment récupérer un code dans une release
    Par Herlece dans le forum Windows Forms
    Réponses: 2
    Dernier message: 17/10/2007, 19h02
  2. Comment récupérer un code retour SFTP ?
    Par hervé94 dans le forum Shell et commandes GNU
    Réponses: 1
    Dernier message: 28/08/2007, 20h45
  3. [C#]Comment récupérer le code d'une Exception ?
    Par joujoukinder dans le forum C#
    Réponses: 18
    Dernier message: 30/07/2007, 01h47
  4. Comment récupérer le code ASCII d'un caractère?
    Par Blue_Strike dans le forum Delphi
    Réponses: 6
    Dernier message: 04/05/2007, 00h38
  5. Réponses: 5
    Dernier message: 21/12/2004, 18h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo