Форум программистов, компьютерный форум, киберфорум
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.81/21: Рейтинг темы: голосов - 21, средняя оценка - 4.81
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
1

сервис

21.04.2011, 13:03. Показов 4156. Ответов 11
Метки нет (Все метки)

возник вопрос по созданию служб может кто сможет помочь?.Для создания процесса с одним сервисом,надо иметь 3
функции:main,servicemain,servicehandle.написал,получаю ошибку:служба запускается как приложение
(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)в мэйн не использовались такие функции как:OpenSCManager,CreateService.
я так понял что даже в етом случае прогу можно запустить как сервис,с помощью утилит sc,net start.
как это сделать??
и второе,я использую фун OpenSCManager,CreateService.они вызываются в мэйн главного потока,значит если запустить
прогу вторично то один и тот же сервис будет зарегистрирован дважды?кроме того,читаю:Созданная служба сразу не
запускается,для этого нужно вызвать StartService.пересмотрел кучу примеров,нигде не видел использования функ
StartService.
люди не поленитесь,расскажите пожалуйста пошагово как это работает!!!!!

Добавлено через 1 час 24 минуты
вопрос с утилитами снимается,разобрался.а вот второй вопрос остался!
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.04.2011, 13:03
Ответы с готовыми решениями:

WinXp сервис
Есть программное обеспечение, которое включает в себя сервис. На win7 работа его была стабильной. В...

Интерактивный сервис (служба)
std::cout << "Привет всем!"; Хочу сделать так, чтобы сервис мог создавать окна GUI. Просто...

Сервис поиска нужной функции
Всем привет! Хотел спросить у знающих людей: существует ли какой-нибудь сервис, где можно внести...

Нужен совет - как отлаживать сервис ?
Содрал код отсюдого http://asawicki.info/news_1404_coding_windows_services_in_c.html ...

11
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
21.04.2011, 23:21 2
C
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
#include <stdio.h>
#include <malloc.h>
#include <string.h>
 
#include <windows.h>
#include <winsvc.h>
 
//#pragma comment(linker, "/ENTRY:entry_point")
 
#define SRVC_NAME                   "SRVC_NAME"
#define SRVC_DISPLAY                "SRVC_DISPLAY"
 
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
 
HANDLE hStopEvent = 0;
BOOL isToStop = FALSE;
 
 
BOOL install_service(void)
{
    char path[MAX_PATH];
    SC_HANDLE Service;
    SC_HANDLE SCManager = OpenSCManager(
                                NULL,
                                NULL,
                                SC_MANAGER_ALL_ACCESS);
 
    if (NULL == SCManager)
        return FALSE;
 
 
    if( !GetModuleFileName( NULL, path, MAX_PATH ) )
    {
        return FALSE;
    }
 
    Service = CreateService(
        SCManager,
        SRVC_NAME,
        SRVC_DISPLAY,
        SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_AUTO_START,
        SERVICE_ERROR_NORMAL,
        path,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL);
 
    if (Service == NULL)
    {
        return FALSE;
    }
 
    StartService(Service,0,0);
    CloseServiceHandle(Service);
    return TRUE;
}
 
BOOL stop_service(void)
{
    SC_HANDLE Service;
    SERVICE_STATUS service_status;
    SC_HANDLE SCManager = OpenSCManager(
                                NULL,
                                NULL,
                                SC_MANAGER_ALL_ACCESS);
 
    if (NULL == SCManager)
        return FALSE;
 
 
    Service=OpenService(SCManager, SRVC_NAME,
        SERVICE_ALL_ACCESS);
    if(!Service)
        return FALSE;
 
    if(!ControlService(Service,
        SERVICE_CONTROL_STOP,
        &service_status))
            return FALSE;
    return TRUE;
}
 
BOOL uninstall_service(void)
{
    SC_HANDLE SCManager;
    SC_HANDLE Service;
 
    stop_service();
    SCManager = OpenSCManager(
                        NULL,
                        NULL,
                        SC_MANAGER_ALL_ACCESS);
 
    if (NULL == SCManager)
        return FALSE;
 
    Service = OpenService(
        SCManager,
        SRVC_NAME,
        DELETE);
 
    if (Service == NULL) {
        return FALSE;
    }
 
    return DeleteService(Service);
}
 
void WINAPI service_ctrl(DWORD dwCtrlCode)
{
    DWORD dwState = SERVICE_RUNNING;
 
    switch(dwCtrlCode) {
        case SERVICE_CONTROL_STOP:
            dwState = SERVICE_STOP_PENDING;
            break;
 
            case SERVICE_CONTROL_SHUTDOWN:
            dwState = SERVICE_STOP_PENDING;
            break;
 
        default: break;
    }
 
    set_service_status(dwState, NO_ERROR, 0, 0);
 
 
    if ((dwCtrlCode == SERVICE_CONTROL_STOP) ||
        (dwCtrlCode == SERVICE_CONTROL_SHUTDOWN)) {
        isToStop = TRUE;
        SetEvent(hStopEvent);
    }
}
 
BOOL set_service_status(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
{
    SERVICE_STATUS ss;
 
    if (dwCurrentState == SERVICE_START_PENDING)
        ss.dwControlsAccepted = 0;
    else
        ss.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
 
    ss.dwServiceType             = SERVICE_WIN32_OWN_PROCESS;
    ss.dwServiceSpecificExitCode = 0;
    ss.dwCurrentState            = dwCurrentState;
    ss.dwWin32ExitCode           = dwWin32ExitCode;
    ss.dwCheckPoint              = dwCheckPoint;
    ss.dwWaitHint                = dwWaitHint;
    return SetServiceStatus(hStatus, &ss);
}
 
void WINAPI ServiceMain(DWORD argc, char *argv)
{
    hStatus = RegisterServiceCtrlHandler(
        SRVC_NAME,
        (LPHANDLER_FUNCTION)service_ctrl);
    if (hStatus == (SERVICE_STATUS_HANDLE)0) {
        return;
    }
 
    set_service_status(SERVICE_RUNNING, 0, 0, 0);
 
    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
    while (WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0) {
        if (isToStop) {
            SetEvent(hStopEvent);
            break;
        }
    }
 
    CloseHandle(hStopEvent);
    set_service_status(SERVICE_STOPPED, NO_ERROR, 0, 0);
}
 
void main(void)
{
    char *cmdline = GetCommandLine();
    SERVICE_TABLE_ENTRY ServiceTable[2];
 
    if (cmdline != NULL) {
        if (strstr(cmdline, " -install")) {
            install_service();
        } else if (strstr(cmdline, " -uninstall")) {
            uninstall_service();
            ExitProcess(0);
        }
    }
 
    ServiceTable[0].lpServiceName = SRVC_NAME;
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
 
    StartServiceCtrlDispatcher(ServiceTable);
    ExitProcess(0);
}
lavan, все предельно ясно, думаю разберешся.
0
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
22.04.2011, 15:34  [ТС] 3
спасибо bobrovskii с твоим кодом буду разбираться.
я тут поторопился сказать,что вопрос с утилитами снимается,он все еще актуален!
делаю так
sc create Name binpath= Path_to_program
теперь служба появилась в консоли и в консоли я нажимаю старт,ошибок никаких нет,но программа ничего не делает!!!!! а должна создать файл.Т.е я понимаю такчто при нажатии на старт,автоматически вызывается фун StartService(),или я ошибаюсь?
C++
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
#include<windows.h>
#include<iostream>
#include<fstream>
using namespace std;
static SERVICE_STATUS hs;
static SERVICE_STATUS_HANDLE hstat;
void WINAPI sermain(DWORD argc,LPTSTR argv[]);
void WINAPI serctrlh(DWORD dwcontrol);
LPTSTR sername=_T("MY_TEST");
ofstream out;
int count;
int main() {
SERVICE_TABLE_ENTRY tab[]={{sername,sermain},{NULL,NULL}};
DWORD check;
if(!StartServiceCtrlDispatcher(tab)) {
 check=GetLastError();
 if(check==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
 cout<<"1";
 else if(check==ERROR_INVALID_DATA)
 cout<<"2";
 else if(check==ERROR_SERVICE_ALREADY_RUNNING)
 cout<<"3";
cout<<"\nbug1";
cin.get();
}
return 0;
}
void WINAPI sermain(DWORD argc,LPTSTR argv[]) {
hstat=RegisterServiceCtrlHandler(sername,serctrlh);
if(!hstat) {
out.open("serfile.txt");
if(!out) {
    cout<<"bf1";
    cin.get();
    return;
}
out<<"bug regeterhandle\n";
out.close();
return;
}
hs.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
  hs.dwCurrentState=SERVICE_START_PENDING;
  hs.dwControlsAccepted=SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  hs.dwWin32ExitCode=0;
  hs.dwServiceSpecificExitCode=0;
  hs.dwCheckPoint=0;
  hs.dwWaitHint=0;
//устанавливаем состояние сервиса
if(!SetServiceStatus(hstat,&hs)) {
out.open("serfile.txt");
if(!out) {
    cout<<"bf2";
    cin.get();
    return;
}
out<<"bug servicestatus 1\n";
out.close();
return;
}
//определяем сервис как работающий
hs.dwCurrentState=SERVICE_RUNNING;
//нет ошибок
hs.dwWin32ExitCode=NO_ERROR;
if(!SetServiceStatus(hstat,&hs)) {
out.open("serfile.txt");
if(!out) {
    cout<<"bug3";
    cin.get();
    return;
}
out<<"bug servicestatus 2\n";
out.close();
return;
}
out.open("serfile.txt");
if(!out) {
    cout<<"bug4";
    cin.get();
    return;
}
out<<"ser is started\n"<<"name is "<<argv[0]<<endl;
//work cicle of service
 
while(hs.dwCurrentState==SERVICE_RUNNING) {
count++;
Sleep(100);
}
 
}
void WINAPI serctrlh(DWORD dwcontrol) {
 
 
switch(dwcontrol) {
case SERVICE_CONTROL_STOP:
out<<"count="<<count<<endl;
out.close();
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
case SERVICE_CONTROL_SHUTDOWN:
hs.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hstat,&hs);
break;
}
return;
}
Добавлено через 53 минуты
все,с утилитами разобрался проблема была в указании пути,где создавать лог файл. пришлось прописать полный путь где надо создавать лог файл

Добавлено через 2 часа 44 минуты
со второй частью вопроса тоже разобрался
Служба не может вызвать StartService в ходе инициализации. Причина в том, что Диспетчер управления службами (SCM) в ходе инициализации блокирует базу данных управления службой, таким образом вызов StartService блокируется. Как только служба сообщает Диспетчеру управления службами (SCM), что она успешно запустилась, служба может вызвать StartService.
0
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
27.04.2011, 17:24  [ТС] 4
и сново сервис!
написал прогу(запускаю кликом по проге)
часть программы:
C++
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
int main(){
scmanager=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
      if(!scmanager) {
          return 0;
      }
      if(!GetModuleFileName(NULL,path,256)) {
      return 0;
      }
      if((ser=OpenService(scmanager,MT,SERVICE_ALL_ACCESS))==NULL) {
      service=CreateService(scmanager,MT,sername,NULL,
      SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
      path,NULL,NULL,NULL,NULL,NULL);
      if(!service) {
          return 0;
      }
      }
      if(ser) {
      StartService(ser,0,0);
      CloseServiceHandle(ser);
      CloseServiceHandle(scmanager);
      }
      else {
      StartService(service,0,0);
      CloseServiceHandle(service);
      CloseServiceHandle(scmanager);
      }
      SERVICE_TABLE_ENTRY tab[]={{MT,servicemain},{NULL,NULL}};
      DWORD check;
if(!StartServiceCtrlDispatcher(tab)) {
          return 0;
      }
      return 0;
}
выскакивает ошибка:сервис запускается как приложение
но,сервис находится в консоли Службы и через эту консоль его можно запустить.
КАК ИЗБАВИТЬСЯ ОТ ЭТОЙ ОШИБКИ????
0
374 / 321 / 32
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
27.04.2011, 17:50 5
C++
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
int main()
{
    scmanager =OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!scmanager)
    {
        return 0;
    }
    if (!GetModuleFileName(NULL, path, 256))
    {
        return 0;
    }
 
// Если служба уже существует и успешно открывается, то далее ...
    if ((ser = OpenService(scmanager, MT, SERVICE_ALL_ACCESS)) == NULL)
    {
        service = CreateService(scmanager, MT, sername, NULL,
            SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
            SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
 
        if (!service)
        {
            return 0;
        }
    }
    if (ser)
    {
// ... мы попадаем сюда, а затем ...
        StartService(ser, 0, 0);
        CloseServiceHandle(ser);
        CloseServiceHandle(scmanager);
    }
    else
    {
        StartService(service, 0, 0);
        CloseServiceHandle(service);
        CloseServiceHandle(scmanager);
    }
 
// ... попадаем сюда ...
    SERVICE_TABLE_ENTRY tab[] = {{MT, servicemain}, {NULL, NULL}};
    DWORD check;
// ... и пытаемся здесь запустить службу, как приложение, о чем вы и получаете сообщение.
    if (!StartServiceCtrlDispatcher(tab))
    {
        return 0;
    }
    return 0;
}
Добавлено через 6 минут
Да, у вас тоже самое будет если эта служба и не установлена. Используйте аргументы командной строки.
0
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
27.04.2011, 18:34  [ТС] 6
ну хорошо,я использую ком строку
C++
1
2
3
4
5
6
7
8
int main(int argc,char *argv[]) {
if(!strcpm(argv[1],"start")
//вызываем фун которая вызовет OpenSCManager,CreateService,SartService после отработки
....
//попали сюда а здесь сново
StartCtrlDispatchar(...)
//И БУДЕТ ТА ЖА ОШИБКА!если нет,объясните почему?
}
0
374 / 321 / 32
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
27.04.2011, 19:31 7
Ну так используйте что-то типа этого (не проверял)
C++
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
nt main()
{
    scmanager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!scmanager)
    {
        return -1;
    }
    if (!GetModuleFileName(NULL, path, 256))
    {
        return -1;
    }
 
    if (!strcpm(argv[1], "start")
    {
        if ((ser = OpenService(scmanager, MT, SERVICE_ALL_ACCESS)) == NULL)
        {
            StartService(ser, 0, 0);
            CloseServiceHandle(ser);
            CloseServiceHandle(scmanager);
            return 0;
        }
        else return -1;
    }
 
    if (!strcpm(argv[1], "install")
    {
        service = CreateService(scmanager, MT, sername, NULL,
            SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
            SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
        if (service)
        {
            StartService(service, 0, 0);
            CloseServiceHandle(service);
            CloseServiceHandle(scmanager);
            return 0;
        }
        else return -1;
 
    }
 
    SERVICE_TABLE_ENTRY tab[] = {{MT, servicemain}, {NULL, NULL}};
 
    if (!StartServiceCtrlDispatcher(tab))
    {
        return 0;
    }
    return 0;
}
0
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
27.04.2011, 19:54  [ТС] 8
а в чем разница,между нашими кодами?суть осталась та же!
0
374 / 321 / 32
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
27.04.2011, 20:02 9
Суть в том, что если выбран запуск или установка, то выполняется соответствующий код, а затем сразу выход (с ошибкой или без ошибки). А если программа запускается без ключа, значит она запускается как служба.
А вообще для этих целей (запуск, останов службы и т.д.) лучше написать отдельное приложение, если не устраивают существующие средства ОС.
0
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
27.04.2011, 20:32  [ТС] 10
да,но можно ведь программно проверить есть ли такая служба,запущенна ли она,т.е все то что мы ждем от аргументов ком строки.И если использовать ключ,то мы всеравно доудем до StartServiceCtrlDispatcher.Т.е если все это делать в одном приложении этой ошибки не избежать?И нормальная практика это разбивание на два приложения?
1)создание сервиса,регистрация и выход(и если я не ошибаюсь,поскольку здесь произойдет ошибка по StartServiceCtrlDispatcher консоль сама не закроется!(а хотелось бы))
2)и второе управляющая прога
0
374 / 321 / 32
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
28.04.2011, 05:48 11
Думаю можно все сделать и так, как выхотите (если я правильно понял): автоматическая регистрация и запуск службы, если она не установлена, или запуск службы, если она уже установлена. И при этом не использовать никаких аргументов командной строки. Но это будет довольно запутано потому, что нужно будет определять кто загружает образ файла в память (пользователь или диспетчер служб) и, соотвественно, решать как выполнять (как пользовательское приложение или как службу). Но таких примеров я, честно говоря, не встречал.

Обычно для этого используют аргументы командной строки и это наиболее распространенная практика.

Конечно можно совместить управляющую программу со службой. Я вижу только один положительный момент этого варианта - возможность обойтись одним единственным файлом.

Вполне нормальным вариантом будет вынести управление вашей службой в отдельное приложение.

Посмотрите пример из MSDN The Complete Service Sample, примеры из книги Дж. Рихтера "Программирование серверных приложений для Microsoft Windows 2000" (легко ищутся в сети и сама книга и примеры к ней).

Добавлено через 34 минуты
Цитата Сообщение от lavan Посмотреть сообщение
И если использовать ключ,то мы всеравно доудем до StartServiceCtrlDispatcher
Нет, не додуем. По-моему вы не совсем понимаете, что одно и то же приложение мы используем и как пользовательское приложение (для управления службой), и как приложение службы. Когда пользователь запускает это приложение с ключем, то мы выполняем только часть кода, где даем указание диспетчеру служб запустить службу, но не выполняем StartServiceCtrlDispatcher. А уже диспетчер служб, получив от нас команду, загружает этот же образ, но по другим адресам и создает новый процесс. И в нем выполняет другую часть кода.
1
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
01.05.2011, 20:38  [ТС] 12
Спасибо за помощь!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.05.2011, 20:38

Web-сервис на C++?
предыстория такова: встретились,как-то,два совсем начинающих на С++.И как обычно завели &quot;умный&quot;...

Писать сервис на мобильные платформы стандартно (нативно, под каждую отдельно) или Qt/C++ (кросплатформенно)?
Друзья, хэлп! Ведём переговоры с разными командами разработчиков. Встали перед сложным выбором....

Laravel расскажите про сервис провайдеры и сервис контейнеры
Всю доку перечитала, все равно ничего понять не могу про них. Везде пишут, что это центральные...

Сервис для уведомлений. Ошибка на небольшом кол-ве клиентов. Сервис слишком занят, чтобы обработать запрос
Уже несколько дней не могу разобраться в чём причина. Код проекта для тестирования прилагаю....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.