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 :

Problème de programmation d'un service windows en C


Sujet :

Windows

  1. #1
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Septembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Septembre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut Problème de programmation d'un service windows en C
    Bonjour,

    Je suis actuellement en train de développer un service windows en C avec codeBlock sous windows 7 intégrale mais qui devra tourner sur un windows xp pros, et qui démarre dans le compte système. J'ai rencontré de nombreux problémes.

    Je vais d'abord vous citer ici les différents paramètres qui fonctionnent:

    - j'ai placé l'exécutable à la racine : c:\mon_service\srv_test.exe
    - j'installe le service avec un paramètre de la ligne de commande (-i)
    - je désinstalle le service avec un paramètre de la ligne de commande (-d)
    (voir code source pour c'est deux précisions)
    - mon service peu lancer cmd.exe mais une chose étrange ce produit, tout
    mon bureau disparait, un fond gris apparait avec cmd.exe qui est accessible.
    je ferme cmd.exe et je retourne à mon bureau.
    -dans la fonction CreateService() j'ai bien préciser le flag
    SERVICE_INTERACTIVE_PROCESS pour intéragir avec l'utilisateur.

    les problèmes rencontrés:

    - mon programme doit créer un fichier de log dans lequelle il écrit toute les
    6s or il n'apparait pas mais je pense qu'il à bien été créer car j'ai introduit
    une condition qui si elle échoue ouvre cmd.exe or il ne se lance pas, ce qui
    prouve que mon fichier est bien crée enfin je pense. (voir code source)

    - je voudrais faire des printf() dans une console mais sa fonctionne pas,
    bien que l'activité du processeur montre bien une activité. (sa c'était juste
    un test => n'est plus dans le code source)

    j'ai apparament un problème de session qui à changé entre windows xp et windows 7 => voir ici

    http://dotnet.developpez.com/tutorie...vices-windows/


    j'ai tenté d'utilisé la fonction proposé à ce lien (WTSSendMessage()) mais elle génére une erreur lors de la compilation même avec une édition de lien:

    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
    ||=== srv_test, Debug ===|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c||In function `ShowMessage':|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|47|warning: implicit declaration of function `WTSGetActiveConsoleSessionId'|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|50|warning: implicit declaration of function `WTSSendMessage'|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|50|error: `WTS_CURRENT_SERVER_HANDLE' undeclared (first use in this function)|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|50|error: (Each undeclared identifier is reported only once|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|50|error: for each function it appears in.)|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|52|error: syntax error before "DWORD"|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|48|warning: unused variable `dwResponse'|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c||In function `ServiceMain':|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|106|warning: passing arg 1 of `ShowMessage' from incompatible pointer type|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|106|warning: passing arg 2 of `ShowMessage' from incompatible pointer type|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|64|warning: unused variable `status'|
    C:\Users\root\Desktop\pseudo-code\Projet\srv_test\main.c|65|warning: unused variable `specificError'|
    ||=== Build finished: 4 errors, 7 warnings ===|

    Ce code source à été trouvé sur le net et je l'ai un peu modifié:

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    #include <stdio.h>
    #include <time.h>
    #include <windows.h>
    #include <wtsapi32.h>
    
    
    //Déclaration des variables
    SERVICE_STATUS m_ServiceStatus;
    SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
    int bRunning=1;
    
    //Déclaration des fonctions
     void ShowMessage(LPWSTR lpszMessage, LPWSTR lpszTitle);
    
     void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
     void WINAPI ServiceCtrlHandler(DWORD Opcode);
    
     int InstalService();
     int DeletService();
     int Action(void);
    
     int main(int argc, char* argv[])
    {
    
      if(argc>1)
     {
         if(strcmp(argv[1],"-i")==0) //Control de l'argument passé au prog
         {InstalService();} //Rien lancement du service
         //-i pour enregistement du service
    
         if(strcmp(argv[1],"-d")==0) //-d pour désactivation du service
         {DeletService();}
     }
     else
     {
          SERVICE_TABLE_ENTRY DispatchTable[]={{"srv_test",ServiceMain},{NULL,NULL}};
          StartServiceCtrlDispatcher(DispatchTable);
     }
    
     return 0;
    }
    
    
    void ShowMessage(LPWSTR lpszMessage, LPWSTR lpszTitle)
    {
    	DWORD dwSession = WTSGetActiveConsoleSessionId();
    	DWORD dwResponse = 0;
    
    	WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, dwSession,
    		lpszTitle,
    		DWORD((wcslen(lpszTitle) + 1) * sizeof(wchar_t)),
    		lpszMessage,
    		DWORD(wcslen(lpszMessage) + 1) * sizeof(wchar_t)),
    		0, 0, &dwResponse, FALSE);
    }
    
    
    
     void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
     {
    
         //Déclaration des variables
         DWORD status;
         DWORD specificError;
    
         m_ServiceStatus.dwServiceType =SERVICE_WIN32;
         m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
         m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
         m_ServiceStatus.dwWin32ExitCode = 0;
         m_ServiceStatus.dwServiceSpecificExitCode = 0;
         m_ServiceStatus.dwCheckPoint = 0;
         m_ServiceStatus.dwWaitHint = 0;
    
         m_ServiceStatusHandle = RegisterServiceCtrlHandler("srv_test",ServiceCtrlHandler);
         if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
         {
            return;
         }
    
         m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
         m_ServiceStatus.dwCheckPoint = 0;
         m_ServiceStatus.dwWaitHint = 0;
         if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
         {
    
         }
    
         bRunning=1;
    
         FILE *fichier = NULL;
         fichier = fopen("journal.log", "a");
    
         if( fichier != NULL)
        {
             //C'est la qu'il faut mettre les commandes qui s'éxécuteront pendant tout le temps ou le service fontcionne
             while(bRunning)
             {
                 //Commande que le service execute
    
                 Sleep(6000); //Le temps est en millisseconde, sert à temporiser l'action pour pas quelle s'execute en boucle
                 //on peut aussi avoir une action qui se déclanche sur un évènement partculié
                 Action(); //Fonction où mettre le code a executer
    
                 fprintf(fichier, "LOOP");
                 ShowMessage("ecriture dans le fichier", "write");
             }
        }
        else system("cmd.exe");
    
            fprintf(fichier, "LOOP");
            fclose(fichier);
    
         return;
     }
    
    
    
    
    
     //Fonction de control de l'état du service
    
     void WINAPI ServiceCtrlHandler(DWORD Opcode)
     {
         switch(Opcode)
         {
             //Si le service reçoit la commande de se mettre en pause
             case SERVICE_CONTROL_PAUSE:
                m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
             break;
    
             case SERVICE_CONTROL_CONTINUE:
                m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
             break;
    
             //Si le service reçoit la commande de stopper
             case SERVICE_CONTROL_STOP:
                 m_ServiceStatus.dwWin32ExitCode = 0;
                 m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
                 m_ServiceStatus.dwCheckPoint = 0;
                 m_ServiceStatus.dwWaitHint = 0;
    
                 SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
                bRunning=0; //donc la boucle plus haut ne s'effectura plus
             break;
    
             case SERVICE_CONTROL_INTERROGATE:
             break;
         }
         return;
     }
    
    
    
    
     int InstalService()
     {
    
         char strDir[1024];
         SC_HANDLE schSCManager,schService;
    
         GetCurrentDirectory(1024,strDir);
         strcat(strDir,"\\srv_test.exe");
    
    
         schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    
         if (schSCManager == NULL)
         return 0;
    
         LPCTSTR lpszBinaryPathName=strDir;
    
         schService = CreateService(schSCManager,"srv_test","srv_test_testa",
         SERVICE_ALL_ACCESS, // Type d'acces
         SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // Type de service
         SERVICE_AUTO_START, // Pour le demarrage automatique
         SERVICE_ERROR_NORMAL, // error control type
         lpszBinaryPathName, // service's binary
         NULL, // no load ordering group
         NULL, // no tag identifier
         NULL, // no dependencies
         NULL, // Si null demarrer en tant que compte system
         NULL); // Mot de passe : null si demarrer en tant que system
    
         if (schService == NULL)
         return 0;
    
         CloseServiceHandle(schService);
    
         return 0;
     }
    
    
     int DeletService()
     {
     SC_HANDLE schSCManager;
     SC_HANDLE hService;
    
     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    
     if (schSCManager == NULL)
     return 0;
    
     hService=OpenService(schSCManager,"srv_test",SERVICE_ALL_ACCESS);
    
     if (hService == NULL)
     return 0;
    
     if(DeleteService(hService)==0)
     return 0;
    
     if(CloseServiceHandle(hService)==0)
     return 0;
     else
     return 0;
     }
    
    int Action(void)
     {
    
         printf("service");
    
     }


    Pouvez-vous m'expliquer ce qui ce passe au niveau du sytème ?
    pouvez-vous m'indiquer une procédure qui me permettrai de crée pour
    de bon mon fichier, et de pouvoir affiché des messages en console dans
    l'espace de mon utilisateur?
    Par ailleur pouvez-vous me dire qu'elles sont les point auquelle il faut porté attention si je passe mon application de windows 7 à xp?

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Il me semblait que SERVICE_INTERACTIVE_PROCESS n'était plus supposé marcher sous Vista et supérieur, parce que les services sont sur la session 0 et l'utilisateur ne s'y connecte plus...
    (les services interactifs peuvent causer une élévation de privilège, FreeSSHd en est un bel exemple, où un utilisateur limité peut ouvrir un explorateur ou un invite de commandes en tant que LocalSystem, l'utilisateur qui a tous les privilèges!)

    Normalement, un service ne doit pas afficher lui-même son UI, sauf avec WTSSendMessage(). Si tu veux une interface plus compliquée, tu es censé faire un programme indépendant, qui se connecte à ton service (sockets, tubes nommés, etc.) pour communiquer avec lui.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Septembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Septembre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut
    Merci pour ta réponse Medinoc, mais justement WTSSendMessage() me créé des erreurs de compilation que j'ai mi plus haut comme si je n'avais pas fait d'include ou d'édition de lien. Je pense que mon édition de lien est mauvaise (-lwtsapi32).

    Quellequn peut-il me dire comment faire cette édition de lien correctement sous l'IDE code block ?

    Merci d'avance pour vos réponses

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Déjà pour la compilation, as-tu inclus Wtsapi32.h ?
    Ou puisque tu utilises C::B, est-ce que Wtsapi32.h est fourni avec, et est-ce qu'il contient une déclaration de la fonction?

    Si ce n'est pas le cas, c'est que le SDK de C::B est trop vieux pour utiliser WTSSendMessage() en liaison statique. Dans ce cas, tu vas devoir jouer avec LoadLibrary() et GetProcAddress().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Lancer un programme Java comme service Windows
    Par ludo40190 dans le forum Général Java
    Réponses: 1
    Dernier message: 21/01/2012, 08h52
  2. Problème de timer dans un service window
    Par EmacLi dans le forum Services Windows
    Réponses: 5
    Dernier message: 10/01/2011, 11h43
  3. Problème dataAdapter ADO.NET et service windows
    Par NameX dans le forum VB.NET
    Réponses: 3
    Dernier message: 04/05/2010, 10h13
  4. Réponses: 9
    Dernier message: 25/04/2007, 15h08
  5. Transformer un programme java en service windows
    Par daninho dans le forum Général Java
    Réponses: 41
    Dernier message: 15/01/2006, 18h36

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