Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.12.04;
Скачать: CL | DM;

Вниз

Почему возникает исключение? Использую такую конструкцию:   Найти похожие ветки 

 
EgorovAlex ©   (2005-11-15 09:29) [0]


procedure Proc1;
begin
 try
   CoInitializeEx(nil, COINIT_MULTITHREADED);
   // работа с ADSI
   CoUninitialize;
 except
   // exception1
 end;
end;

procedure Proc2;
begin
 try
   ...
   Proc1;
 except
   // exception2
 end;
end;

Если я вызываю Proc2 из программы, то всё работает нормально, если же я вызываю Proc2 из потока сервиса, то возникает исключение exception2.

Но если я меняю эту конструкцию на такую:

procedure Proc1;
begin
 try
   // работа с ADSI
 except
   // exception1
 end;
end;

procedure Proc2;
begin
 try
   CoInitializeEx(nil, COINIT_MULTITHREADED);
   ...
   Proc1;
   CoUninitialize;
 except
   // exception2
 end;
end;

То вызов Proc2 проходит нопмально даже из потока сервиса.

Почему такое может возникать?


 
Digitman ©   (2005-11-15 09:41) [1]


> возникает исключение exception2


класс исключения какой ?


 
EgorovAlex ©   (2005-11-15 10:02) [2]

EAccessViolation


 
Digitman ©   (2005-11-15 10:09) [3]

а exception1 какого класса ?

и как ты обрабатываешь exception1 в случае его возникновения ?


 
EgorovAlex ©   (2005-11-15 10:12) [4]

exception1 вообще никогда не возникает


 
Digitman ©   (2005-11-15 10:19) [5]

значит исключение возникает

procedure Proc2;
begin
try
  ... // <- здесь
  Proc1;
except
  // exception2
end;
end;


 
EgorovAlex ©   (2005-11-15 10:26) [6]

Нет, я трассировку выполнения кода ставил (после каждой строки кода велась запись в лог файл). При этом если всё оставить как было в самом первом варианте, но закомментировать строку CoUninitialize; то исключение в Proc2 не возникает, но после этого сервис не останавливается.

Вот полный код этих функций: происходит проверка вхождения пользователя в группу (проверяются и все вложенные группы):

function UserInGroup(UserDomain, UserName, GroupDomain, GroupName: WideString): Boolean;
var
 Groups: TStringList;

 procedure GetGroupsForGroup(AdsPath, GroupName: WideString);
 var
   Connection, Command, Res: Variant;
   Group: IADsGroup;
   varMembers: OleVariant;
   varGroup, varType: WideString;
   I, N, L: Integer;
 begin
   if (AdsPath = "") then
   begin
     Connection := CreateOleObject("ADODB.Connection");
     Command := CreateOleObject("ADODB.Command");
     try
       Connection.Provider := "ADsDSOObject";
       Connection.Open("Active Directory Provider");

       Command.ActiveConnection := Connection;
       Command.Properties("Page Size") := 1000;
       Command.Properties("Searchscope") := ADS_SCOPE_SUBTREE;
       Command.CommandText := "SELECT distinguishedName FROM ""LDAP://" + UserDomain +
                              """ WHERE objectCategory=""group"" AND sAMAccountName=""" + GroupName + """";
       try
         Res := Command.Execute;
         if not Res.EOF then
           AdsPath := Res.Fields[0].Value;
       except
       end;
       Res := NULL;
     finally
       Command := NULL;
       Connection.Close;
       Connection := NULL;
     end;
   end;
   if (AdsPath <> "") then
   try
     ADsGetObject(PWideChar("LDAP://" + AdsPath), IADsGroup, Group);
     varMembers := Group.GetEx("MemberOf");
     for I := 0 to VarArrayHighBound(varMembers, 1) do
     begin
       varGroup := varMembers[I];
       N := Pos("CN=", varGroup);
       Delete(varGroup, 1, N + 2);
       varType := varGroup;
       N := Pos(",", varGroup);
       L := Length(varGroup);
       Delete(varGroup, N, L);
       if (Groups.IndexOf(varGroup) = -1) then
       begin
         Groups.Add(varGroup);
         N := Pos("CN=", varType);
         if (N > 0) then
         begin
           Delete(varType, 1, N + 2);
           N := Pos(",", varType);
           Delete(varType, N, L);
           if not SameText(varType, "Builtin") then
             GetGroupsForGroup(varMembers[I], "");
         end
         else
           GetGroupsForGroup(varMembers[I], "");
       end;
     end;
   except
   end;
 end;

var
 Enum: IEnumVariant;
 User: IADsUser;
 Group, LGroup: IAdsGroup;
 varMember: OleVariant;
 Temp: LongWord;
 I: Integer;
 ADs: IADs;
 LocalComputer: WideString;
begin
 Result := False;
 try
   CoInitializeEx(nil, COINIT_MULTITHREADED);
   Groups := TStringList.Create;
   try
     LocalComputer := GetLocalHostName;
     if SameText(UserDomain, LocalComputer) then
     begin
       if SameText(GroupDomain, LocalComputer) then
       begin
         ADsGetObject(PWideChar("WinNT://" + UserDomain + "/" + UserName), IADsUser, User);
         Enum := User.Groups._NewEnum as IEnumVariant;
         if Assigned(Enum) then
           while (Enum.Next(1, varMember, Temp) = S_OK) do
           begin
             Group := IDispatch(varMember) as IAdsGroup;
             Groups.Add(Group.Name);
             VariantClear(varMember);
           end;
         for I := 0 to Groups.Count - 1 do
           if SameText(GroupName, Groups[I]) then
           begin
             Result := True;
             Break;
           end;
       end;
     end
     else
     begin
       ADsGetObject(PWideChar("WinNT://" + UserDomain + "/" + UserName), IADsUser, User);
       Enum := User.Groups._NewEnum as IEnumVariant;
       if Assigned(Enum) then
         while (Enum.Next(1, varMember, Temp) = S_OK) do
         try
           Group := IDispatch(varMember) as IAdsGroup;
           Groups.Add(Group.Name);
           GetGroupsForGroup("", Group.Name);
         finally
           VariantClear(varMember);
         end;
       if SameText(GroupDomain, LocalComputer) then
       begin
         ADsGetObject(PWideChar("WinNT://" + GroupDomain + "/" + GroupName), IADsGroup, LGroup);
         Enum := LGroup.Members._NewEnum as IEnumVariant;
         if Assigned(Enum) then
           while (Enum.Next(1, varMember, Temp) = S_OK) do
           try
             ADs := IDispatch(varMember) as IADs;
             if SameText(ADs.Class_, "User") then
             begin
               User := IDispatch(varMember) as IAdsUser;
               if SameText(UserName, User.Name) then
               begin
                 Result := True;
                 Break;
               end;
             end
             else
             if SameText(ADs.Class_, "Group") then
             begin
               Group := IDispatch(varMember) as IAdsGroup;
               for I := 0 to Groups.Count - 1 do
                 if SameText(Group.Name, Groups[I]) then
                 begin
                   Result := True;
                   Break;
                 end;
               if Result then
                 Break;
             end;
           finally
             VariantClear(varMember);
           end;
       end
       else
         for I := 0 to Groups.Count - 1 do
           if SameText(GroupName, Groups[I]) then
           begin
             Result := True;
             Break;
           end;
     end;
   finally
     Groups.Free;
     CoUninitialize;
   end;
 except
   WriteErr(0, "UserInGroup");
 end;
end;

function UserInGroupSidStr(UserDomain, UserName, GroupSidStr: WideString): Boolean;
var
 GroupName, GroupDomain: WideString;
 N: Integer;
begin
 Result := False;
 try
   GroupName := SidStrToUser(GroupSidStr);
   GroupDomain := GroupName;
   N := Pos("\", GroupName);
   if (N > 0) then
   begin
     Delete(GroupName, 1, N);
     Delete(GroupDomain, N, Length(GroupDomain));
     if SameText(GroupDomain, "BUILTIN") then
       GroupDomain := GetLocalHostName;
     Result := UserInGroup(UserDomain, UserName, GroupDomain, GroupName);
   end;
 except
   WriteErr(0, "UserInGroupSidStr");
 end;
end;


 
Digitman ©   (2005-11-15 10:31) [7]

приведи полный код обработчиков событий объекта TService OnCreate, onDestroy, OnStart, OnStop, OnExecute


 
EgorovAlex ©   (2005-11-15 10:44) [8]

У меня сервис на API написан, ничего особенного, этот код работает уже долго:

program pService;

uses
 Windows, WinSvc, SysUtils, ScktComp, Registry, Classes,
 uThread, uProcs, uRecords, uTypes;

type
 TSvcServerSocket = class(TServerSocket)
   procedure ServerSocketGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
     var SocketThread: TServerClientThread);
 end;

var
 DispatchTable: array [0..1] of _SERVICE_TABLE_ENTRYA;
 SvcStatus    : SERVICE_STATUS;
 hSvc         : SERVICE_STATUS_HANDLE;

 Port         : Integer;
 ServerSocket : TSvcServerSocket;

procedure TSvcServerSocket.ServerSocketGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
 var SocketThread: TServerClientThread);
begin
 try
   SocketThread := TDataThread.Create(False, ClientSocket);
 except
   WriteErr(204, "");
 end;
end;

procedure LoadServerSettings;
begin
 try
   with TRegistry.Create do
   try
     RootKey := HKEY_LOCAL_MACHINE;
     if OpenKey(PMRegPath, True) then
       if ValueExists("Port") then
         Port := ReadInteger("Port")
       else
         Port := DefaultPort;
   finally
     Free;
   end;
 except
   WriteErr(206, "");
 end;
end;

procedure SetSvcStatus(CurrentState, ExitCode, CheckPoint, WaitHint: Cardinal);
begin
 SvcStatus.dwCurrentState  := CurrentState;
 SvcStatus.dwWin32ExitCode := ExitCode;
 SvcStatus.dwCheckPoint    := CheckPoint;
 SvcStatus.dwWaitHint      := WaitHint;
 SetServiceStatus(hSvc, SvcStatus);
end;

procedure ServiceCtrlHandler(Opcode: Cardinal); stdcall;
begin
 case Opcode of
   SERVICE_CONTROL_STOP,
   SERVICE_CONTROL_SHUTDOWN:
     begin
       SetSvcStatus(SERVICE_STOP_PENDING, 0, 1, 2000);
       SetEvent(hStopEvent);
     end;
   SERVICE_CONTROL_INTERROGATE:
     SetSvcStatus(SvcStatus.dwCurrentState, 0, 0, 0);
 end;
end;

procedure ServiceMain(argc: Cardinal; var argv: array of PChar); stdcall;
begin
 hSvc := RegisterServiceCtrlHandler(ServiceName, @ServiceCtrlHandler);
 if (hSvc <> 0) then
 try
   SvcStatus.dwServiceType             := SERVICE_WIN32;
   SvcStatus.dwControlsAccepted        := SERVICE_ACCEPT_STOP or SERVICE_ACCEPT_SHUTDOWN;
   SvcStatus.dwServiceSpecificExitCode := 0;

   SetSvcStatus(SERVICE_START_PENDING, 0, 1, 2000);
   if CreateStorage then
     LoadRecords
   else
   begin
     WriteErr(72, "");
     Exit;
   end;

   SetSvcStatus(SERVICE_START_PENDING, 0, 2, 2000);
   LoadServerSettings;
   if (RegInfo <> "") then
   begin
     MaxConnections := StrToInt(Copy(RegInfo, 0, Pos(#13#10, RegInfo) - 1));
     RegInfo := Copy(RegInfo, Pos(#13#10, RegInfo) + 2, Length(RegInfo));
   end;

   SetSvcStatus(SERVICE_START_PENDING, 0, 3, 2000);
   try
     ServerSocket := TSvcServerSocket.Create(nil);
     ServerSocket.ServerType  := stThreadBlocking;
     ServerSocket.OnGetThread := ServerSocket.ServerSocketGetThread;
     ServerSocket.Port        := Port;
     ServerSocket.Active      := True;

     SetSvcStatus(SERVICE_RUNNING, 0, 0, 0);
   except
     WriteErr(202, "");
   end;

   hStopEvent := CreateEvent(nil, True, False, nil);
   WaitForSingleObject(hStopEvent, INFINITE);
   CloseHandle(hStopEvent);

   SetSvcStatus(SERVICE_STOP_PENDING, 0, 2, 2000);
   ServerSocket.Free;
   FreeStorage;

   SetSvcStatus(SERVICE_STOP_PENDING, 0, 3, 2000);
   if not BadPassword then
     CopyFile(PChar(DataPath + "Records.dat"), PChar(DataPath + "Records.bak"), False);
 finally
   SetSvcStatus(SERVICE_STOPPED, 0, 0, 0);
 end
 else
   WriteErr(70, "");
end;

begin
 LoadGlobalSettings;
 try
   DispatchTable[0].lpServiceName := ServiceName;
   DispatchTable[0].lpServiceProc := @ServiceMain;
   DispatchTable[1].lpServiceName := nil;
   DispatchTable[1].lpServiceProc := nil;

   if not StartServiceCtrlDispatcher(DispatchTable[0]) then
     WriteErr(88, "");
 except
   WriteErr(200, "");
 end;
end.


 
Digitman ©   (2005-11-15 11:03) [9]

и все эти чудеса, видимо, происходят в контексте TDataThread.ClientExecute ?


 
EgorovAlex ©   (2005-11-15 11:30) [10]

Да, там от клиента сервис получает сообщение запрос на проверку вхождения и ему возвращается результат:

procedure TDataThread.ClientExecute;
var
 Msg, Id, ParentId, Count, Mode, Index, Security, Port, cId: Cardinal;
 SS   : TWinSocketStream;
 Rec  : TDataRecord;
 WS, S: TMemoryStream;
 Size : Longint;
 UserName, DomainName, DBPassword, Computer, aLogin, aComputer, Reg: string250;
 MaxSize, Left: Integer;
 Crypt, Client: Boolean;
 S1, S2, S3: string100;

 procedure WriteMsg(Msg: Cardinal);
 begin
   WS.Write(Msg, SizeOf(Msg));
 end;

begin
 SS := TWinSocketStream.Create(ClientSocket, 1200000);
 S := TMemoryStream.Create;
 try
   try
     if ReadBuffer(SS, Msg, SizeOf(Msg), 0) then
     begin
       WS := TMemoryStream.Create;
       // &#239;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#231;&#224;&#227;&#238;&#235;&#238;&#226;&#238;&#234;
       if ReadBuffer(SS, Client, SizeOf(Client), MSG_CONNECT) and
          ReadBuffer(SS, cId, SizeOf(cId), MSG_CONNECT) then
       begin
         // &#239;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#228;&#224;&#237;&#237;&#251;&#229;
         case Msg of
           MSG_CHECK_PERMISSION:
             if ReadBuffer(SS, Id, SizeOf(Id), MSG_CHECK_PERMISSION) and
                ReadBuffer(SS, UserName, SizeOf(UserName), MSG_CHECK_PERMISSION) and
                ReadBuffer(SS, DomainName, SizeOf(DomainName), MSG_CHECK_PERMISSION) then
               if CheckPermission(Id, UserName, DomainName, Security) then
               begin
                 WriteMsg(MSG_PERMISSION_CHECKED);
                 WS.Write(Security, SizeOf(Security));
               end
               else
                 WriteMsg(MSG_ERR_CHECK_PERMISSION)
             else
               WriteMsg(MSG_ERR_READ_DATA);
         end;
       end;
       WS.Position := 0;
       ClientSocket.SendStream(WS);
     end;
   except
     WriteErr(20, "");
   end;
 finally
   S.Free;
   SS.Free;
 end;
end;

В CheckPermission есть список пользователей и групп, который проверяется и там используется эта UserInGroupSidStr


 
Digitman ©   (2005-11-15 11:38) [11]

так ...

и AV-исключение, насколько я понимаю, возникает при исполнении строчки

if CheckPermission(Id, UserName, DomainName, Security) then

?


 
EgorovAlex ©   (2005-11-15 14:12) [12]

Точно, чтобы небыло неясностей вот эта процедура:
тут для записи получаем список разрешённых пользователей и групп и после этого проверяем у пользователя разрешения для этой записи:

function CheckPermission(Id: Cardinal; UserName, DomainName: string; var Security: Cardinal): Boolean;
var
 S, S2: TMemoryStream;
 Count, Sec: Cardinal;
 SRec: TSecurityRec;
 I: Integer;
 UserSid: string;
 Found: Boolean;
begin
 Result := False;
 S := TMemoryStream.Create;
 try
   if (DomainName = "") then
     UserSid := UserToSidStr(UserName)
   else
     UserSid := UserToSidStr(DomainName + "\" + UserName);

   GetPermissions(Id, Count, S);
   if (Count = 0) then
   begin
     S.Clear;
     SRec.Name    := UserSid;
     SRec.RecType := SecOwner or SecWrite or SecRead;
     S.Write(SRec, SizeOf(SRec));
     EditPermissions(Id, 1, S);
     Count := 1;
   end;
   S.Position := 0;
   Security := 0;
   Sec := 0;
   Found := False;
   for I := 0 to Count - 1 do
   begin
     S.Read(SRec, SizeOf(SRec));
     Sec := Sec or SRec.RecType;
     if ((SRec.RecType and SecGroup) = 0) then
     begin
       if (UserSid = SRec.Name) then
       begin
         Security := Security or SRec.RecType;
         Result := True;
         Found := True;
       end;
     end
     else
       if UserInGroupSidStr(DomainName, UserName, SRec.Name) then
       begin
         Security := Security or SRec.RecType;
         Result := True;
       end;
   end;
   // &#229;&#241;&#235;&#232; &#237;&#229; &#237;&#224;&#233;&#228;&#229;&#237;&#238; &#237;&#232; &#238;&#228;&#237;&#238;&#227;&#238; &#226;&#235;&#224;&#228;&#229;&#235;&#252;&#246;&#224;
   if (Sec and SecOwner = 0) then
   begin
     if Found then
     begin
       S2 := TMemoryStream.Create;
       try
         S.Position := 0;
         for I := 0 to Count - 1 do
         begin
           S.Read(SRec, SizeOf(SRec));
           if (UserSid = SRec.Name) then
             SRec.RecType := SRec.RecType or SecOwner or SecWrite or SecRead;
           S2.Write(SRec, SizeOf(SRec));
         end;
         EditPermissions(Id, Count, S2);
       finally
         S2.Free;
       end;
     end
     else
     begin
       SRec.Name := UserToSidStr(UserName);
       SRec.RecType := SRec.RecType or SecOwner or SecWrite or SecRead;
       S.Write(SRec, SizeOf(SRec));
       EditPermissions(Id, Count + 1, S);
     end;
   end;
 finally
   S.Free;
 end;
end;


 
Digitman ©   (2005-11-15 14:38) [13]

я не понял - где в [12] вызов ф-ции UserInGroup() (там где собственно и происходит, судя по твоему тексту, вызов якобы проблемной CoUninitialize) ?


 
EgorovAlex ©   (2005-11-15 15:54) [14]

Там есть вызов UserInGroupSidStr (я её приводил), a из неё уже вызывается UserInGroup


 
Набережных С. ©   (2005-11-16 06:52) [15]


> EgorovAlex ©

Скомпилируй с отладочной инфой, разреши временно взаимодействие с рабочим столом, расставь точки останова и запусти сервис из компонента консоли.
В Delphi выбери Project/attach to process. Найди в списке свой серверный процесс и подключись к нему. Теперь подключай клиента и смотри, что там делается.

И попутно - а каков сакральный смысл в использовании флага COINIT_MULTITHREADED? Что-то в коде не просматривается...


 
Набережных С. ©   (2005-11-16 06:53) [16]


> Найди в списке свой серверный процесс

В смысле - сервисный, процесс сервиса.


 
EgorovAlex ©   (2005-11-16 08:13) [17]

Спасибо, отладить попробую - до этого ни разу так не пробовал отлаживать сервис.
Насчёт COINIT_MULTITHREADED - к этой процедуре предполагается одновременный доступ нескольких клиентов и он в таких случаях будет выполняться в разных потоках. А какой флаг предпочтительней? Я пробовал и CoInitialize(nil), но это мало помогает.


 
Набережных С. ©   (2005-11-16 08:45) [18]


> EgorovAlex ©   (16.11.05 08:13) [17]


> Я пробовал и CoInitialize(nil), но это мало помогает.

Да нет, она тут не при чем, это понятно.

> Насчёт COINIT_MULTITHREADED - к этой процедуре предполагается
> одновременный доступ нескольких клиентов и он в таких случаях
> будет выполняться в разных потоках.

Ну так подключение-то к объектам все равно каждый клиент производит независимо от других, в собственном потоке, и имеет дело с собственным экземпляром.

С точки зрения СОМ твой сервис - клиент. MTA в клиенте имеет смысл, если работаем с внутрипроцессным сервером, при этом создаем один экземпляр серверного объекта, а потом работаем с ним из разных потоков, либо если нужно работать из одного потока с объетом, созданным в другом потоке. Но только если сервер внутрипроцессный. Ну, возможно, еще в некоторых очень специфичных случаях. Но в данном случае я никакого смысла не вижу, а вот ресурсов MTA потребляет несколько больше, чем STA, в сервисе это надо учитывать.


 
EgorovAlex ©   (2005-11-16 09:22) [19]

Спасибо за информацию о COM.

Что-то не получается отлаживать, точнее не получается трассировать. Скомпилировал сервис, запустил, подключился - о том, что подключился я сужу так, если нажать Ctrl+F2, то сервис останавливается. Но клиент не подключается к сервису, когда я его отлаживаю - сообщает об ошибке соединения.


 
Digitman ©   (2005-11-16 10:27) [20]


> клиент не подключается к сервису, когда я его отлаживаю
> - сообщает об ошибке соединения


ну разумеется не подключится !
ты же ctrl-F2 нажал, тем самым остановив выполнение кодовых потоков сервиса ...

тебе нужно не ctrl-F2 жать, а установить брейкпойнт в самом начале ClientExecute, тогда как только клиент подключится произойдет останов на этом брейкпойнте, и далее все как обычно - пошаговая трассировка с контролем что, где, как и почему происходит у тебя при обработке кл.запроса


 
EgorovAlex ©   (2005-11-16 11:38) [21]

Нет, что я не смогу подключиться после ctrl-F2 я и сам понимаю. Я не могу клиентом к сервису подключиться сразу после того, как я из дельфы подключаюсь отлаживать сервис. Если не подключаться, то коннектится.
У меня отладка не получается - я и брекпойнты ставлю - на них ничего не останавливается.


 
Digitman ©   (2005-11-16 12:14) [22]


> EgorovAlex ©   (16.11.05 11:38) [21]


а ты в точности выполнил все инструкции по отладке сервиса, как они приведены в справке в теме "Debugging service applications" ?


 
Набережных С. ©   (2005-11-16 12:43) [23]


> EgorovAlex ©   (16.11.05 11:38) [21]

Ну а компилировал-то с включенной отладочной информацией?

Вот ты установил сервис, далее:
-- Перекомпилируй его на всякий случай.
-- Установи точки останова.
-- В консоли открой компонент Службы.
-- Проверь свойства своей службы, должно быть разрешено взаимлодействие с рабочим столом. Если нет, установи.
-- Запусти службу.
-- В Delphi подключись к процессу службы. В момент подключения произойдет останов и появится окно CPU, сервис приостановится. Нажми F9 чтобы продолжить выполнение. Окно CPU можно закрыть.

После этого служба будет работать в нормальном режиме, пока не дойдет до точки останова.

У меня ни разу не было никаких с этим проблем.


 
EgorovAlex ©   (2005-11-16 13:19) [24]

To Набережных С.:
При помпиляции включено - Menu Project -> Options... -> tab Compiler -> секция Debugging: все галки кроме Use Debug DCUs включены


 
Digitman ©   (2005-11-16 13:32) [25]


> Если не подключаться, то коннектится


ну может твой клиент критичен к таймауту ожидания коннекта - кто ж его знает) ..


> отладка не получается - я и брекпойнты ставлю - на них ничего
> не останавливается.


еще раз спрашиваю - ты "соблюл" ВСЕ рекомендации, указанные в справке ?
или кой-чего проигнорировал якобы за ненадобностью-непонятностью ?

sleep() пробовал использовать в коде сервиса-трэда ?


 
EgorovAlex ©   (2005-11-16 14:18) [26]

Мои шаги:
1. Скомпилировал сервис с вышеуказанными параметрами Debugging
2. Прописал в реестре параметр как указано в хелпе:
   1 First create a key called Image File Execution Options in the following registry location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
   2 Create a subkey with the same name as your service (for example, MYSERV.EXE). To this subkey, add a value of type REG_SZ, named Debugger. Use the full path to Delphi32.exe as the string value.
3. Запустил сервис (взаимодействие с рабочим столом активировано)
4. Открыл в Delphi проект сервиса и выбрал Run -> Attach to process... и подключился к сервису.
5. Выкло окно CPU: я нажал F9 и закрыл это окно. Перед этим поставил брекпойнты в нужных местах.
6. Клиентом коннекчусь к сервису, работаю, но брекпойнты не обрабатываются хотя клиент нормально коннектится и работает.

Что я делаю не так?


 
Набережных С. ©   (2005-11-16 14:40) [27]

EgorovAlex ©   (16.11.05 13:19) [24]
Ну не знаю, что еще сказать:( У меня иногда были проблемы с неинтерактивными сервисами, достаточно было сделать их интерактивнами и все начинало работать. Все, что описано в [25] точно выполняется? Работаешь под полноценным администратором? Попробуй подкорректировать реестр, как в справке написано, но сразу скажу, что мне это ни разу не требовалось.


 
Digitman ©   (2005-11-16 14:41) [28]

вроде бы все так ..

ОС и версия Делфи какие ?

sleep() в ServiceMain() пробовал ?


 
Набережных С. ©   (2005-11-16 14:41) [29]

Что-то тут опять глюкануло, не видел EgorovAlex ©   (16.11.05 14:18) [26]


 
Набережных С. ©   (2005-11-16 14:45) [30]

EgorovAlex ©   (16.11.05 14:18) [26]
Точки останова активны? Синие точки есть? В качестве сервиса точно запускается тот файл, который создала Delphi во время ПОСЛЕДНЕЙ компиляции?


 
Набережных С. ©   (2005-11-16 16:25) [31]

http://delphimaster.net/view/2-1132036191/


 
Набережных С. ©   (2005-11-16 16:27) [32]

Да чтож его так колбасит-то, блин, вот дерьмо!

> 3. Запустил сервис (взаимодействие с рабочим столом активировано)
> 4. Открыл в Delphi проект сервиса и выбрал Run -> Attach
> to process... и подключился к сервису.

Имхо, вот оно. Поменяй действия местами. Открываешь проект, компилишь, запускаешь сервис, подключаешься. Именно в такой последовательности. То есть к моменту запуска сервиса проект уже дожен быть открыт в дельфи и скомпилирован!
А в реестре, скорее всего, можно убрать изменения.


 
Набережных С. ©   (2005-11-16 16:29) [33]


> Да чтож его так колбасит-то, блин, вот дерьмо!

Это я про провайдера, не подумай чего:)


 
EgorovAlex ©   (2005-11-16 19:48) [34]

> Синие точки есть?
Нет, синих точек нет :( Даже когда подключился к сервису


 
Набережных С. ©   (2005-11-16 20:07) [35]

Ну тогда остается два варианта:
- В исполняемом файле нет актуальной отладочной информации.
- SCM запускает не тот файл.

Действуй строго по шагам:

1) Деинсталлируй сервис.
2) Выгрузи проект из IDE.
3) Произведи поиск по всем дискам и удали ВСЕ найденные файлы  YourService.exe.
4) Загрузи проект в Дельфи.
5) Расставь точки останова.
6) Пересобери( Build ) проект с включенной отл. инфой.
7) Инсталлируй сервис. Проследи, чтобы путь к сервису указывал на этот вновь созданный файл YourService.exe. Прям в компоненте "Службы".
8) Из консоли запусти сервис.
9) Приаттачься отладчиком к процессу сервиса.

Если все это не поможет, то я уже не знаю:( Разве что повторить это же после удаления всех корректур в реестре.


 
EgorovAlex ©   (2005-11-17 14:20) [36]

Спасибо, разобрался. Подключится удалось - я сервис из другого места запускал, не из того, где он скомпилирован. Только проблемы это не решило - исключение возникает, а почему - не понятно :(


 
Digitman ©   (2005-11-17 14:23) [37]


> проблемы это не решило - исключение возникает, а почему
> - не понятно


ну а подключался-то для чего ?)

как раз для ответа на вопрос "почему" ...

ставь брейкпойнт на начало ClientExecute - и вперед, с песней ... пошаговая трассировка ответит на твой вопрос



Страницы: 1 вся ветка

Текущий архив: 2005.12.04;
Скачать: CL | DM;

Наверх




Память: 0.62 MB
Время: 0.059 c
8-1120822518
Pavel_Delphin
2005-07-08 15:35
2005.12.04
Обработка видеосигнала.


1-1131426661
BanderLog
2005-11-08 08:11
2005.12.04
ComboBox + Mask


2-1132415019
pohil
2005-11-19 18:43
2005.12.04
Указатели


14-1131734081
ArtemESC
2005-11-11 21:34
2005.12.04
Chdisk в WinXP


2-1131767247
Астроном-любитель
2005-11-12 06:47
2005.12.04
Как найти формулу луны ?