Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » C++ .exe als Dienst

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
20.06.2003, 09:21 Uhr
ai-tee



Jouw thx,

hat jemand von euch schonmal nen Dienst eingerichtet und weiss was man evtl. beachten muss? Ich bin mir nicht sicher ob ich vielleicht Eingabeparameter falsch gesetzt habe oder so ... ich bekomme beim Starten des Dienstes immer die Fehlermsg.:

1053 The service did not respond to the start or control request in a timely fashion. ERROR_SERVICE_REQUEST_TIMEOUT

Ich weiss aber nicht woran es liegt ...
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
20.06.2003, 09:47 Uhr
ai-tee



Also ... ich habe mich nochmal ein wenig schlau gemacht ... aber wirkliche Antworten bekam ich nicht ... gibt es denn hier keinen, der sich mit Diensten gut auskennt?

Meine Funktion (main) wird wie folgt aufgerufen ...

C++:
void main (int argc, char *argv[ ]) { ... }


Kann es vielleicht schon daran liegen? Dass quasi der Dienstmanager auf einen Rückgabewert wartet und daher den Start des Programs als gescheitert betrachtet?

Nochmal zum Programm:
Das Programm ist ein Win32 Konsolenprogramm. Die .exe wird einfach per Aufruf gestartet und das Programm beginnt das Verzeichnis nach einem bestimmten Dateityp zu durchsuchen ... je nach Erfolg oder Misserfolg werden noch bestimmte Routinen abgearbeitet ... und im Abschluss geht das Programm in den Wartemodus und wartet so lange, bis wieder Aktivität ist im Verzeichnis ...

Es sollte doch möglich sein, dies als Dienst einzurichten oder??
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
20.06.2003, 09:55 Uhr
~ao
Gast



Zitat:
ai-tee postete
Es sollte doch möglich sein, dies als Dienst einzurichten oder??

Hallo ai-tee,
ob und wie das geht, steht in der MSDN-Hilfe unter Platform SDK / Base Services / DLLs, Processes and Threads / Services.
Ist nicht ganz einfacher Stoff, aber so ist das nun mal, wenns ans Eingemachte von Windows geht. Da mußte wohl durch.
ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
23.06.2003, 10:56 Uhr
ai-tee



Ja thx, aber dort war ich ja selbst schon ... ich habe ja auch schon alles eingerichtet. Nach dem starten der .Exe wurde der Dienst erfolgreich installiert. Ich scheitere nur immer am Starten der Exe.
Liegt vielleicht auch daran, dass ich nicht umbedingt genau weiss, welche Optionen die richtigen sind ...

Ich habs sogar schon mit diesem Tool aus den Windows Toolkit probiert ... aber selbst damit lässt sich nach der Installation der Dienst nicht starten ... Error 1053 ...

Irgendjemand da, der schon Erfahrungen mit diesem Fehler gemacht hat?
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
23.06.2003, 11:14 Uhr
ao

(Operator)



Zitat:
ai-tee postete
Ja thx, aber dort war ich ja selbst schon ... ich habe ja auch schon alles eingerichtet. Nach dem starten der .Exe wurde der Dienst erfolgreich installiert. Ich scheitere nur immer am Starten der Exe.


Wie jetzt? Hast du die .exe gestartet oder scheiterst du dabei?

Zitat:

Irgendjemand da, der schon Erfahrungen mit diesem Fehler gemacht hat?

Sorry, leider nein.
Du hast diese ganzen Callback-Funktionen, von denen in der Hilfe die Rede ist (ServiceMain, Control-Handler) geschrieben, und die machen auch die vorgeschriebenen Aktionen (StartServiceCtrlDispatcher, RegisterServiceCtrlHandler und so)?

Setze Breakpoints auf die Funktionen, starte dein Programm im Debugger und arbeite dann die Callbacks schrittweise ab, bis du auf die Stelle stößt, die fehlschlägt.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
23.06.2003, 11:25 Uhr
ai-tee



Also in meiner Exe ist der Code zum ...

1. öffnen des OpenSCManagers
2. öffnen des Services
3. bei err von 2. (ERROR_SERVICE_DOES_NOT_EXIST) CreateService
4. StartService

Meine Probleme:

1. Das starten aus der Exe heraus funktioniert überhaupt nicht.
2. Wenn ich in den Dienstmanager gehe und dort den nun installierten Service aufrufe kommt nach ca. 70% die Fehlermeldung:

1053 The service did not respond to the start or control request in a timely fashion. ERROR_SERVICE_REQUEST_TIMEOUT

Kann es z.B. sein, dass meine .Exe etwas bestimmte zurückliefern muss?
Die Main rufe ich z.b. so auf:

bool main (int argc, char *argv[ ])

Und die Service Funktion rufe ich so auf (thisPath is das argv von der main):

void OperateService (CString thisPath)
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
23.06.2003, 11:26 Uhr
ai-tee



P.S. Debuggen macht nicht viel Sinn oder? Weil ich das starten ja aus dem Dienstmanager vornehme ... und es dort ebenfalls nicht klappt ...
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
23.06.2003, 14:02 Uhr
ao

(Operator)



Zitat:
ai-tee postete
1. Das starten aus der Exe heraus funktioniert überhaupt nicht.
2. Wenn ich in den Dienstmanager gehe und dort den nun installierten Service aufrufe kommt nach ca. 70% die Fehlermeldung:


Und in den anderen 30%? Funktioniert dann der Service oder kriegst du bloß keine Fehlermeldung?

Zitat:

bool main (int argc, char *argv[ ])


int main (int argc, char *argv[]) ist richtig. Aber ich glaube nicht, daß dich das weiterbringt.

Zitat:

Und die Service Funktion rufe ich so auf (thisPath is das argv von der main):
void OperateService (CString thisPath)

Also, ich hab das MSDN-Kapitel über Services weder vollständig gelesen noch das Ganze mal ausprobiert, aber ich glaube, du bist mit OpenSCManager und CreateService auf dem falschen Dampfer. Das ist das, was der Dienste-Manager tut, um ein fremdes Programm als Service anzumelden (vorausgesetzt, dieses ist korrekt als Service geschrieben, d.h. mit den o.g. Callbacks und so). Damit dein Programm sich selber anmelden kann, braucht es StartServiceCtrlDispatcher und das ganze andere Geraffel. Und dann macht auch das Debuggen Sinn.

Wie gesagt, ohne Gewähr. So interpretiere ich das, was ich hier mal eben überfliegen kann.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
23.06.2003, 15:14 Uhr
ai-tee



Achso ... oh ... öhm ... das muss ich jetzt erstmal nachlesen ... Callbacks (was auch immer das ist) habe ich natürlich keine ...

naja ich schau mal auf das was Du da schreibst ... bis später
--
Greetz, ai`tee
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
23.06.2003, 23:10 Uhr
Uwe
C/C++ Master
(Administrator)


Hallo,
mal ein Bsp. welches funktioniert, aber nichts macht :)
Install:

C++:
// Includes
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
// Defines
#define GENSRV_ServiceName    TEXT("TestService")
#define GENSRV_DisplayName    TEXT("Mein Test Service")
// Hauptprogramm
int main()
{
     // lokale Variablen vorbereiten
     SC_HANDLE    hSCManager = NULL;
     SC_HANDLE    hService = NULL;    
     TCHAR        szWinDir[MAX_PATH];
     TCHAR        szImagePath[MAX_PATH];  

     // SCM öffnen
     if((hSCManager = OpenSCManager(    NULL, NULL,
                           SC_MANAGER_CREATE_SERVICE))
                          == NULL)
     {
         // Fehler beim Öffnen
         _tprintf(TEXT("Fehler beim Oeffnen des SCM\n"));

         // Zurück
         return ;
     }

     // Windows Verzeichnis auslesen
     GetWindowsDirectory(szWinDir, MAX_PATH);

     // Namen der Service-Exe ermitteln
     _stprintf(    szImagePath, TEXT("%s\\system32\\%s.exe"),
               szWinDir, GENSRV_ServiceName);

     // Service hinzufügen
     if ((hService = CreateService(    hSCManager,
                          GENSRV_ServiceName,
                          GENSRV_DisplayName,
                         SERVICE_ALL_ACCESS,
                          SERVICE_WIN32_OWN_PROCESS,
                          SERVICE_DEMAND_START,
                          SERVICE_ERROR_IGNORE,
                           szImagePath, NULL, NULL,
                           NULL, NULL, NULL)) == NULL)
     {
         // Hinzügen fehlgeschlagen, Fehler melden
         _tprintf(TEXT("Hinzufuegen fehlgeschlagen\n"));

         // Zurück
         return ;
     }

     // Handle zum Service schließen
     CloseServiceHandle(hService);

     // Handle zum SCM schließen
     CloseServiceHandle(hSCManager);

     // Alles ok
     _tprintf(TEXT("%s erfolgreich installiert\n"), szImagePath);
        return 0;
}


Service:

C++:
// Includes

#include <windows.h>
#include <stdio.h>

// Defines

#define GENSRV_ServiceName      TEXT("TestService")
#define GENSRV_DisplayName      TEXT("Mein Test Service")

// Prototypen
bool        NotifySCM(    DWORD in_dwState,
                      DWORD in_dwWin32ExitCode,
                      DWORD in_dwProgress);
void        ServiceMain(DWORD in_dwArgc, LPTSTR *in_pszArgv);
void        ServiceHandler(DWORD in_dwControl);
WORD        MainServiceThread(LPDWORD in_ThreadParam);


// globale Variablen
HANDLE    hDoneEvent = NULL;
HANDLE    hThread = NULL;
DWORD    dwCurrentState;
SERVICE_STATUS_HANDLE    hService;

// Hauptprogramm main. Das Hauptprogramm des Dienstes könnte auch
// als WinMain erzeugt werden.
int main()
{  
     // service table entry Struktur definieren
     SERVICE_TABLE_ENTRY ServiceTable[] =    
          {
              {
                 GENSRV_ServiceName,
                 (LPSERVICE_MAIN_FUNCTION)ServiceMain
             },
              {
                 NULL,
                 NULL
             }  
         };  
    
     // Verbindung mit SCR aufbauen
     StartServiceCtrlDispatcher(ServiceTable);
        return 0;
}

// Initialisierung des Services

BOOL ServiceInitialization(DWORD in_dwArg, LPTSTR *in_pszArgv)
{  
     // Hier können Initialisierungen durchgeführt werden
     // ...

     // Alles OK
     return (true);
}

// Hauptfunktion des Services

VOID ServiceMain(DWORD in_dwArgc, LPTSTR *in_pszArgv)
{
     // lokale Variable vorbereiten
     DWORD   ThreadId;
    // Funktion zum Behandeln von Service Funktionalität registrieren
    if (!(hService = RegisterServiceCtrlHandler(    GENSRV_ServiceName,
                (LPHANDLER_FUNCTION)ServiceHandler)))
     {
         // Fehler, Abbruch
         return;
     }

     // Statusinformationen aktualisieren
     NotifySCM(SERVICE_START_PENDING, 0, 1);

     // kann der Service Initialisiert werden?
     if (!ServiceInitialization(in_dwArgc, in_pszArgv))
     {
         // Fehler, Abbruch
         return;
     }

     // Statusinformationen aktualisieren
     NotifySCM(SERVICE_START_PENDING, 0, 2);

     // Ereignis erzeugen
      if ((hDoneEvent=CreateEvent(NULL,FALSE,FALSE,NULL)) == 0)
     {
         // Fehler, Abbruch
         return;  
     }

     // Statusinformationen aktualisieren
     NotifySCM(SERVICE_START_PENDING, 0, 3);

     // Neuen Thread erzeugen
     if ((hThread = CreateThread(     0, 0,
                   (LPTHREAD_START_ROUTINE)MainServiceThread,
                  0, 0, &ThreadId)) == 0)
     {
         // Fehler! Ereignis Handle schließen
         CloseHandle(hDoneEvent);

         // zurück
         return;
     }

     // Statusinformationen aktualisieren
     NotifySCM(SERVICE_RUNNING, 0, 0);

     // Warten, bis der Service beendet wurde
     WaitForSingleObject(hDoneEvent, INFINITE);  

     // Threadhandle schließen
     CloseHandle(hThread);  

     // Thread beenden
     ExitThread(ThreadId);  

     // Ereignis-Handle schließen
     CloseHandle(hDoneEvent);  

     // Alles OK, zurück
     return 0;
}

  // Statusübertragung
  bool NotifySCM(     DWORD in_dwState, DWORD in_dwWin32ExitCode,

              DWORD in_dwProgress)
{
     // SERVICE_STATUS Struktur deklarieren
     SERVICE_STATUS ServiceStatus;  

     // Werte in Struktur eintragen
     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     ServiceStatus.dwCurrentState = dwCurrentState = in_dwState;
     ServiceStatus.dwControlsAccepted =     SERVICE_ACCEPT_STOP |
                          SERVICE_ACCEPT_PAUSE_CONTINUE  
                          | SERVICE_ACCEPT_SHUTDOWN;  
     ServiceStatus.dwWin32ExitCode = in_dwWin32ExitCode;  
     ServiceStatus.dwServiceSpecificExitCode = 0;  
     ServiceStatus.dwCheckPoint = in_dwProgress;  
     ServiceStatus.dwWaitHint = 3000;  

     // Status übermitteln
     return (SetServiceStatus(hService, &ServiceStatus));
}



// Thread-Hauptfunktion
    
WORD MainServiceThread(LPDWORD ThreadParam)
{
     // Wiederholen, solange der Service läuft
     while (TRUE)
     {
         // Eine Minute warten
         Sleep(60000);

         // Datei öffnen
         FILE *pFile = fopen("c:\\testfile.zip","rb");

         // Konnte die Datei geöffnet werden?
         if (pFile != NULL)
         {
             // Ausgabedatei vorbereiten
             FILE *pOutputFile = fopen("c:\\backup.zip","w+b");

             // Buffer anlegen
             byte Buffer[1024];

             // Anzahl der bislang eingelesenen Bytes speichern
             int nBytesRead=-1;

             // Gesamtes File auslesen
             while (!feof(pFile))
             {
                 // Jeweils 1024 Bytes einlesen
                 int nBytesRead=fread(Buffer, 1, 1024,
                               pFile);

                 // Hat alles geklappt?
                 if ((nBytesRead!=0) && (!ferror(pFile)))
                 {
                     // Daten in Ausgabedatei speichern
                     fwrite(Buffer, 1, nBytesRead,
                              pOutputFile);
                     if (ferror(pOutputFile))
                     {
                         // Signal ausgeben
                         MessageBeep(MB_ICONASTERISK);

                         // Kopiervorgang abbrechen
                         break;
                     }
                 }
                 else
                 {
                     // Signal ausgeben
                     MessageBeep(MB_ICONASTERISK);

                     // Kopiervorgang abbrechen
                     break;
                 }
             }
            
         }
         else
         {
             // Signal ausgeben
             MessageBeep(MB_ICONASTERISK);
         }
     }
}


// Terminierung des Services

void ServiceTermination()
{  
     // Hier können abschließende Aufräumarbeiten durchgeführt werden
}


// Nachrichtenbehandlung des Services

void ServiceHandler(DWORD in_dwControl)
{  
     switch(in_dwControl)
     {
         case SERVICE_CONTROL_STOP:  
         {
             // Statusinformationen aktualisieren      
             NotifySCM(SERVICE_STOP_PENDING, 0, 1);  

             // Ereignis signalisieren
             SetEvent(hDoneEvent);        
            
             // Statusinformationen aktualisieren
             NotifySCM(SERVICE_STOPPED, 0, 0);        
             break;
         }
         case SERVICE_CONTROL_PAUSE:  
         {
            // Statusinformationen aktualisieren
            NotifySCM(SERVICE_PAUSE_PENDING, 0, 1);    

            // Thread pausieren
            SuspendThread(hThread);
            
            // Statusinformationen aktualisieren
            NotifySCM(SERVICE_PAUSED, 0, 0);        
            break;      
         }
         case SERVICE_CONTROL_CONTINUE:
         {
            // Statusinformationen aktualisieren
            NotifySCM(SERVICE_CONTINUE_PENDING, 0, 1);  

            // Thread wieder starten
            ResumeThread(hThread);      
            
            // Statusinformationen aktualisieren
            NotifySCM(SERVICE_RUNNING, 0, 0);        
            break;    
         }
         case SERVICE_CONTROL_INTERROGATE:    
         {
            // Statusinformationen aktualisieren
            NotifySCM(dwCurrentState, 0, 0);        
            break;      
         }
         case SERVICE_CONTROL_SHUTDOWN:  
         {
             // Service beenden      
             ServiceTermination();        
             break;  
         }
     }
}


De-Install:

C++:
// Includes

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

// Defines

#define GENSRV_ServiceName      TEXT("TestService")
#define GENSRV_DisplayName      TEXT("Mein Test Service")

// Hauptprogramm

int main()
{    
     // lokale Variablen vorbereiten
     SC_HANDLE    hSCManager = NULL;
     SC_HANDLE    hService = NULL;    

     // SCM öffnen
     if((hSCManager = OpenSCManager(NULL, NULL,
                      SC_MANAGER_CREATE_SERVICE)) == NULL)
     {
         // Fehler beim Öffnen
         _tprintf(TEXT("Fehler beim Oeffnen des SCM\n"));

         // Zurück
         return;
     }

     if (!(hService = OpenService(hSCManager, GENSRV_ServiceName,
                      STANDARD_RIGHTS_REQUIRED)))
     {
         // Fehler melden
         _tprintf(TEXT("Oeffnen des Services fehlgeschlagen!"));

         // zurück
         return;
     }

     if (!DeleteService(hService))
     {
         // Fehler melden
         _tprintf(TEXT("Fehler beim Deinstallieren"));

         // return
         return;
     }

     // Handle zum Service schließen
     CloseServiceHandle(hService);    

     // Handle zum SCM schließen
     CloseServiceHandle(hSCManager);    

     // Alles ok
     _tprintf(TEXT("Service erfolgreich deinstalliert\n"));
           return 0;
}


--
"Es ist schwierig, ein Programm wirklich idiotensicher zu machen, weil Idioten so genial sind."

Bis dann...
Uwe

Dieser Post wurde am 24.06.2003 um 07:33 Uhr von Uwe editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: