Я почитал многое по поводу отладки сервисов. Чего только не предлагали:
1. написать сначала простой exe а потом перенести в проект с сервисом;
2. запускать сервис и потом атачить его из делфи;
.
.
.
И всё ето не то!!!
А ктонибудь знает что нужно сделать, чтобы сервис можно было отлаживать как обыкновенный exe`шник, нажал F9 и всё прекрасно начинает проверяться!!!!!!!
Заранее спасибо за то что посмотрели!!!
Re: Отладка сервисов!!!
От:
Аноним
Дата:
18.02.04 09:02
Оценка:
Здравствуйте, Yanish, Вы писали:
Y>Я почитал многое по поводу отладки сервисов. Чего только не предлагали:
Ну вот и еще одно предложение...
Создать обычное Service приложение.
Добавить в него новую форму.
Изменить файл .dpr проекта следующим образом.
program SmpService;
uses
SvcMgr,
Forms,
srvMain in'srvMain.pas'{Service1: TService},
frmMain in'frmMain.pas'{MainForm};
{$R *.RES}begin
SvcMgr.Application.Initialize;
SvcMgr.Application.CreateForm(TService1, Service1);
SvcMgr.Application.Run;
// this isn't a service application, and we've creating the MainForm to debug
// But if application runned by Windows Service manager, don't create anythingif (not Service1.SrvcRunning) then begin
Forms.Application.Initialize;
Forms.Application.CreateForm(TMainForm, MainForm);
MainForm.Show;
MainForm.Update;
Service1.OnExecute(Service1);
end;
end.
В обработчик события
Service1.OnExecute
добавить следующий код:
procedure TService1.ServiceExecute(Sender: TService);
var
bIsService: Boolean;
begin
bIsService := not Assigned(MainForm);
while (Assigned(MainForm) or (bIsService and (not Terminated))) do
try
if (bIsService) then ServiceThread.ProcessRequests(True)
else Forms.Application.HandleMessage();
except{...}end;
end;
Y>А ктонибудь знает что нужно сделать, чтобы сервис можно было отлаживать как обыкновенный exe`шник, нажал F9 и всё прекрасно начинает проверяться!!!!!!!
Вроде бы ничего. Ты вообще себе представляешь, как работает отладчик? Ему нужно, грубо говоря, знать ProcessHandle. Для обычных приложений нажатие F9 приводит к тому, что среда получает хэндл при помощи CreateProcess и тут же аттачит дебаггер к нему. Для dll делается то же самое, только запускается не свежескомпиленный экзешник, а тот, который указан в Host Application.
Запуском сервиса ведает специальная штука в винде, svcmgr. Поэтому самая правильная отладка сервиса — это аттач к нему после старта. К сожалению, стандартный Delphi настроить таким образом нельзя.
Надо отметить, что потенциально ToolsAPI позволяет написать плугин к IDE, который будет проверять, не сервисное ли приложение мы пишем, и если да, то по F9
— проверять, скомпилирован ли Exe
— если надо компилировать, проверять, стартован ли сервис
— если надо, стопать сервис
— компилировать
— если надо, регистрировать сервис
— стартовать сервис
— ловить его ProcessID
— аттачиться к сервису
Пока что я таких плугов не видел. Хочешь написать?
... << RSDN@Home 1.1.3 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Yanish, Вы писали:
Y>Здравствуйте, Sinclair, Вы писали:
S>>Пока что я таких плугов не видел. Хочешь написать?
Y>Да хотел бы, копаю потихоньку в этом направлении ....
Здравствуйте, ironwit, Вы писали:
I>Здравствуйте, Yanish, Вы писали:
Y>>Здравствуйте, Sinclair, Вы писали:
S>>>Пока что я таких плугов не видел. Хочешь написать?
Y>>Да хотел бы, копаю потихоньку в этом направлении ....
I>что накопал?
Можна и написать если такого нет. Необходимые знания есть...
Попробую на выходных накалякать Действительно может получится полезная штука.
Только думаю что это будет специятельная кнопочка. Честно влом парсить проэкт на наличие Service Datamodule. Ну и кроме того, сервис можна написать и без стандартной реализации (SvcMgr.pas) или програма может быть написана для работы в двух режимах: GUI и Service.
Здравствуйте, Yanish, Вы писали:
Y>Я почитал многое по поводу отладки сервисов. Чего только не предлагали: Y>И всё ето не то!!!
Y>
Y>А ктонибудь знает что нужно сделать, чтобы сервис можно было отлаживать как обыкновенный exe`шник, нажал F9 и всё прекрасно начинает проверяться!!!!!!!
Самый простой вариант
Напиши так, что бы работало в 2 режимах, как приложение и как сервис.
где нибудь, у меня в exSvcUtils
var//Глобальная переменная, должна показывать что исполняемся в режиме сервиса
IsService: Boolean = False;
{ Сервис запущен в режиме установки/удаления }function SvcIsInstallMode: Boolean;
begin
Result := FindCmdLineSwitch('INSTALL') or FindCmdLineSwitch('UNINSTALL');
end;
{ Проверяем возможность запуска в режиме сервиса, TRUE если можем }function SvcCanStart(const sSvc: string; sUser: string = ''): Boolean;
var
schm: SC_Handle;// service control manager handle
schs: SC_Handle;// service handle
ServiceStartName: string;
lpqscConfig: PQueryServiceConfig;
dwSize: DWord;
s: string;
begin
Result := False;
schm := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if _failed(schm) then Exit;
schs := OpenService(schm, PChar(sSvc), SERVICE_ALL_ACCESS);
if _failed(schs) then Exit;
dwSize := 0;
QueryServiceConfig(schs, nil, 0, dwSize);
lpqscConfig := AllocMem(dwSize);
try
QueryServiceConfig(schs, lpqscConfig, dwSize, dwSize);
ServiceStartName := PQueryServiceConfig(lpqscConfig)^.lpServiceStartName;
if SameText(ServiceStartName, 'LocalSystem') then
ServiceStartName := 'SYSTEM';
finally
Dispose(lpqscConfig);
end;
CloseServiceHandle(schs);
CloseServiceHandle(schm);
sUser := GetCompUser();
// здесь пытаемся обработать ситуацию когда указано от имени кого запускать сервисif Pos('@', ServiceStartName) <> 0 then begin
s := RegStringValueGet('System\CurrentControlSet\Services\Tcpip\Parameters', 'Domain', HKEY_LOCAL_MACHINE);
if s <> ''then
sUser := sUser +'@'+ s;
end;
Result := SameText(ServiceStartName, sUser);
end;
if SvcIsInstallMode() or SvcCanStart(GetServiceName())
then begin// Start as service
SvcMgr.Application.Initialize;
exSvcUtils.IsService := True;
SvcMgr.Application.CreateForm(TdmMain, dmMain);
// удален ресурс, поэтому создаем из кода
svcService := TsvcServiceCommon.CreateNew(SvcMgr.Application);
SvcMgr.Application.Run;
end
else begin// Start as application
Application.Initialize;
Application.CreateForm(TdmMain, dmMain);
while not Application.Terminated do
Application.HandleMessage;
Application.Terminate;
end;
Здравствуйте, glh, Вы писали:
glh>Самый простой вариант
glh>Напиши так, что бы работало в 2 режимах, как приложение и как сервис.
[Skip]
Плохо что в коде SC_MANAGER_ALL_ACCESS и SERVICE_ALL_ACCESS. Не все же юзера администраторы
Мне не нравится SvcCanStart. Зачем сие? Тут нужно узнать запустил ли процес Service Manager или мы просто тыкнули в в иконку
Простенький пример я писал вот здесь
This code fragment determines whether the current process is running interactively or as a service (services running in a real user account have a SID with SECURITY_SERVICE_RID in their token; console processes have a SID with SECURITY_INTERACTIVE_RID; services running as BUILTIN\SYSTEM [LocalSystem] have neither). If the process is a LocalSystem service, the fragment checks for interactive access to the desktop, too.
Kudos to Rohan Philips for sharing this!
type
TDServiceUtils = class
protected
class function InternalIsService(out IsService, IsInteractive : Boolean): Integer;
public
....
class function IsService: Boolean;
end;
implementation
class function TDServiceUtils.IsService: Boolean;
var
aIsService : Boolean;
aIsInteractive : Boolean;
begin
aIsService := False;
Result := (InternalIsService (aIsService, aIsInteractive) <> 0) or aIsService;
end;
class function TDServiceUtils.InternalIsService(out IsService, IsInteractive : Boolean): Integer;
var
hProcessToken: THandle;
groupLength: Cardinal;
groupInfo: PTokenGroups;
siaNt: SID_IDENTIFIER_AUTHORITY;
pInteractiveSid: PSID;
pServiceSid: PSID;
ndx: Cardinal;
sanda: SID_AND_ATTRIBUTES;
aSid: PSID;
aKey: HKEY;
aStrKey: string;
aServiceName: string;
dwType: Cardinal;
dwSize: Cardinal;
begin
hProcessToken := 0;
groupLength := 50;
groupInfo := nil;
siaNt := SECURITY_NT_AUTHORITY;
pInteractiveSid := nil;
pServiceSid := nil;
Result := NO_ERROR;
try// open the tokenif not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hProcessToken) then
begin
Result := GetLastError;
Exit;
end;
// allocate a buffer of default size
groupInfo := AllocMem (groupLength);
// try to get the infoif not GetTokenInformation(hProcessToken, TokenGroups,
groupInfo, groupLength, groupLength) then
begin// if buffer was too small, allocate to proper size, otherwise errorif GetLastError <> ERROR_INSUFFICIENT_BUFFER then
begin
Result := GetLastError;
Exit;
end;
FreeMem(groupInfo);
groupInfo := AllocMem(groupLength);
if not GetTokenInformation(hProcessToken, TokenGroups,
groupInfo, groupLength, groupLength) then
begin
Result := GetLastError;
Exit;
end;
end;
//
// We now know the groups associated with this token. We want
// to look to see if the interactive group is active in the
// token, and if so, we know that this is an interactive process.
//
// We also look for the "service" SID, and if it's present,
// we know we're a service.
//
// The service SID will be present iff the service is running in a
// user account (and was invoked by the service controller).
//
// create comparison sidsif not AllocateAndInitializeSid(siaNt, 1, SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0, pInteractiveSid) then
begin
Result := GetLastError;
Exit;
end;
if not AllocateAndInitializeSid(siaNt, 1, SECURITY_SERVICE_RID,
0, 0, 0, 0, 0, 0, 0, pServiceSid) then
begin
Result := GetLastError;
Exit;
end;
// reset flags
IsInteractive := False;
IsService := False;
// try to match sids
ndx := 0;
while ndx < groupInfo.GroupCount do
begin
sanda := groupInfo.Groups[ndx];
aSid := sanda.Sid;
//
// Check to see if the group we're looking at is one of
// the two groups we're interested in.
//if EqualSid(aSid, pInteractiveSid) then
begin//
// This process has the Interactive SID in its
// token. This means that the process is running as
// a console process
//
IsInteractive := True;
IsService := False;
Break;
end else
if EqualSid(aSid, pServiceSid) then
begin//
// This process has the Service SID in its
// token. This means that the process is running as
// a service running in a user account ( not local system ).
//
IsService := True;
IsInteractive := False;
Break;
end;
Inc (ndx);
end;
if not (IsService or IsInteractive) then
begin//
// Neither Interactive or Service was present in the current
// users token, This implies that the process is running as
// a service, most likely running as LocalSystem.
//
IsService := True;
// determine if the local system service is interactive. We
// do this y looking in the service's registry and checking
// the Type value for the SERVICE_INTERACTIVE_PROCESS bit
aKey := 0;
aStrKey := Format ('SYSTEM\CurrentControlSet\Services\%s', [aServiceName]);
if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
PChar (aStrKey),
0,
KEY_READ,
aKey) = ERROR_SUCCESS then
begin
dwType := 0;
dwSize := sizeof(DWORD);
if RegQueryValueEx(aKey,
PChar ('Type'),
nil,
nil,
@dwType,
@dwSize) = ERROR_SUCCESS then
begin
if (dwType and SERVICE_INTERACTIVE_PROCESS) <> 0 then
IsInteractive := True;
end;
RegCloseKey(aKey);
end;
end;
finally
if pServiceSid <> nil then
FreeSid (pServiceSid);
if pInteractiveSid <> nil then
FreeSid (pInteractiveSid);
if groupInfo <> nil then
FreeMem (groupInfo);
if hProcessToken <> 0 then
CloseHandle (hProcessToken);
end;
end;
Здравствуйте, Danchik, Вы писали:
D>Здравствуйте, ironwit, Вы писали:
I>>Здравствуйте, Yanish, Вы писали:
Y>>>Здравствуйте, Sinclair, Вы писали:
S>>>>Пока что я таких плугов не видел. Хочешь написать?
Y>>>Да хотел бы, копаю потихоньку в этом направлении ....
I>>что накопал?
D>Можна и написать если такого нет. Необходимые знания есть...
было бы здорово
Здравствуйте, glh, Вы писали:
glh>Здравствуйте, Yanish, Вы писали:
Y>>Я почитал многое по поводу отладки сервисов. Чего только не предлагали: Y>>И всё ето не то!!!
Y>>
Y>>А ктонибудь знает что нужно сделать, чтобы сервис можно было отлаживать как обыкновенный exe`шник, нажал F9 и всё прекрасно начинает проверяться!!!!!!!
glh>Самый простой вариант
glh>Напиши так, что бы работало в 2 режимах, как приложение и как сервис.
у меня вот здесь com сервер и NT service
Здравствуйте, Danchik, Вы писали:
D>Плохо что в коде SC_MANAGER_ALL_ACCESS и SERVICE_ALL_ACCESS. Не все же юзера администраторы
Определяется еще и внешними условиями.
C превеликим бы удовольствием работал под System по умолчанию.
Тк Администратор не может настроить мне доступ для учетной записи Network Service для корректного исп-я шар на других машинах.
Учетная запись, из-под которой запускаеться эта группа сервисов имеет права администратора.
D>Мне не нравится SvcCanStart. Зачем сие? Тут нужно узнать запустил ли процес Service Manager или мы просто тыкнули в в иконку
, если можем запуститься как сервис-запускаемся как сервис.
Успехов!
C уважением, Алексей.
------------------------------------------------
Хороших %s не бывает — бывает не худший вариант.
Здравствуйте, glh, Вы писали:
glh>Здравствуйте, Danchik, Вы писали:
D>>Плохо что в коде SC_MANAGER_ALL_ACCESS и SERVICE_ALL_ACCESS. Не все же юзера администраторы
glh>Определяется еще и внешними условиями. glh>C превеликим бы удовольствием работал под System по умолчанию. glh>Тк Администратор не может настроить мне доступ для учетной записи Network Service для корректного исп-я шар на других машинах. glh>Учетная запись, из-под которой запускаеться эта группа сервисов имеет права администратора.
Я просто намекаю на то, что можна было обойтись более легкими правами доступа. Тем более что это у вас в какой-то либе. А либы должны быть написаны как можна качественней. Кусок моей либы, для примера, вы видели.
D>>Мне не нравится SvcCanStart. Зачем сие? Тут нужно узнать запустил ли процес Service Manager или мы просто тыкнули в в иконку glh>, если можем запуститься как сервис-запускаемся как сервис.
Мне всегда нужно было наоборот (и практически всем), сли запускаем не из SvcManager — то работаем как Desktop програма.
Re: Отладка сервисов!!!
От:
Аноним
Дата:
22.08.06 17:45
Оценка:
Здравствуйте, Yanish, Вы писали:
Y>
Y>А ктонибудь знает что нужно сделать, чтобы сервис можно было отлаживать как обыкновенный exe`шник, нажал F9 и всё прекрасно начинает проверяться!!!!!!!
svcom — есть такой продукт для работы с сервисами и иже с ними в Delphi. Алексей Дынников, автор этого продукта поможет Вам информацией более профессионально нежели средний RSDN-овец. Ибо занимается он этим давно и успешно. Копай в сторону aldyn-software.com