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

API, COM et SDKs Delphi Discussion :

Tuer un service à partir d'un autre service


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre du Club
    Homme Profil pro
    Editeur
    Inscrit en
    Juillet 2002
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Editeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 39
    Points : 50
    Points
    50
    Par défaut Tuer un service à partir d'un autre service
    En environnement Windows 7 64b.

    Je dispose d'un service, lancé en mode administrateur. Ce dernier doit stopper :
    1/ des applications exécutées en mode administrateur,
    2/ des services exécutés en mode administrateur.

    Pour le 1/, cela fonctionne.

    mais pour le 2/, je ne comprends pas ce qui se passe.

    Voici le code utilisé pour stopper un service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    function StopperService(NomService: string): DWORD;
    var
      hsc: SC_HANDLE;
      hSchSvc: SC_HANDLE;
      SvcStatus: TServiceStatus;
    begin
      hsc := OpenSCManager(nil, nil, STANDARD_RIGHTS_READ);
     
      if (hsc = 0) then
        Result := GetLastError
      else
      begin
        hSchSvc := OpenService(hsc, PChar(NomService), SERVICE_ALL_ACCESS);
        CloseServiceHandle(hsc);
     
        if (hSchSvc = 0) then
          Result := GetLastError
        else
        begin
          // Stoppe le service
          if ControlService(hSchSvc, SERVICE_CONTROL_STOP, SvcStatus) then
          begin
            CloseServiceHandle(hSchSvc);
            Result := ERROR_SUCCESS;
          end
          else
            Result := GetLastError
        end;
      end;
    end;
    Je précise que ce code fonctionne lorsqu'il est utilisé dans un programme, mais pas à partir d'un autre service...

    Si quelqu'un pouvait éclaircir ma lanterne, je pense à une histoire de droits (fonctionne bien sous XP par exemple), mais je ne vois pas....

    Par avance merci à vous tous.

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Que dit GetLastError ?
    Philippe.

  3. #3
    Membre du Club
    Homme Profil pro
    Editeur
    Inscrit en
    Juillet 2002
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Editeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 39
    Points : 50
    Points
    50
    Par défaut
    On passe bien dans les lignes 24 et 25, et getLastError me renvoi ERROR_SUCCESS.

    On pourrait ainsi croire que le service estbien arrêté, mais non, il tourne toujours...... Peut-être parce que le dit service était en train d'effectuer une tâche et qu'il n'a pas bien reçu l'ordre de s'arrêter ?

    j'ai aussi essayer de tuer le processus (plutôt que d'arrêter le service), pas la procédure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    function TuerProcessus(NomProcessus: string;IDProcessus : Cardinal = 0;TypeProcessus : Byte = 0): integer;
    var
      bNext            : boolean;
      bProcessusTrouve : boolean;
      hSnapshotHandle  : THandle;
      pProcessEntry32  : TProcessEntry32;
      hProcessHandle   : THandle;
    begin
      Result := -1;
     
      // Obtient la liste des processus
      hSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      if (hSnapshotHandle <> THandle(-1)) then
      begin
        // Cherche le processus en paramètre
        try
          pProcessEntry32.dwSize := SizeOf(pProcessEntry32);
          bNext := Process32First(hSnapshotHandle, pProcessEntry32);
          while bNext do
          begin
            case TypeProcessus of
              // Par ID processus Windows
              1 : begin
                    // Recherche si l'identifiant est fourni
                    if IDProcessus > 0 // Recherche sur l'ID et le nom
                    then bProcessusTrouve := (IDProcessus = pProcessEntry32.th32ProcessID) and
                                             ((UpperCase(ExtractFileName(pProcessEntry32.szExeFile)) = UpperCase(NomProcessus))  or
                                              (UpperCase(pProcessEntry32.szExeFile)                  = UpperCase(NomProcessus)))
                    else bProcessusTrouve := ((UpperCase(ExtractFileName(pProcessEntry32.szExeFile)) = UpperCase(NomProcessus))  or
                                              (UpperCase(pProcessEntry32.szExeFile)                  = UpperCase(NomProcessus)));
                  end
              // par défaut sinon sur le nom du processus
              else
                begin
                  bProcessusTrouve := ((UpperCase(ExtractFileName(pProcessEntry32.szExeFile)) = UpperCase(NomProcessus))  or
                                       (UpperCase(pProcessEntry32.szExeFile)                  = UpperCase(NomProcessus)));
                end;
            end;
            if bProcessusTrouve then
            begin
              // Processus trouvé, essaye de le tuer
              Result := 0;  // Processus trouvé, mais pas encore tué
              hProcessHandle := OpenProcess(SERVICE_ALL_ACCESS, False, pProcessEntry32.th32ProcessID);
              if (hProcessHandle <> 0) then
              begin
                try
                  Result := Integer(TerminateProcess(hProcessHandle, 0));
                finally
                  CloseHandle(hProcessHandle);
                end;
              end;
              break;   // Si le processus est trouvé, on sort de la boucle quelque soit le résultat de fermeture du processus
            end;
           bNext := Process32Next(hSnapshotHandle, pProcessEntry32);
          end;
        finally
          CloseHandle(hSnapshotHandle);
        end;
      end;
    end;
    résultat pas plus encourageant

  4. #4
    Membre éclairé
    Avatar de Whiler
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 298
    Points : 664
    Points
    664
    Par défaut
    Citation Envoyé par lgirard Voir le message
    Je précise que ce code fonctionne lorsqu'il est utilisé dans un programme, mais pas à partir d'un autre service...
    Il fonctionne si j'exécute mon application en tant qu'administrateur... sinon, le service n'est pas arrêté...

    Citation Envoyé par lgirard Voir le message
    Si quelqu'un pouvait éclaircir ma lanterne, je pense à une histoire de droits (fonctionne bien sous XP par exemple), mais je ne vois pas....
    Je ne sais pas comment on exécute un service en tant qu'administrateur...
    (pour avoir les droits qui vont bien...)

    Éventuellement, s'il n'y a pas besoin que ce soit un service, il est possible de planifier une tâche Windows pour que celle-ci s'exécute en tant qu'administrateur... ce n'est pas la réponse à la question, mais un éventuel workaround en attendant mieux....

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 712
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 712
    Points : 13 179
    Points
    13 179
    Par défaut
    Citation Envoyé par Whiler Voir le message
    Je ne sais pas comment on exécute un service en tant qu'administrateur...
    Un service tourne sous le compte SYSTEM. On ne peut pas espérer plus de droits

    Sinon, j'essayerais un simple ShellExecute(..., 'net.exe', 'stop "Ton Service"', ...)

  6. #6
    Membre éclairé
    Avatar de Whiler
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 298
    Points : 664
    Points
    664
    Par défaut
    oui, mais...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ---------------------------
    Error
    ---------------------------
    Unable to create process: L’opération demandée nécessite une élévation.
    ---------------------------
    OK   
    ---------------------------

    Pour obtenir ça, j'ai fait le test suivant :
    Un service qui appelle une appli console où j'ai modifié le manifest pour demander une élévation...
    Si je lance l'appli console à la main, j'ai un prompt pour l'élévation que j'accepte, et le service s'arrête (via le shellexecute ou la fonction StopperService)...

    Si le service appelle mon appli console... l'élévation n'a pas lieu.. et donc, l'autre service n'est pas arrêté...

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 712
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 712
    Points : 13 179
    Points
    13 179
    Par défaut
    Ton test n'est pas de service à service mais passe par une application desktop
    Je doute fort que l'UAC ait une quelconque influence sur la session 0. Sinon aucun service ne fonctionnerait convenablement...

  8. #8
    Membre éclairé
    Avatar de Whiler
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 298
    Points : 664
    Points
    664
    Par défaut Oups
    Bon... ce que j'ai dit dans mon précédent message est faux...

    et tu as bien sur raison sur tous les points...

    Le shellexecute avec fonctionne nickel.
    et mon élévation ne pose aucun pb !

    (mes précédents tests étaient pourris... j'avais les méthodes start et execute, mais j'avais juste oublié de les câbler sur le service.. donc, forcément, il se passait pas grand chose)

  9. #9
    Membre du Club
    Homme Profil pro
    Editeur
    Inscrit en
    Juillet 2002
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Editeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 39
    Points : 50
    Points
    50
    Par défaut
    Merci à tous pour votre participation à cette réflexion.

    La solution trouvée réside dans le paramétrage d'exécution du service A, celui qui doit 'tuer' le service B.
    En effet, il faut que le service A soit lancé en mode 'standard' (dans les propriétés du service, onglet 'connexion', ouvrir une session en tant que 'compte système local'.
    Dans mon exemple, pour d'autre raisons, il était nécessaire que le service B soit quant à lui lancé avec le compte administrateur.

    Mes tests m'ont également montré que la plateforme ne change rien dans ce paramétrage: XP ou W7 il faut le même paramétrage pour chacun de ces 2 services.

    Encore une fois, merci à tous pour vos posts.

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 469
    Points : 24 905
    Points
    24 905
    Par défaut
    Pour la configuration avancée, il y a aussi sc.exe
    Je m'en suis servi pour affecter un compte utilisateur en ligne de commande sans passer par les écrans de services.msc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sc.exe config obj=... password=...
    Si tu es l'auteur des DEUX services, rien ne t'empeche un échange de message interne, et que la cible se termine d'elle-même à la reception du message, cela peut t'éviter les problèmes de droits
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 31/12/2013, 10h26
  2. Windows 8, Service WCF appelant un autre service WCF
    Par gbrout dans le forum Services Web
    Réponses: 0
    Dernier message: 18/08/2012, 00h20
  3. Réponses: 2
    Dernier message: 03/05/2012, 17h43
  4. appel d'un service à partir d'un autre service
    Par sitws dans le forum Débuter
    Réponses: 1
    Dernier message: 19/06/2011, 16h27
  5. Réponses: 30
    Dernier message: 02/12/2005, 15h30

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