Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Windows Service install\unistall tool (console)


Автор: sOckets 23.9.2006, 22:43
Привет , вот я выкладываю код инсталлера\унинсталлера сервисов для Windows NT\XP
Просьба заценить чистоту и читабельность кода.
Ну и исправить ошибки типа "Как не стоит писать код" smile
Код

#include <windows.h>
#include <iostream.h>
#define SIZE 500
//----------------------------------------------------- ПЕРЕМЕННЫЕ
    int                i;                                    // нужный INT в работе for\if 
    SC_HANDLE        MSCH;                                // Хэндлы service control 
    SC_HANDLE        MYSH;                                // Хэндл нашего сервиса
    char            MYS_SERVICE_NAME[SIZE];                // Название сервиса
    char            MYS_SERVICE_NAME_FOR_USER[SIZE];    // Название сервиса как будет видеть юзер
    char            PATH_TO_EXE[SIZE];                    // Путь до исполняемого файла запускаемого как сервис
//------------------------------------------------------

void HELP_BANNER_FOR_USER()
{    // Выводит баннер юзеру
    cout << " ########################-> ABOUT <-######################\n";
    cout << " # SerIns - Service Installer for :\n";
    cout << " #    1) Windows \"Longhorn\".\n";
    cout << " #    2) Windows XP.\n";
    cout << " #    3) Windows 2000 Professional.\n";
    cout << " #    4) Windows NT Workstation.\n";
    cout << " #########################################################\n\n";

    cout << " ########################->  USE  <-######################\n";
    cout << " # For install service use flag '-i'\n";
    cout << " # servins.exe  -i \"file.exe\" \"service name\" \"service display name\"\n #\n";
    cout << " # For uninstall service use flag '-u'\n";
    cout << " # servins.exe  -u \"service name\" \n #\n";    
    cout << " # Example:\n #\n";
    cout << " #    servins.exe \"C:\\my folder\\file.exe\" \"MyService\" \"My Proxy Server\"\n";
    cout << " #########################################################\n";    
}

void COPY_CHAR(char* FROM,char* TO)
{    // копирование с одного массива в другой
    for (i = 0;i <= strlen(FROM)-1; i++)
    {
        TO[i] = FROM[i];
    }
}

void GET_PROGRAM_ARGV_I(char* TO_EXE,char* SV_NAME,char* DS_NAME)
{    // Получаем аргументы от юзера для установки
    if (strlen(TO_EXE) < SIZE && strlen(SV_NAME) < SIZE  && strlen(DS_NAME) < SIZE)
    {
        // Получаем путь до файла
        COPY_CHAR(TO_EXE,PATH_TO_EXE);

        // Получаем имя сервиса
        COPY_CHAR(SV_NAME,MYS_SERVICE_NAME);

        // Заменяем пробелы на "_"
        for (i = 0;i <= strlen(MYS_SERVICE_NAME)-1; i++)
        {
            if (MYS_SERVICE_NAME[i]==' ') MYS_SERVICE_NAME[i] = '_';
        }

        // Получаем название сервиса
        COPY_CHAR(DS_NAME,MYS_SERVICE_NAME_FOR_USER);
    }
}

void GET_PROGRAM_ARGV_U(char* SV_NAME)
{    // Получаем аргументы от юзера для удаления сервиса
    if (strlen(SV_NAME) < 500)
    {
        for (i = 0;i <= strlen(SV_NAME)-1; i++)
        {
            MYS_SERVICE_NAME[i] = SV_NAME[i];
        }
    }
}

int main(int argc,char* argv[])
{
    //----------------------------------------------------- START
    // Проверяем ввёл ли пользователь нормальное количество параметров
    if (argc < 2)
    {
        HELP_BANNER_FOR_USER();
        return 1;
    }
    
    // Проверяем ключ
    i = strcmp(argv[1],"-i");
    if (i == 0)
    {
        // Тут юзер выбрал создать сервис , поэтому мы должны проверить сколько он ввёл параметров , если он ввёл мало
        // то мы ему сообщим об этом
        // Проверяем ввёл ли пользователь нормальное количество параметров
        if (argc != 5)
        {
            HELP_BANNER_FOR_USER();
            return 1;
        }
        
        // Получаем параментры с командной строки и передаём их функции
        GET_PROGRAM_ARGV_I(argv[2],argv[3],argv[4]);
        
        // Стучимся в менеджер сервисов
        MSCH = OpenSCManager(NULL,NULL,0x0002);
        if (MSCH == NULL)
        {
            cout << "Error service name";
            return 1;
        }

        // Создаём сервис
        MYSH = CreateService(MSCH,MYS_SERVICE_NAME,MYS_SERVICE_NAME_FOR_USER,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,PATH_TO_EXE,NULL,NULL,NULL,NULL,NULL);
        if (MYSH == NULL) 
        {
            cout << "Error Create of service";
            return FALSE;
        } else {
            CloseServiceHandle(MYSH); 
            cout << "Service : " << MYS_SERVICE_NAME << " installed";
            return TRUE;
        }
        return 0;
    }
    i = strcmp(argv[1],"-u");
    if (i == 0)
    {
        if (argc != 3)
        {
            cout << "<" << argv[0] << ">" << " -u \"ServiceName\"";
            return 1;
        }
        GET_PROGRAM_ARGV_U(argv[2]);
        // Стучимся в менеджер сервисов
        MSCH = OpenSCManager(NULL,NULL,0xF003F);
        if (MSCH == NULL)
        {
            cout << "Error service name";
            return 1;
        }
        // Открываем сервис
        MYSH = OpenService(MSCH,MYS_SERVICE_NAME,0xF003F);
        if (MYSH == NULL)
        {
            cout << "Error open service";
            return 1;
        }
        i = DeleteService(MYSH);
        if (i != 0)
        {
            cout << "Service removed";
            return 0;
        }
        return 0;
    }
//----------------------------------------------------- END
    return 0;
}


Скоро напишу не консольную версию

Автор: registered 23.9.2006, 23:44
а что Вы вообще хотите - указать ошибки - или показать рабочий код ?

Автор: sOckets 23.9.2006, 23:47
Код рабочий , просто я хочю чтоб "гуру" указали мне на ошибки типо "Как не стоит писать код" =\

Автор: registered 24.9.2006, 00:04
Цитата(sOckets @  23.9.2006,  23:47 Найти цитируемый пост)
Код рабочий , просто я хочю чтоб "гуру" указали мне на ошибки типо "Как не стоит писать код" =\ 


я конечно не гуру smile, но на первый взгляд

1. 
Цитата(sOckets @  23.9.2006,  22:43 Найти цитируемый пост)
#define SIZE 500

Код

const SIZE = 500;


2. 
Цитата(sOckets @  23.9.2006,  22:43 Найти цитируемый пост)
//----------------------------------------------------- ПЕРЕМЕННЫЕ
    int                i;                                    // нужный INT в работе for\if 
    SC_HANDLE        MSCH;                                // Хэндлы service control 
    SC_HANDLE        MYSH;                                // Хэндл нашего сервиса
    char            MYS_SERVICE_NAME[SIZE];                // Название сервиса
    char            MYS_SERVICE_NAME_FOR_USER[SIZE];    // Название сервиса как будет видеть юзер
    char            PATH_TO_EXE[SIZE];                    // Путь до исполняемого файла запускаемого как сервис
//------------------------------------------------------


глобально не есть хорошо

3. 
Цитата(sOckets @  23.9.2006,  22:43 Найти цитируемый пост)
void COPY_CHAR(char* FROM,char* TO)
{    // копирование с одного массива в другой
    for (i = 0;i <= strlen(FROM)-1; i++)
    {
        TO[i] = FROM[i];
    }
}


для этого есть strcpy, strcpy_s - но в идеале нужно конечно std::string

4. используй smart-поинтеры


ну.... далее нет смысла - лучше задавай вопросы smile

Автор: sOckets 24.9.2006, 00:10
Цитата
для этого есть strcpy, strcpy_s - но в идеале нужно конечно std::string


А чем эта функция не потходит ? на счёт strcpy я в курсе smile просто 

Цитата
const SIZE = 500;


Почему ?

На будущее , пожалуйста обьясняйте почему вы так думаете.

Автор: vinter 24.9.2006, 09:10
Цитата

const SIZE = 500;    

Почему ?

потому что дефайны считаются плохим тоном..

Автор: Kuvaldis 24.9.2006, 10:25
Цитата

const SIZE = 500;    

Почему ?

Плохо тем, что, например, в #define A B, идет механическая (!) замена A на В а тексте програмы, без проверки на соотвествие типов. => возможны неприятные ошибки

Автор: bel_nikita 24.9.2006, 10:38
Цитата(vinter @ 24.9.2006,  08:10)
потому что дефайны считаются плохим тоном..

хто сказал?

Добавлено @ 10:41 
Цитата(registered @ 23.9.2006,  23:04)
4. используй smart-поинтеры

зачем тут смарт-поинтеры применять?

Автор: sOckets 24.9.2006, 10:46
Цитата
4. используй smart-поинтеры


Понятие я имею что такое smart-поинтеры smile

Автор: vinter 24.9.2006, 10:53
в книгах пишут " по возможности избегайте, define'ов "..

Автор: registered 24.9.2006, 10:56
вообще тут напрашивается класс smile

например что-то вроде 
Код

/*-----------------------------------------------------------------------*/
class SCHandle {
private :
    boost::shared_ptr<void> m_handle;

public :
    SCHandle (SC_HANDLE handle = NULL)
        : m_handle (handle, CloseServiceHandle) {;}
    ~SCHandle() {;}

    operator SC_HANDLE () const { return (SC_HANDLE)m_handle.get(); }
};
/*-----------------------------------------------------------------------*/
class ServiceManager  {
private :
    std::string m_name;
    SCHandle m_hService;
    SERVICE_STATUS m_status;

    unsigned GetStatus (void) const;
    unsigned GetUserStatus (void) const;

public :
    explicit ServiceManager (const std::string& serviceName);
    ~ServiceManager() {;}

    bool IsExist    (void) const;
    bool IsRunning  (void) const;
    bool IsStopped  (void) const;
    bool IsPaused   (void) const;

    bool Start      (void) const;
    bool Stop       (void);
    bool Pause      (void);
    bool Continue   (void);

    bool Install    (const std::string& displayName, unsigned startType,
                     const char* services = NULL, const char* group = NULL);
    bool Uninstall  (void);

};


Код

ServiceManager::ServiceManager (const std::string& serviceName)
    : m_name (serviceName), m_hService (NULL)
{
    ZeroMemory (&m_status, sizeof (SERVICE_STATUS));

    SCHandle hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
    if (!hSCManager)
    {
        DebugMessage ("ServiceManager::ServiceManager (OpenSCManager)");
        throw std::exception("Ошибка открытия SCManager");
    }

    m_hService = OpenService (hSCManager, m_name.c_str(), SERVICE_ALL_ACCESS);
    if (!m_hService)
    {
        DebugMessage ("ServiceManager::ServiceManager (OpenService)");
    }

}
/* -------------------------------------------------------------------------- */
bool ServiceManager::IsExist (void) const
{
    return (m_hService != NULL);
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::IsRunning (void) const
{
    return (GetStatus() == SERVICE_RUNNING);
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::IsStopped (void) const
{
    return (GetStatus() == SERVICE_STOPPED);
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::IsPaused (void) const
{
    return (GetStatus() == SERVICE_PAUSED);
}
/* -------------------------------------------------------------------------- */
unsigned ServiceManager::GetStatus (void) const
{
    SERVICE_STATUS status = {0};
    QueryServiceStatus (m_hService, &status);
    return status.dwCurrentState;
}
/* -------------------------------------------------------------------------- */
unsigned ServiceManager::GetUserStatus (void) const
{
    SERVICE_STATUS status = {0};
    QueryServiceStatus (m_hService, &status);
    return status.dwServiceSpecificExitCode;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Start (void) const
{
    if (!m_hService) return false;
    if (!StartService (m_hService, 0, NULL))
    {
        DebugMessage ("ServiceManager::Start (StartService)");
        return false;
    }

    return true;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Stop (void)
{
    if (!m_hService) return false;
    if (!ControlService(m_hService, SERVICE_CONTROL_STOP, &m_status))
    {
        DebugMessage ("ServiceManager::Stop (ControlService)");
        return false;
    }
    return true;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Pause (void)
{
    if (!m_hService) return false;
    if (!ControlService (m_hService, SERVICE_CONTROL_PAUSE, &m_status))
    {
        if (GetLastError () != ERROR_SERVICE_NOT_ACTIVE)
        {
            DebugMessage ("ServiceManager::Pause (ControlService)");
            return false;
        }            
    }

    return true;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Continue (void)
{
    if (!m_hService) return false;
    if (!ControlService(m_hService, SERVICE_CONTROL_CONTINUE, &m_status))
    {
        DebugMessage ("ServiceManager::Continue (ControlService)");
        return false;
    }

    return true;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Install (const std::string& displayName, unsigned startType,
                              const char* services, const char* group)
{
    if (m_hService) return true;

    SCHandle hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (!hSCManager)
    {
        DebugMessage ("ServiceManager::Install (OpenSCManager)");
        return false;
    }

    m_hService = OpenService (hSCManager, m_name.c_str(), SERVICE_ALL_ACCESS);
    if (m_hService) return true;

    m_hService = CreateService (
        hSCManager, m_name.c_str(),
        displayName.c_str(), SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
        startType, SERVICE_ERROR_NORMAL, GetProcessPath (),
        group, NULL, services, NULL, NULL);

    if (!m_hService)
    {
        DebugMessage ("ServiceManager::Install (CreateService)");
        return false;
    }
    return true;
}
/* -------------------------------------------------------------------------- */
bool ServiceManager::Uninstall (void)
{
    if (!m_hService) return true;
    if (m_status.dwCurrentState != SERVICE_STOPPED)
    {
        if (!ControlService (m_hService, SERVICE_CONTROL_STOP, &m_status))
        {
            DebugMessage ("ServiceManager::Uninstall (ControlService)");
            return false;
        }
    }

    if (!DeleteService (m_hService))
    {
        DebugMessage ("ServiceManager::Uninstall (DeleteService)");
        return false;
    }
    return true;
}
/* -------------------------------------------------------------------------- */


Автор: sOckets 24.9.2006, 11:17
Цитата
вообще тут напрашивается класс 

Ну программа мелочная , поэтому я думаю класс не стоит вообще юзать для таких мелочей  ,пойми если новичём будет читать тот код что у тебя и у меня ...я (как новичёк) больше пойму то что сам накалякал smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)