Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.07.2021, 16:44   #1
druidvic
Пользователь
 
Регистрация: 05.06.2016
Сообщений: 45
По умолчанию Как получить дескриптор службы из DisplayName?

Службу времени взял так как она без зависимостей.
W32Time - из свойств службы.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentCo ntrolSet\services\W32Time]
"DisplayName"="@%SystemRoot%\\syste m32\\w32time.dll,-200"
Код собрался даже без warning.
Код:
#include <windows.h>
#include <stdio.h>

using namespace std;

int main()
{

    SC_HANDLE  schSCManager; //инициализация
    LPCSTR lstrDispleyName="W32Time";
//    LPSTR     lpServiceName=NULL;
//    LPDWORD   lpcchBuffer=0;
   // BOOL schService;

    // Получить дескриптор базы данных SCM.
    schSCManager = OpenSCManager(
        NULL,                    // локальный компьютер
        NULL,                    // services Active database
        SC_MANAGER_ALL_ACCESS);  // полные права доступа

    if (NULL == schSCManager)
    {
        printf("OpenSCManager failed (%ld)\n", GetLastError());
        return 0;
    }

  //  Получить имя службы из DisplayName
  int schService=GetServiceKeyNameA(
                       schSCManager,
                       lstrDispleyName,
                       //lpServiceName,
                       //lpcchBuffer);
                       NULL,
                       0);

printf("ServiceKeyName failed (%ld)\n", GetLastError());
         if (NULL == schService)
    {
        printf("ServiceKeyName failed (%ld)\n", GetLastError());
        return 0;
    }

     CloseServiceHandle(schSCManager);
}
В листинге Starting a Service так и не смог понять откуда взялся параметр
szSvcName, // name of service
Поэтому попытался получить его через GetServiceKeyNameA()
Попытался прошагать:
Цитата:
Active debugger config: GDB/CDB debugger:Default
Building to ensure sources are up-to-date
Selecting target:
Debug
Adding source dir: D:\Projects\CodeBlock\API\Starting a Service\
Adding source dir: D:\Projects\CodeBlock\API\Starting a Service\
Adding file: D:\Projects\CodeBlock\API\Starting a Service\bin\Debug\Starting a Service.exe
Changing directory to: D:/Projects/CODEBL~1/API/STARTI~1/.
Set variable: PATH=.;C:\gcc\bin;C:\gcc;C:\gcc\lib exec\gcc\x86_64-w64-mingw32\11.1.0;E:\db\XE18c\dbhomeXE \bin;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windo ws\System32;C:\Windows;C:\Windows\S ystem32\wbem;C:\Windows\System32\Wi ndowsPowerShell\v1.0
Starting debugger: C:\gcc\bin\gdb.exe -fullname -quiet -args D:/Projects/CODEBL~1/API/STARTI~1/bin/Debug/STARTI~1.EXE
done
Setting breakpoints
Debugger name and version: GNU gdb (GDB) 10.1
At D:\Projects\CodeBlock\API\Starting a Service\main.cpp:28
Continuing...
Program received signal SIGSEGV, Segmentation fault.
In ?? () ()
Continuing...
Program received signal SIGSEGV, Segmentation fault.
In ?? () ()
Continuing...
Program terminated with signal SIGSEGV, Segmentation fault.
Debugger finished with status 0
Цитата:
Call stack #0 0x7fefeafddd9 ?? () (??:??)
В конце окно "Прекращена работа программы".
В документации написано:
Цитата:
"...
lpServiceName

A pointer to a buffer that receives the service name. If the function fails, this buffer will contain an empty string.

The maximum size of this array is 4K bytes. To determine the required size, specify NULL for this parameter and 0 for the lpcchBuffer parameter. The function will fail and GetLastError will return ERROR_INSUFFICIENT_BUFFER. The lpcchBuffer parameter will receive the required size.
If the buffer pointed to by lpServiceName is too small to contain the service name, the function stores no data in it. When the function returns, lpcchBuffer contains the size of the service name, excluding the NULL terminator."
Т.е. если я правильно понял, то через ошибку, сначала определяется необходимый размер буфера, для szSvcName, а затем получают ServiceName.
Вот только как это дело "прошагать" если точки прерывания, после вызова GetServiceKeyNameA, не срабатывают?
Как эту ServiceName вытащить, чтобы потом задать переменной?

Последний раз редактировалось BDA; 06.07.2021 в 21:32.
druidvic вне форума Ответить с цитированием
Старый 06.07.2021, 17:08   #2
ForenLi
Форумчанин
 
Регистрация: 02.06.2021
Сообщений: 515
По умолчанию

Цитата:
Сообщение от druidvic Посмотреть сообщение
В листинге Starting a Service так и смог понять откуда взялся параметр
Цитата:
The szSvcName variable is a global variable that contains the name of the service to be started.
Цитата:
Сообщение от druidvic Посмотреть сообщение
Т.е. если я правильно понял, то через ошибку, сначала определяется необходимый размер буфера, для szSvcName, а затем получают ServiceName.
Это не ошибка, а стандартное поведение.

Цитата:
Сообщение от druidvic Посмотреть сообщение
Вот только как это дело "прошагать" если точки прерывания, после вызова GetServiceKeyNameA, не срабатывают?
Потому что у вас программа упала.

Цитата:
Сообщение от druidvic Посмотреть сообщение
Как эту ServiceName вытащить, чтобы потом задать переменной?
Зачем она вам? Что вы сделать хотите?
ForenLi вне форума Ответить с цитированием
Старый 06.07.2021, 21:16   #3
druidvic
Пользователь
 
Регистрация: 05.06.2016
Сообщений: 45
По умолчанию

Цитата:
Сообщение от ForenLi Посмотреть сообщение
Это не ошибка, а стандартное поведение.
Потому что у вас программа упала.
Пусть стандартное, но из-за него прога падает
Цитата:
Зачем она вам? Что вы сделать хотите?
Есть 2-е программы, которым при запуске требуются работающие службы, по 3 службы на каждую.
Эти службы, после выхода из программ продолжают работать. Мне это не нравится. Железо старое.
Хочу установить для них ручной запуск, в свойствах (по умолчанию- авто), сделать для каждой лаунчеры и ручную остановку служб(после закрытия программ).
P.S. С++ только начал учить и хочется все знать :-)

Последний раз редактировалось druidvic; 06.07.2021 в 21:29.
druidvic вне форума Ответить с цитированием
Старый 06.07.2021, 21:26   #4
druidvic
Пользователь
 
Регистрация: 05.06.2016
Сообщений: 45
По умолчанию

Цитата:
Сообщение от ForenLi Посмотреть сообщение
The szSvcName variable is a global variable that contains the name of the service to be started.
Но перед тем как szSvcName сделать глобальной ее надо получить.
пробовал объявлять сразу после main,
LPSTR lpServiceName=NULL; без коментариев.
результат тот же - падает.

Последний раз редактировалось druidvic; 06.07.2021 в 21:34.
druidvic вне форума Ответить с цитированием
Старый 06.07.2021, 21:38   #5
druidvic
Пользователь
 
Регистрация: 05.06.2016
Сообщений: 45
По умолчанию

Вот и получается: чтобы запустить надо szSvcName сделать глобальной, а чтобы ее получить надо вызвать процедуру ошибки, при вызове которой прога падает.
druidvic вне форума Ответить с цитированием
Старый 06.07.2021, 22:55   #6
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,289
По умолчанию

Код:
#include <windows.h>
#include <stdio.h>

using namespace std;

int main()
{
    SC_HANDLE schSCManager;
    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (NULL == schSCManager)
    {
        printf("OpenSCManager failed (%ld)\n", GetLastError());
        return 0;
    }

    DWORD lpcchBuffer = 0;
    LPCSTR lstrDisplayName = "Microsoft ACPIEx Driver";

    int schService = GetServiceKeyName(schSCManager, lstrDisplayName, NULL, &lpcchBuffer);
    if (0 == schService && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        printf("buf size %ld\n", lpcchBuffer);
    } else {
        printf("ServiceKeyName failed (%ld)\n", GetLastError());
        CloseServiceHandle(schSCManager);
        return 0;
    }

    TCHAR *lpServiceName = NULL;
    lpServiceName = new TCHAR[lpcchBuffer + 1];
    ZeroMemory(lpServiceName, (lpcchBuffer + 1) * sizeof(TCHAR));

    schService = GetServiceKeyName(schSCManager, lstrDisplayName, lpServiceName, &lpcchBuffer);

    if (0 == schService) {
        printf("ServiceKeyName failed (%ld)\n", GetLastError());
        delete[] lpServiceName;
        CloseServiceHandle(schSCManager);
        return 0;
    }

    printf("%s\n", lpServiceName);

    delete[] lpServiceName;
    CloseServiceHandle(schSCManager);
    return 0;
}
Выдает имя, но, возможно, напутал с типами где-то.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 07.07.2021, 14:57   #7
druidvic
Пользователь
 
Регистрация: 05.06.2016
Сообщений: 45
По умолчанию

BDA, Код собирается и работает на "Ура". С типами Вы, слава богу, нигде не напутали.
Свои ошибки осознал.
Чтобы прога не падала надо было использовать if ... else. Это основная моя ошибка.
Вместо lpcchBuffer - &lpcchBuffer, т.е. сразу указатель.
Вместо "W32Time" - "Служба времени Windows"

Спасибо! Без Вас бы код долго исправлял.

P.S. Еще раз проштудирую, и можно двигаться дальше. Конечная цель - лаунчер, который будет запускать службы (перед открытием программы), отслеживать завершение и останавливать связанные службы.
druidvic вне форума Ответить с цитированием
Старый 07.07.2021, 18:06   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от druidvic Посмотреть сообщение
Конечная цель - лаунчер, который будет запускать службы (перед открытием программы), отслеживать завершение и останавливать связанные службы.
В этом случае службы известны заранее - можно воспользоваться servicename вместо display service name, ибо экранное имя может меняться в зависимости от локализации винды.
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как получить дескриптор? druidvic Общие вопросы C/C++ 10 05.08.2021 17:05
Как получить иконку зная дескриптор? pavellyba Общие вопросы Delphi 0 25.09.2011 01:08
Как правильно получить дескриптор на устройство Master_Devel Win Api 2 24.05.2011 23:54
как получить дескриптор приложения в C#? fiatik Общие вопросы .NET 1 08.11.2008 08:18