powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Запуск сервиса из программы: 5 - Access Denied.
18 сообщений из 18, страница 1 из 1
Запуск сервиса из программы: 5 - Access Denied.
    #38225275
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!

У меня обычное приложение в Трее, которое запускается при входе пользователя в систему Windows 7.
Хочу из этой своей программы управлять службой (запускать/останавливать).
Под WindowsXP/2003 прекрасно работает.
Под Windows7/2008 при попытке получить доступ к службе выдает: 5 - Access Denied.

Код: pascal
1.
  hService:=OpenService(hSCManager, PAnsiChar("Service1"), SERVICE_START);


Здесь hService=0, а GetLastError выдает 5 - Access Denied.


Если запустить программку от имени администратора (с выскакиванием UAC), то все ОК, доступ открыт.
Видимо, в Windows 7 при обычном запуске программа запускается с пониженными правами (ниже чем в WinXP.)

А как сделать, чтобы программа запускалась с достаточными для управления службой правами, и при этом выскакивания UAC не происходило, ведь программа загружается автоматом при входе пользователя в Windows и сворачивается в Tray.

Заранее благодарен.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38225281
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильный ответ: никак.

Бонус-ответ: надо изменить конфигурацию службы, дав право на её запуск/останов обычным пользователям.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38225311
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А в свойствах службы в Delphi как называется это свойство? Можно ли его на стадии разработки сервиса установить таким, чтобы данную службу могли запускать обычные Пользователи?
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38225449
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это не свойство, это ACL. Меняется вызовом SetServiceObjectSecurity. Пример использования можно найти в гугле по "change windows service acl".
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38225642
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, поразбираюсь.

Всё что мне нужно, дать права службе, чтобы ее могли запускать обычные пользователи.

Самое интересное, что из оснастку "services.msc" я запускаю под обычной учёткой и спокойно, без всяких UAC и прочего, могу запускать/останавливать службы.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38226589
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52, ты что-то путаешь.

Право на SERVICE_START и SERVICE_STOP по умолчанию даётся только администраторам и LocalSystem .

Посмотри внимательнее, MMC запускается под админом. Запрос UAC будет ещё при старте. А если запускать консоль под ограниченным пользователем, то там даже кнопки старт/стоп не будут доступны (для 95% тех служб, которые не меняли свои настройки).
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #38226684
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел статейку
http://msmvps.com/blogs/erikr/archive/2007/09/26/set-permissions-on-a-specific-service-windows.aspx

При попытке выполнить "sc sdset..." выдает
[SC] OpenSCManager: ошибка: 5:
Отказано в доступе.

Если cmd запустить из-под администратора, но под той же учеткой, то команда проходит, но пользователь по-прежнему не имеет доступа к управлению службой.

Главное понять, под какой учеткой выполнять sdset.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Запуск сервиса из программы: 5 - Access Denied.
    #39927055
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте,

В прошлом актуальность вопроса для меня отпала, но сейчас снова вернулся к этой теме.
Вопрос был таким: как настроить службу чтобы все юзеры с обычными правами могли управлять службой (START, STOP, RESTART, CONFIG) ?

Решение нашлось таким:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
var hSCManager, hService: SC_HANDLE;
    BytesNeeded: cardinal;
    sd: PSecurityDescriptor;
begin
    hSCManager:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
    if hSCManager > 0 then
    begin
      hService:=OpenService(hSCManager, PChar('MyServiceName'), READ_CONTROL or WRITE_DAC);
      BytesNeeded:=0;
      if not QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd, 0, BytesNeeded) then
        if (GetLastError = ERROR_INSUFFICIENT_BUFFER)and(BytesNeeded>0) then
        begin
          GetMem(sd, BytesNeeded);
          if QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd, BytesNeeded, BytesNeeded) then
            if InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION) then
              if SetSecurityDescriptorDacl(sd, true, nil, false) then
                if SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd) then
                begin
                  // granted!
                end;
          FreeMem(sd, BytesNeeded);
        end;
    end;
end;


Код работает, вроде как надо, но хотелось бы прояснить некоторые моменты.

Команда
Код: plaintext
   sc.exe sdshow MyServiceName
до выполнения кода, указанного выше, выдавала такие права у службы:
Код: plaintext
   D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
а после применения кода права стали такими:
Код: plaintext
   D:NO_ACCESS_CONTROLS:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

Вопрос 1: не напортил ли я чего? Сильно глубоко не разобрался с данным вопросом, поэтому написал на форум.
Не могу понять, как расшифровать строку:
Код: plaintext
   D:NO_ACCESS_CONTROLS:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Что значит, NO_ACCESS_CONTROLS?
WD в конце - это Everyone, а что такое AU;FA и почему они вначале, а не в конце?

Вопрос 2: После переустановки службы, права где-то в винде сохраняются. Как сбросить эти права после деинсталляции службы, чтобы Windows "забыла" про них, чтобы после новой установки службы права стали как по-умолчанию?
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927057
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52,

https://habr.com/ru/post/75090/
https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format (тут есть NO_ACCESS_CONTROL).

Очень похоже на то, что вы просто грохнули список ACL и 'NO_ACCESS_CONTROL' означает то что означает - отсутствие каких-либо ACL.
(S: - это признак системного ACL).
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927060
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тоже так понял, что что-то грохнул.
Вопрос в том, не будет ли каких-то проблем. Опасно ли то, что ACL теперь нету.

В идеале, я бы хотел дать всем возможность запускать/останавливать/изменять конфигурацию службы.
Но как изменить код (см.выше), чтобы оставить все права на службу, но изменить или добавить то, что мне нужно?
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927213
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код выше я взял в Интернете и хотел спросить знающих людей вот что:
после чтения QueryServiceObjectSecurity для чего нужно InitializeSecurityDescriptor? Наверное как раз здесь и обнуляются права доступа? Как можно изменить код, чтобы после чтения текущих прав на службу, изменить эти права или что-то в них добавить, а затем записать обратно? Собственно, мне это и нужно, но как это сделать?
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927241
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52
Здравствуйте,

В прошлом актуальность вопроса для меня отпала, но сейчас снова вернулся к этой теме.
Вопрос был таким: как настроить службу чтобы все юзеры с обычными правами могли управлять службой (START, STOP, RESTART, CONFIG) ?

Решение нашлось таким:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
var hSCManager, hService: SC_HANDLE;
    BytesNeeded: cardinal;
    sd: PSecurityDescriptor;
begin
    hSCManager:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
    if hSCManager > 0 then
    begin
      hService:=OpenService(hSCManager, PChar('MyServiceName'), READ_CONTROL or WRITE_DAC);
      BytesNeeded:=0;
      if not QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd, 0, BytesNeeded) then
        if (GetLastError = ERROR_INSUFFICIENT_BUFFER)and(BytesNeeded>0) then
        begin
          GetMem(sd, BytesNeeded);
          if QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd, BytesNeeded, BytesNeeded) then
            if InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION) then
              if SetSecurityDescriptorDacl(sd, true, nil, false) then
                if SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd) then
                begin
                  // granted!
                end;
          FreeMem(sd, BytesNeeded);
        end;
    end;
end;



Код работает, вроде как надо, но хотелось бы прояснить некоторые моменты.

Команда
Код: plaintext
   sc.exe sdshow MyServiceName
до выполнения кода, указанного выше, выдавала такие права у службы:
Код: plaintext
   D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
а после применения кода права стали такими:
Код: plaintext
   D:NO_ACCESS_CONTROLS:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Вопрос 1: не напортил ли я чего? Сильно глубоко не разобрался с данным вопросом, поэтому написал на форум.
Не могу понять, как расшифровать строку:
Код: plaintext
   D:NO_ACCESS_CONTROLS:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Что значит, NO_ACCESS_CONTROLS?
WD в конце - это Everyone, а что такое AU;FA и почему они вначале, а не в конце?

Вопрос 2: После переустановки службы, права где-то в винде сохраняются. Как сбросить эти права после деинсталляции службы, чтобы Windows "забыла" про них, чтобы после новой установки службы права стали как по-умолчанию?
"В интернете" код взяли?.. Это понятно, но это не означает, что думать больше не надо.
1. Все открытые хендлы надо закрывать;
2. Getmem/Free брать в блок try.
3. Если запуск будет не из под админа - то с таким набором желательных прав (ALL) получите 0.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927243
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Getmem/Free брать в блок try.
Впрочем, там выделение вообще не нужно, в стеке надо объявить и все.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927534
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52
чтобы все юзеры с обычными правами могли управлять службой
Код: pascal
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.
function CreateSecAttr(const ASecDescStr: string): PSecurityAttributes;
var
  LSecDesc: Pointer;
begin
  Win32Check(
    ConvertStringSecurityDescriptorToSecurityDescriptor(
      PChar(ASecDescStr), SDDL_REVISION_1, LSecDesc, nil
    )
  );
  GetMem(Result, SizeOf(Result^));
  Result^.nLength := SizeOf(Result^);
  Result^.bInheritHandle := False;
  Result^.lpSecurityDescriptor := LSecDesc;
end;

function CreateSharedSecAttr: PSecurityAttributes;
const
  csec_desc_str = 'D:(A;OICI;GA;;;WD)';
begin
  Result := CreateSecAttr(csec_desc_str);
end;

procedure DestroySecAttr(ASecAttr: PSecurityAttributes);
begin
  if ASecAttr <> nil then begin
    LocalFree(ULONG_PTR(ASecAttr^.lpSecurityDescriptor));
    FreeMem(ASecAttr);
  end;
end;

Вызов CreateSharedSecAttr вернет атрибуты со всеми правами
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927870
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Огромное спасибо за помощь!!! Ваш код очень-очень пригодился.

Как я понял, ваш код создает структурку типа PSecurityAttributes, в которой есть указатель lpSecurityDescriptor на дескриптор безопасности с прописанной DACL. А мне как раз это и нужно, т.к. далее в своем коде я вызываю SetServiceObjectSecurity с параметром DACL_SECURITY_INFORMATION, чтобы прописать содержимое DACL из lpSecurityDescriptor в объект службы.

Я все правильно понял? Поправьте меня, если я где-то не прав.

Вопросы:

1) В вашем коде функция ConvertStringSecurityDescriptorToSecurityDescriptor сама создает и выделяет память для LSecDesc и прописывает в него DACL? Т.е. до этого вызова мне не нужно запрашивать память GetMem под указатель для LSecDesc и вызывать InitializeSecurityDescriptor? Ведь в DestroySecAttr вы освобождаете место, занятое lpSecurityDescriptor

2) Константу SDDL_REVISION_1 нигде не могу найти. В каком модуле она? Прописал пока жёстко const SDDL_REVISION_1=1;

3) Ваш код я применил так (см.ниже). На вид всё отлично работает. Если найдете замечания в коде, пожалуйста, напишите.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
var hSCManager, hService: SC_HANDLE;
    sa: PSecurityAttributes;
begin
  hSCManager:=0;
  hSCManager:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCManager > 0 then
  begin
    hService:=OpenService(hSCManager, PChar('ExilandBackupProfessional'), WRITE_DAC);
    if hService>0 then
    begin
      sa:=CreateSharedSecAttr; // создаем DACL
      if IsValidSecurityDescriptor(sa.lpSecurityDescriptor) then // на всякий случай проверяем
      begin // пропишем содержимое DACL из sa.lpSecurityDescriptor в объект службы
        if SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor) then
          ShowMessage('success!')
        else
          ShowMessage('SetServiceObjectSecurity ошибка: '+SysErrorMessage(GetLastError));
      end;
      DestroySecAttr(sa); // освобождаем sa и место, занятое lpSecurityDescriptor
      CloseServiceHandle(hService);
    end;
    CloseServiceHandle(hSCManager);
  end;
end;


Теперь любые пользователи могут работать со службой.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39927874
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
До выполнения кода команда sc.exe sdshow MyService выдавала:

Код: plaintext
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

А после

Код: plaintext
D:(A;OICI;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

Как я понял, теперь даны полные права на службу всем, и при этом SACL не испортил.
...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39928135
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52
1) В вашем коде функция ConvertStringSecurityDescriptorToSecurityDescriptor сама создает и выделяет память для LSecDesc и прописывает в него DACL? Т.е. до этого вызова мне не нужно запрашивать память GetMem под указатель для LSecDesc и вызывать InitializeSecurityDescriptor? Ведь в DestroySecAttr вы освобождаете место, занятое lpSecurityDescriptor
Именно так. Система сама выделит нужную память, а вам в конце нужно вызвать LocalFree
m52
2) Константу SDDL_REVISION_1 нигде не могу найти.
В стандартных ее нет. У меня прописано так
Код: pascal
1.
2.
3.
const
  SDDL_REVISION_1 = 1;
  SDDL_REVISION = SDDL_REVISION_1;


m52
Если найдете замечания в коде, пожалуйста, напишите.

m52
Код: pascal
1.
sa:=CreateSharedSecAttr; // создаем DACL

Достаточно сразу вызвать ConvertStringSecurityDescriptorToSecurityDescriptor. Вам же не нужна структура SecurityAtributes
m52
Код: pascal
1.
DestroySecAttr(sa); // освобождаем sa и место, занятое lpSecurityDescriptor

Соответственно тут вызов LocalFree

А вообще я бы переписал ваш код на вменяемые исключения. Иначе, когда у вас OpenService вернет ошибку вы об этом так и не узнаете

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
begin
  hSCManager:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Win32Check(hSCManager <> 0);
  try
    hService:=OpenService(hSCManager, 'ExilandBackupProfessional', WRITE_DAC);
    Win32Check(hService <> 0);
    try
      Win32Check(
        ConvertStringSecurityDescriptorToSecurityDescriptor(
          'D:(A;OICI;GA;;;WD)', SDDL_REVISION_1, LSecDesc, nil
        )
      );
      try
        Win32Check(SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, LSecDesc));
      finally
        LocalFree(ULONG_PTR(LSecDesc)); // освобождаем sa и место, занятое lpSecurityDescriptor
      end
    finally
      CloseServiceHandle(hService);
    end;
  finally
    CloseServiceHandle(hSCManager);
  end;
end;

...
Рейтинг: 0 / 0
Запуск сервиса из программы: 5 - Access Denied.
    #39928170
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Учел все ваши замечания, добавил проверки, избавился от структуры SecurityAtributes (она мне действительно не нужна).
Огромное человеческое спасибо!!!
Теперь все работает отлично! Удачи и всех благ!
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Запуск сервиса из программы: 5 - Access Denied.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]