Avatar billede apromis Praktikant
21. november 2004 - 21:57 Der er 23 kommentarer og
1 løsning

Installere som service ?

Hejza.

Jeg har lavet et program som kopirer nogen filer på maskinen, som meget praktisk.
Og dette program skal på et tidspunkt udgives til fri download.

Men jeg vil gerne i installations filen, at den laver kopi.exe til en service.
Hvordan gøres dette ?

På forhånd tak.
Avatar billede jpk Nybegynder
22. november 2004 - 08:59 #1
Jeg går ud fra det er en Windows Service vi snakker om?

I så fald er der flere muligheder, alt efter lyst/smag...

1) Du kan bruge programmet SrvAny.exe fra Windows Resource Kit til at køre et program som en service.

2) Du kan implementere selve service interface-funktionerne i dit program v.h.a. OpenSCManager, CreateService, OpenService, StartService etc.
Avatar billede jpk Nybegynder
22. november 2004 - 09:10 #2
Hvis du arbejder i .NET, kan du bruge ServiceBase klassen...
Avatar billede apromis Praktikant
22. november 2004 - 12:25 #3
Ja det er en Windows service jeg skal have gang i.
Og det er ikke .NET jeg arbejder i.

Men der skal ikke installeres nogen andre programmer end mit.


Men kan du uddøbe?
eller vil du komme med et ekspempel, så ville jeg være glad !

På forhånd tak.
Avatar billede jpk Nybegynder
22. november 2004 - 13:43 #4
Du kan downloade et kodeeksempel på:
http://www.programmersheaven.com/zone3/cat33/28440.htm
Avatar billede apromis Praktikant
22. november 2004 - 19:12 #5
Hejza igen.

Jeg har kigget lidt på den kode.. Men kan ikke finde, det som jeg 100% skal bruge.

Kan godt se at programmet han har lavet virker, men er ikke sikker på det jeg laver.

Tror det af noget af det her, men kan ikke finde den helt rigtige kode:
// cService.cpp: implementation of the cService class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Service.h"
#include "cService.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

extern void Output(CString Out);

// global instance of Service
cService g_Service;


cService::cService()
{

}

cService::~cService()
{

}

// return Errorcode or 0
// Install the service when user clicks the Create button
DWORD cService::Create()
{
    SC_HANDLE hdlSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);

    CString Calling = ::GetCommandLine();
    Calling += " /Service";

    if (hdlSCM == NULL) return ::GetLastError();

    SC_HANDLE hdlServ = CreateService(
        hdlSCM,                    // SCManager database
        ServiceName,              // name of service
        ServiceDisplayName,        // service name to display
        STANDARD_RIGHTS_REQUIRED,  // desired access
        SERVICE_WIN32_OWN_PROCESS, // service type
        SERVICE_DEMAND_START,      // start type
        SERVICE_ERROR_NORMAL,      // error control type
        Calling,                  // service's binary Path name
        NULL,                      // no load ordering group
        NULL,                      // no tag identifier
        NULL,                      // no dependencies
        NULL,                      // LocalSystem account
        NULL);                    // no password

    DWORD Ret = 0;
    if (!hdlServ) Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}


// return Errorcode or 0
// Uninstall the service when user clicks the Delete button
DWORD cService::Delete()
{
    SC_HANDLE hdlSCM = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);

    if (!hdlSCM) return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, DELETE);
   
    DWORD Ret = 0;
    if (!DeleteService(hdlServ)) Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}

// return Errorcode or 0
// Start the service when user clicks the Start button
DWORD cService::Start()
{
    SC_HANDLE hdlSCM = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);

    if (!hdlSCM) return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_START);

    DWORD Ret = 0;
    if (!StartService(hdlServ, 0, NULL)) Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}


// return Errorcode or 0
// Stop the service when user clicks the Stop button
DWORD cService::Stop()
{
    SC_HANDLE hdlSCM = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);

    if (!hdlSCM) return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_STOP);

    SERVICE_STATUS ServStat;
    DWORD Ret = 0;
    if (!ControlService(hdlServ, SERVICE_CONTROL_STOP, &ServStat)) Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}


// this function must be in global namespace (Windows API callback)
void ApiServiceMainStarter(DWORD argc, LPTSTR *argv);

void ApiServiceMainStarter(DWORD argc, LPTSTR *argv)
{
    g_Service.MainStart(argc, argv);
}

// this function must be in global namespace (Windows API callback)
void ApiServiceControlHandler(DWORD Opcode);

void ApiServiceControlHandler(DWORD Opcode)
{
    g_Service.ControlHandler(Opcode);
}

// Service Main Function called by Windows
void cService::MainStart(DWORD argc, LPTSTR *argv)
{
    CString Out = *argv;
    Output("Service Main -- Start with Arguments: \"" + Out + "\"");

    hdlStat = ::RegisterServiceCtrlHandler(ServiceName, (LPHANDLER_FUNCTION) ApiServiceControlHandler);
    if (!hdlStat)
    {
        int Err = ::GetLastError();
        Out.Format("Service Main -- RegisterServiceHandler Error : %d\n", Err);
        Output(Out);
        return;
    }
    else Output("Service Main -- RegisterServiceHandler");

    hTimer = ::CreateWaitableTimer(NULL, FALSE, "DemoService-Timer");
   
    ControlHandler (0); // Set status Running
   
    EndlessLoop(); // Do the service work (write to logfile every 5 seconds)
}


// Start the service (in the Exe which is running as Service!!)
void cService::Dispatch()
{
    SERVICE_TABLE_ENTRY DispTbl[] =
    {
        { ServiceName, (LPSERVICE_MAIN_FUNCTION) ApiServiceMainStarter},
        { NULL , NULL}
    };

    Output("Dispatch -- Before calling StartServiceCtrlDispatcher\n");
   
    if (!::StartServiceCtrlDispatcher(DispTbl)) // does not return until service stopped
    {
        int Err = ::GetLastError();
        CString Out;
        Out.Format("Dispatch -- StartServiceCtrlDispatcher Error : %d\n", Err);
        Output(Out);
    }
    else Output("Dispatch -- Returning from StartServiceCtrlDispatcher\n");
}


// Control Handler handles Start / Stop events
void cService::ControlHandler(DWORD Opcode)
{
    SERVICE_STATUS  strctStat;
    strctStat.dwServiceType        = SERVICE_WIN32;
    strctStat.dwControlsAccepted  = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    strctStat.dwWin32ExitCode      = NO_ERROR;
    strctStat.dwServiceSpecificExitCode = 0; // returned Status code
    strctStat.dwCheckPoint        = 0;      // returned Error code
    strctStat.dwWaitHint          = 0;

    CString Command, Status;
    if (Opcode == SERVICE_CONTROL_STOP)
    {
        Command = "CONTROL_STOP";
        strctStat.dwCurrentState = SERVICE_STOPPED;
        Status  = "SERVICE_STOPPED";       
    }
    else if (Opcode == SERVICE_CONTROL_SHUTDOWN)
    {
        Command = "CONTROL_SHUTDOWN";
        strctStat.dwCurrentState = SERVICE_STOPPED;
        Status  = "SERVICE_STOPPED";       
    }
    else if (Opcode == SERVICE_CONTROL_INTERROGATE)
    {
        Command = "CONTROL_INTERROGATE";
        strctStat.dwCurrentState = SERVICE_RUNNING;
        Status  = "SERVICE_RUNNING";       
    }
    else
    {
        Command.Format("Command Opcode Nr. %d ", Opcode);
        strctStat.dwCurrentState = SERVICE_RUNNING;    
        Status  = "SERVICE_RUNNING";
    }


    if (Opcode != 0) Output("Control Handler -- received Command "+Command);

    if (!SetServiceStatus (hdlStat, &strctStat))
    {
        int Err = ::GetLastError();
        CString Out;
        Out.Format("Control Handler -- Set Status Error : %d", Err);
        Output(Out);
        return;
    }
    else Output("Control Handler -- SetStatus "+Status);
}


// writing the current time every 5 Seconds to the LOG file    to demonstrate that service ir running
void cService::EndlessLoop()
{
    Output("EndlessLoop Start\n");

    SYSTEMTIME Clock;
    CString Min, Sec, Out;
   
    // This endlessloop is killed by Windows when the service is stopped or shutdown
    while (1)
    {
        if (hTimer != 0)
        {
            LARGE_INTEGER Elapse;
            Elapse.QuadPart = -50000000; // 5 Seconds in 100 Nanoseconds resolution (negative=relative)
            BOOL Res = ::SetWaitableTimer(hTimer, &Elapse, 0, NULL, NULL, TRUE);

            if (Res)
            {
                DWORD Event = WaitForSingleObject(hTimer, 30000); // 30 seconds timeout
                // Event = (258=WAIT_TIMEOUT) (128=WAIT_ABANDONED) (0=WAIT_OBJECT_0) (0xFFFFFFFF=WAIT_FAILED)
            }
        }
       
        ::GetLocalTime(&Clock);
        Out.Format("Timer %02d:%02d:%02d:%03d", Clock.wHour, Clock.wMinute, Clock.wSecond, Clock.wMilliseconds);
        Output(Out);
    };
}

Vil du ikke hjælpe mig videre ?
Avatar billede jpk Nybegynder
23. november 2004 - 15:42 #6
Det er svært at hjælpe dig når du ikke skriver hvad du vil have hjælp til?
Hvis du vil have flere eksempler/forklaringer på en Windows Service' funktioner, kan du fx kigge i afsnittet her:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/using_services.asp
Avatar billede apromis Praktikant
23. november 2004 - 15:58 #7
Hej vil gerne have hjælp til at få en program til at være en service..

Alts create den.
Forstår du mig, eller er jeg for udtydelig ?
Avatar billede jpk Nybegynder
24. november 2004 - 08:31 #8
Jeg forstår fint at du vil have dit program til at være en service, men hvilken del af programmeringen er det du har problemer med?
Jeg har desværre ikke tid til at lave et helt program for dig, men du kan se fremgangsmetoden i eksemplerne fra "Using services"-afsnittet i MSDN (linket).
Avatar billede apromis Praktikant
24. november 2004 - 09:36 #9
Jeg tror jeg bliver nød til at lukke så, og oprette med flere points om et dage.

Jeg kan ikke finde ud af det eksempel... :(
Avatar billede jpk Nybegynder
24. november 2004 - 09:54 #10
Jeg skal prøve at se, om jeg kan afsætte lidt tid til eksempel/forklaring senere idag...
Avatar billede apromis Praktikant
24. november 2004 - 12:09 #11
okay det lyder fint. Takker
Avatar billede jpk Nybegynder
24. november 2004 - 15:56 #12
Jeg har lavet et lille eksempel (ServiceTest), der virker således:

1) Installér servicen:
ServiceTest.exe /install

Du kan så finde den under services i kontrolpanelet

Der kan du så starte/stoppe den.
Den skriver bare tiden i en fil (C:\Service.txt) hvert 5. sekund


2) Afinstallér servicen:
ServiceTest.exe /uninstall

Den fjernes fra services...



Jeg har kodet det i MS VC++ .NET 7.1, men uden .NET(managed) og uden MFC.
Hvilket udviklingsmiljø bruger du?
Avatar billede apromis Praktikant
24. november 2004 - 22:13 #13
jeg bruger Bloodshed Dev-C++ .. Det er det du mener ikke ?
Avatar billede jpk Nybegynder
25. november 2004 - 08:55 #14
Jo, jeg har lavet en lille console-app, der ser sådan ud:


// ServiceTest.cpp : Defines the entry point for the console application.
//

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include "cService.h"

using namespace std;

extern cService g_Service;

int _tmain(int argc, _TCHAR* argv[])
{
    int nResult = 0;

    // Check if there is a second argument (first one is .exe filename)
    if(argc >= 2)
    {
        string arg(argv[1]);
        if(arg == "/install") // If the argument is "/install", create the service
        {
            cout << "Installing service" << endl;
            string strParameters = " /start";
            // Collect any additional parameters
            for(int i=2; i<argc; ++i)
                strParameters += string(" ") + argv[i];
            nResult = g_Service.Create(argv[0] + strParameters);
        }
        else if(arg == "/uninstall") // If the argument is "/uninstall", delete the service
        {
            cout << "Uninstalling service" << endl;
            nResult = g_Service.Delete();
        }
        else if(arg == "/start") // If the argument is "/start", start the service
        {
            g_Service.Dispatch();
        }
    }

    if(nResult == 0) // Check for error
    {
        cout << "Done..." << endl;
    }
    else
    {
        // Get result text
        LPTSTR lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, nResult, 0, (LPTSTR)&lpMsgBuf, 0, NULL);

        // Show result
        cout << lpMsgBuf << endl;

        // Free the buffer.
        LocalFree(lpMsgBuf);
    }

    return nResult;
}




Den bruger klassen cService, som du kan se her:

// cService.h: interface for the cService class.
//
//////////////////////////////////////////////////////////////////////

#ifndef SERVICE_H
#define SERVICE_H

#include <windows.h>
#include "winsvc.h"
#include <string>
using namespace std;

const LPSTR ServiceName        = "DemoService";
const LPSTR ServiceDisplayName = "A little Demo Service";

class cService 
{
public:
    cService();
    virtual ~cService();

    DWORD Create(string strCmd);
    DWORD Delete();
    DWORD Start();
    DWORD Stop();

    void Dispatch();
    void MainStart(DWORD argc, LPTSTR *argv);
    void ControlHandler(DWORD Opcode);

private:
    SERVICE_STATUS_HANDLE  hdlStat;
    HANDLE hTimer;
};

#endif // SERVICE_H







// cService.cpp: implementation of the cService class.
//
//////////////////////////////////////////////////////////////////////

#include "cService.h"
#include <fstream>

// global instance of Service
cService g_Service;

// this function must be in global namespace (Windows API callback)
void ApiServiceMainStarter(DWORD argc, LPTSTR *argv)
{
    g_Service.MainStart(argc, argv);
}

// this function must be in global namespace (Windows API callback)
void ApiServiceControlHandler(DWORD Opcode)
{
    g_Service.ControlHandler(Opcode);
}


cService::cService()
{
}

cService::~cService()
{
}

DWORD cService::Create(string strCmd)
{
    SC_HANDLE hdlSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);

    if(hdlSCM == 0)
        return ::GetLastError();

    SC_HANDLE hdlServ = CreateService(
        hdlSCM,                    // SCManager database
        ServiceName,              // name of service
        ServiceDisplayName,        // service name to display
        STANDARD_RIGHTS_REQUIRED,  // desired access
        SERVICE_WIN32_OWN_PROCESS, // service type
        SERVICE_DEMAND_START,      // start type
        SERVICE_ERROR_NORMAL,      // error control type
        strCmd.c_str(),          // service's binary Path name
        0,                        // no load ordering group
        0,                        // no tag identifier
        0,                        // no dependencies
        0,                        // LocalSystem account
        0);                        // no password

    DWORD Ret = 0;
    if(!hdlServ)
        Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}

DWORD cService::Delete()
{
    SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);

    if(!hdlSCM)
        return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, DELETE);

    DWORD Ret = 0;
    if(!DeleteService(hdlServ))
        Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}

DWORD cService::Start()
{
    SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);

    if(!hdlSCM)
        return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_START);

    DWORD Ret = 0;
    if(!StartService(hdlServ, 0, 0))
        Ret = ::GetLastError();

    CloseServiceHandle(hdlServ);
    return Ret;
}

DWORD cService::Stop()
{
    SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);

    if(!hdlSCM)
        return ::GetLastError();

    SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_STOP);

    SERVICE_STATUS ServStat;
    DWORD Ret = 0;
    if(!ControlService(hdlServ, SERVICE_CONTROL_STOP, &ServStat))
        Ret = ::GetLastError();
    CloseServiceHandle(hdlServ);
    return Ret;
}

// Service Main Function called by Windows
void cService::MainStart(DWORD argc, LPTSTR *argv)
{
    hdlStat = ::RegisterServiceCtrlHandler(ServiceName, (LPHANDLER_FUNCTION)ApiServiceControlHandler);
    if(!hdlStat)
    {
        int Err = ::GetLastError();
        return;
    }

    // Set status Running
    ControlHandler(0);

    // Do the service work
    while(true)
    {
        SYSTEMTIME Clock;
        ::GetLocalTime(&Clock);

        ofstream file;
        file.open("c:\\Service.txt", ios_base::out|ios_base::app);
        file << Clock.wHour << ":" << Clock.wMinute << ":" << Clock.wSecond << endl;
        file.close();
        Sleep(5000);
    }
}

// Start the service (in the Exe which is running as Service!!)
void cService::Dispatch()
{
    SERVICE_TABLE_ENTRY DispTbl[] =
    {
        { ServiceName, (LPSERVICE_MAIN_FUNCTION)ApiServiceMainStarter},
        { 0, 0}
    };

    if(!::StartServiceCtrlDispatcher(DispTbl)) // does not return until service stopped
    {
        int Err = ::GetLastError();
    }
}

// Control Handler handles Start / Stop events
void cService::ControlHandler(DWORD Opcode)
{
    SERVICE_STATUS  strctStat;
    strctStat.dwServiceType        = SERVICE_WIN32;
    strctStat.dwControlsAccepted  = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    strctStat.dwWin32ExitCode      = NO_ERROR;
    strctStat.dwServiceSpecificExitCode = 0; // returned Status code
    strctStat.dwCheckPoint        = 0;      // returned Error code
    strctStat.dwWaitHint          = 0;

    if(Opcode == SERVICE_CONTROL_STOP)
        strctStat.dwCurrentState = SERVICE_STOPPED;
    else if(Opcode == SERVICE_CONTROL_SHUTDOWN)
        strctStat.dwCurrentState = SERVICE_STOPPED;
    else if(Opcode == SERVICE_CONTROL_INTERROGATE)
        strctStat.dwCurrentState = SERVICE_RUNNING;
    else
        strctStat.dwCurrentState = SERVICE_RUNNING;    

    SetServiceStatus(hdlStat, &strctStat);
}
Avatar billede apromis Praktikant
25. november 2004 - 19:09 #15
Undskyld men forstår ikke helt..
Jeg har tre filer ikke ? hvad for et skal mit program tilføjes ?

Håber du lig vil hjælpe mig færdig.. Så vil jeg gerne give flere points.
Avatar billede jpk Nybegynder
26. november 2004 - 08:56 #16
Du har filerne cService.h og cService.cpp, de skal tilføjes til dit projekt.
Den første fil, ServiceTest.cpp, er et simpelt eksempel på hvordan du bruger cService-klassen.
Avatar billede apromis Praktikant
26. november 2004 - 09:44 #17
For en masse fejl, med linkin :( ...
Gør jeg noget forkert mon ?

Jeg har følgene filer i min mappe:
cService.h
cService.cpp
main.cpp (ServiceTest.cpp)


Hvad der galt her ?
Kan du evt lægge dem i en zip som virker ?


Har sat det op til 100 points
Avatar billede jpk Nybegynder
26. november 2004 - 09:55 #18
Du bliver jo nødt til at skrive hvilke fejl du får, ellers kan jeg ikke hjælpe!

Jeg bruger et andet udviklingsmiljø, derfor hjælper det ikke noget at sende dig mit projekt...
Avatar billede apromis Praktikant
26. november 2004 - 09:59 #19
Altså jeg tror det går galt når jeg prøver at få de filer tilføjet i filen.

  [Linker error] undefined reference to `g_Service'
  [Linker error] undefined reference to `cService::Create(std::string)'
  [Linker error] undefined reference to `g_Service'
  [Linker error] undefined reference to `cService::Delete()'
  [Linker error] undefined reference to `g_Service'
  [Linker error] undefined reference to `cService::Dispatch()'
C:\Dev-Cpp\service\Makefile.win [Build Error]  [servicetester.exe] Error 1

Disse fejl for jeg..
Avatar billede jpk Nybegynder
26. november 2004 - 10:07 #20
Jeg kender ikke meget til Dev-Cpp og derfor heller ikke til dets måde at rapportere fejl på. Det ligner dog at filerne ikke rigtig er tilføjet projektet..?
Avatar billede apromis Praktikant
26. november 2004 - 10:16 #21
hmm det kan godt være du har ret.. Men syntes ikke jeg kan tilføje dem..

Ved du evt hvordan.
Avatar billede jpk Nybegynder
26. november 2004 - 13:20 #22
Næ, jeg kender som sagt ikke til Dev-Cpp og jeg synes heller ikke umiddelbart der er nogle svar på Eksperten der kan bruges...
Avatar billede apromis Praktikant
27. november 2004 - 17:39 #23
okay.. opretter et nyt spm, med det problem...

Hvis du svarer er der points...
Avatar billede jpk Nybegynder
28. november 2004 - 10:57 #24
okay, tak...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester