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

Вниз

Запуск одной копии программы и обнаружение ее при повторном запус   Найти похожие ветки 

 
Fantom   (2005-01-21 10:07) [0]

Всем привет!
Тема не самая новая и уже проелась, но вчера просидел 3 часа в поисках примера по етому поводу так ничего толкового не нашел... Помогите пожалуйста.
Есть программа, написанная на Delphi. Мне нужно чтобы пользователь мог запусть ее только один раз, а при повторном запуске, если прога уже запущена, первая копия становилась активной независимо свернутая она на панель или весит в трее...
Спасибо!


 
REA   (2005-01-21 10:43) [1]

Я делал так (насчет трея не знаю):

Function CheckStart: Boolean;
Var
 HWin: HWnd;
 CName, SavTitle, FileName: String;
 CopyStruct: TCopyDataStruct;
Begin
 SavTitle := Application.Title;
 Application.Title := "";
 HWin := FindWindow("TApplication", PChar(SavTitle));
 If (HWin<>0) Then
 Begin
   If IsIconic(HWin) then
     ShowWindow(HWin, SW_Restore);
   BringWindowToTop(HWin);
   SetForegroundWindow(HWin);
   If ParamCount>0 Then
   Begin
     CopyStruct.dwData := 1;
     FileName := ParamStr(1);
     CopyStruct.cbData := Length(FileName);
     CopyStruct.lpData := PChar(FileName);
     CName := TSketchMainForm.ClassName;
     HWin := FindWindow(PChar(CName), Nil);
     If HWin<>0 Then
       SendMessage(HWin, WM_COPYDATA, Application.Handle, Integer(@CopyStruct));
   End;
   Result := False;
 End Else
 Begin
   Application.Title := SavTitle;
   Result := True;
 End;
End;


 
Digitman ©   (2005-01-21 10:49) [2]

одно из решений - использование именованых программных каналов для коммуникации между процессами

unit IPCThread;

interface

uses
 Windows, Messages, SysUtils, Classes;

const

 sIPCPipeName    = "SomeIPCchannel";
 MAX_MSG_SIZE    = 1024;
 DEFAULT_TIMEOUT = 5000;
 TM_CONNECT      = WM_USER + 1000;
 TM_SENDMSG      = WM_USER + 1001;

type

 ETransportError = class(Exception); //исключение по отказу транспорта (например, соединение разорвано)
 EActionError = class(Exception); //исключение в ходе исполнения акции

 TSignature = (CallSig, ResultSig); //сигнатура транспортного пакета
 TAction = Integer; //код акции

//заголовок информациионного пакета
 PDataBlockHeader = ^TDataBlockHeader;
 TDataBlockHeader = packed record
   Signature: TSignature; //сингатура
   Action: TAction; //код акции
   ExceptionFlag: Boolean; //флаг исключения для пакета с сигнатурой результата
   WaitEvent: DWord; //событие ожидания результата инф.транзакции
   ParamSize: DWord; //кол-во байт параметра акции
 end;

//информационный пакет
 PDataBlock = ^TDataBlock;
 TDataBlock = packed record
   Header: TDataBlockHeader; //заголовок
   Params: array[0..MAX_MSG_SIZE - SizeOf(TDataBlockHeader) - 1] of Byte; //параметры
 end;

const
 DataBlockHdrSize = SizeOf(TDataBlockHeader);

type

//прототип ф-ции обработки вызванной акции
 TActionHandler = function(Action: TAction; Params: Pointer; ParamSize: DWord; out ResultData; out ResultSize: DWord): Boolean;

//базовый класс транспортного трэда

 TIPCThread = class(TThread)
 private
   FPipeName: String;
   hPipe: THandle;
   hWnd: THandle;
   ovr, ovw: TOverlapped;
   FEvents: array[0..1] of THandle;
   FConnected, FPendingConnect, FPendingRead, FPendingWrite: Boolean;
   FInBuf, FOutBuf: PDataBlock; //буферы приема/передачи
   FBytesRead, FBytesWritten: DWord;
   FActionHandler: TActionHandler;
   FSendQueue: TThreadList; //очередь передаваемых инф.пакетов
   FPendingQueue: TList; //список объектов-событий ожидания результатов акций
   FRecvQueue: TThreadList; //очередь принятых инф.пакетов
   procedure ClearSendingQueue;
   procedure ClearReceivingQueue;
   procedure ClearPendingQueue;
   procedure ProcessReadEvent;
   procedure ProcessWriteEvent;
   procedure ProcessMessages;
   procedure ProcessTransport;
   procedure ProcessIncomingCall;
   procedure ProcessIncomingResult;
   procedure MsgQuit(var Message: TMessage); message WM_QUIT;
   procedure MsgSendMsg(var Message: TMessage); message TM_SENDMSG;
 protected
   procedure DoTerminate; override;
   procedure DoConnect; virtual;
   procedure DoDisconnect; virtual;
   procedure Execute; override;
 public
   constructor Create(WndHandle: THandle; PipeName: String; ActionHandler: TActionHandler);
   destructor Destroy; override;
//после УСПЕШНОГО исполнения акции во избежание утечек памяти
//следует вызвать FreeMem(ResultData), если ResultSize > 0
   function CallAction(Action: TAction; Params: Pointer; ParamSize: DWord; out ResultData: Pointer; out ResultSize: DWord): Boolean;
   property Connected: Boolean read FConnected;
 end;

//класс транспортного трэда клиента
 TIPCClientThread = class(TIPCThread)
 private
   FServerName: String;
 protected
   procedure DoConnect; override;
   procedure DoDisconnect; override;
 public
   constructor Create(WndHandle: THandle; ServerName, PipeName: String; ActionHandler: TActionHandler);
 end;

//класс транспортного трэда сервера
 TIPCServerThread = class(TIPCThread)
 private
 protected
   procedure DoConnect; override;
   procedure DoDisconnect; override;
 public
 end;

продолжение следует...


 
Digitman ©   (2005-01-21 10:50) [3]

implementation

{ TIPCThread }

constructor TIPCThread.Create(WndHandle: THandle; PipeName: String; ActionHandler: TActionHandler);
begin
 hWnd := WndHandle;
 FPipeName := PipeName;
 FActionHandler := ActionHandler;
 FillChar(ovr, sizeof(ovr), 0);
 FillChar(ovw, sizeof(ovw), 0);
 ovr.hEvent := CreateEvent(nil, False, False, nil);
 ovw.hEvent := CreateEvent(nil, False, False, nil);
 FEvents[0] := ovr.hEvent;
 FEvents[1] := ovw.hEvent;
 GetMem(FInBuf, MAX_MSG_SIZE);
 GetMem(FOutBuf, MAX_MSG_SIZE);
 FSendQueue := TThreadList.Create;
 FRecvQueue := TThreadList.Create;
 FPendingQueue := TList.Create;
 inherited Create(False);
end;

destructor TIPCThread.Destroy;
begin
 PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
 inherited;
 if hPipe <> 0 then
   CloseHandle(hPipe);
 FRecvQueue.Free;
 FSendQueue.Free;
 FPendingQueue.Free;
 CloseHandle(ovr.hEvent);
 CloseHandle(ovw.hEvent);
 CloseHandle(hPipe);
 FreeMem(FInBuf);
 FreeMem(FOutBuf);
end;

procedure TIPCThread.Execute;
var
 Msg: TMsg;
begin
 PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
 try
//пока трансп.трэд не терминирован
   while not Terminated do
     begin
       DoConnect; //соединение с удаленным партнером
       if Terminated then Exit;
//пока транспорт активен и трэд не терминирован
       while not Terminated and FConnected do
         ProcessTransport; //обработка транспортных событий
     end;
 finally
   DoDisconnect;
 end;
end;

//обработка сообщений трансп.трэду
procedure TIPCThread.ProcessMessages;
var
 Msg: TMsg;
begin
 while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
   Dispatch(Msg.Message);
end;

//очистка списка объектов-событий ожидания рез-тов вызванных акций
procedure TIPCThread.ClearPendingQueue;
var
 i: Integer;
begin
 with FPendingQueue do
 begin
   for i := 0 to Count - 1 do
     CloseHandle(THandle(Items[i]));
   Clear;
 end;
end;

//очистка очереди передачи
procedure TIPCThread.ClearSendingQueue;
var
 Msg: TMsg;
 DataBlock: PDataBlock;
 List: TList;
 i: Integer;
begin
 while PeekMessage(Msg, 0, TM_SENDMSG, TM_SENDMSG, PM_REMOVE) do
   begin
     DataBlock := PDataBlock(Msg.wParam);
     with DataBlock.Header do
     if (Signature = CallSig) and  (WaitEvent <> 0) then
       CloseHandle(WaitEvent);
     FreeMem(DataBlock);
   end;
 List := FSendQueue.LockList;
 with List do
 try
   for i:= 0 to Count - 1 do
     begin
       DataBlock := Items[i];
       with DataBlock.Header do
       if (Signature = CallSig) and (WaitEvent <> 0) then
         CloseHandle(WaitEvent);
       FreeMem(DataBlock);
     end;
   Clear;
 finally
   FSendQueue.UnLockList;
 end;
end;

продолжение следует ..


 
Digitman ©   (2005-01-21 10:51) [4]

//очистка очереди приема
procedure TIPCThread.ClearReceivingQueue;
var
 List: TList;
 i: Integer;
 DataBlock: PDataBlock;
begin
 List := FRecvQueue.LockList;
 with List do
 try
   for i:= 0 to Count - 1 do
     begin
       DataBlock := Items[i];
       if DataBlock.Header.Signature = ResultSig then
         CloseHandle(DataBlock.Header.WaitEvent);
       FreeMem(DataBlock);
     end;
   Clear;
 finally
   FRecvQueue.UnLockList;
 end;
end;

//обработка трансп.событий
procedure TIPCThread.ProcessTransport;
var
 Msg: TMsg;
 DataBlock: PDataBlock;
 Size: DWord;
begin
 if not FPendingRead then
   begin
     FPendingRead := not ReadFile(hPipe, FInBuf^, MAX_MSG_SIZE, FBytesRead, @ovr) and (GetLastError = ERROR_IO_PENDING);
     if not FPendingRead then
       DoDisconnect
   end
 else
   case MsgWaitForMultipleObjects(2, FEvents, False, INFINITE, QS_SENDMESSAGE or QS_POSTMESSAGE) of
     WAIT_OBJECT_0     :  ProcessReadEvent;
     WAIT_OBJECT_0 + 1 :  ProcessWriteEvent;
     WAIT_OBJECT_0 + 2 :  ProcessMessages;
   end;
end;

//событие приема данных
procedure TIPCThread.ProcessReadEvent;
var
 ovl_Result: Boolean;
begin
 FPendingRead := False;
 ovl_Result := GetOverlappedResult(hPipe, ovr, FBytesRead, False);
 if ovl_Result and (FBytesRead = 0) then Exit;
 if not ovl_Result or (FBytesRead <> (DataBlockHdrSize + FInBuf.Header.ParamSize)) then
   DoDisconnect
 else
   case FInBuf.Header.Signature of
     CallSig:    ProcessIncomingCall;
     ResultSig:  ProcessIncomingResult;
   else
     DoDisconnect;
   end;
end;

//событие передачи данных
procedure TIPCThread.ProcessWriteEvent;
var
 DataBlock: PDataBlock;
 BlockSize: DWord;
 List: TList;
 ovl_Result: Boolean;
begin
 FPendingWrite := False;
 ovl_Result := GetOverlappedResult(hPipe, ovw, FBytesWritten, False);
 if ovl_Result and (FBytesWritten = 0) then Exit;
 if not ovl_Result or (FBytesWritten <> (DataBlockHdrSize + FOutBuf.Header.ParamSize)) then
   DoDisconnect
 else
   begin
     List := FSendQueue.LockList;
     with List do
     try
       if Count > 0 then
         begin
           DataBlock := Items[0];
           Delete(0);
         end
       else
         DataBlock := nil;
     finally
       FSendQueue.UnLockList;
     end;
     if Assigned(DataBlock) then
       begin
         BlockSize := DataBlockHdrSize + DataBlock.Header.ParamSize;
         CopyMemory(FOutBuf, DataBlock, BlockSize);
         FreeMem(DataBlock);
         if WriteFile(hPipe, FOutBuf^, BlockSize, FBytesWritten, @ovw) then Exit;
         FPendingWrite := GetLastError = ERROR_IO_PENDING;
         if not FPendingWrite then
           with FOutBuf.Header do
           begin
             if (Signature = CallSig) and (WaitEvent <> 0) then
               CloseHandle(WaitEvent);
             DoDisconnect;
           end;
       end;
   end;
end;

//обработка входящих запросов на исполнение акции
procedure TIPCThread.ProcessIncomingCall;
const
 ActionNotSupported: PChar = "Акция не поддерживается удаленной стороной";
var
 ResultDataBlock: PDataBlock;
 ResultDataBlockSize: DWord;
 excptmsg: String;
begin
 with FInBuf^ do
 try
   Header.ExceptionFlag := True;
   if not Assigned(FActionHandler)
   or not FActionHandler(Header.Action, @Params, Header.ParamSize, Params, Header.ParamSize) then
     begin
       StrCopy(@Params, ActionNotSupported);
       Header.ParamSize := StrLen(ActionNotSupported) + 1;
     end
   else
     Header.ExceptionFlag := False;
 except
   on e:Exception do
     begin
       excptmsg := "Исполнение акции вызвало исключительную ситуацию"#10 + e.ClassName + #10 + e.Message;
       StrCopy(@Params, PChar(excptmsg));
       Header.ParamSize := Length(excptmsg) + 1;
     end;
 end;
 ResultDataBlockSize :=  DataBlockHdrSize + FInBuf.Header.ParamSize;
 GetMem(ResultDataBlock, ResultDataBlockSize);
 with ResultDataBlock^ do
   begin
     Header.Action := FInBuf.Header.Action;
     Header.WaitEvent := FInBuf.Header.WaitEvent;
     Header.Signature := ResultSig;
     Header.ExceptionFlag := FInBuf.Header.ExceptionFlag;
     Header.ParamSize := FInBuf.Header.ParamSize;
     if Header.ParamSize > 0 then
       CopyMemory(@Params, @FInBuf.Params, FInBuf.Header.ParamSize);
     PostThreadMessage(ThreadId, TM_SENDMSG, Cardinal(ResultDataBlock), ResultDataBlockSize);
   end;
end;

продолжение следует ..


 
Digitman ©   (2005-01-21 10:51) [5]

//обработка входящих результатов исполнения акции
procedure TIPCThread.ProcessIncomingResult;
var
 List: TList;
 DataBlock: PDataBlock;
 BlockSize: DWord;
 idx: Integer;
begin
 BlockSize := DataBlockHdrSize + FInBuf.Header.ParamSize;
 List := FRecvQueue.LockList;
 with List do
 try
   GetMem(DataBlock, BlockSize);
   CopyMemory(DataBlock, FInBuf, BlockSize);
   idx := FPendingQueue.IndexOf(Pointer(DataBlock.Header.WaitEvent));
   if idx >= 0 then
     begin
       FPendingQueue.Delete(idx);
       if SetEvent(DataBlock.Header.WaitEvent) then
         Add(DataBlock)
       else
         FreeMem(DataBlock);
     end
   else
     FreeMem(DataBlock);
 finally
   FRecvQueue.UnLockList;
 end;
end;

//обработка сообщений на постановку инф.блока в очередь на передачу
procedure TIPCThread.MsgSendMsg(var Message: TMessage);
var
 List: TList;
 DataBlock: PDataBlock;
 BlockSize: DWord;
 idx: Integer;
begin
 DataBlock := PDataBlock(Message.wParam);
 if FPendingWrite then
   begin
     List := FSendQueue.LockList;
     try
       List.Add(DataBlock);
     finally
       FSendQueue.UnLockList;
     end;
   end
 else
   begin
     BlockSize := Message.lParam;
     CopyMemory(FOutBuf, DataBlock, BlockSize);
     FreeMem(DataBlock);
     with FOutBuf.Header do
     begin
       if (Signature = CallSig) and (WaitEvent <> 0) then
         idx := FPendingQueue.Add(Pointer(WaitEvent));
     end;
     if WriteFile(hPipe, FOutBuf^, BlockSize, FBytesWritten, @ovw) then
       Exit;
     FPendingWrite := GetLastError = ERROR_IO_PENDING;
     if not FPendingWrite then
       DoDisconnect;
   end;
end;

//команда на завершение трэда
procedure TIPCThread.MsgQuit(var Message: TMessage);
begin
 Terminate;
end;

//вызов акции на исполнение удаленной стороной

//Вх.аргументы :
// Action - код акции
// Params - параметры акции
// ParamSize - число байт параметров акции
//Вых.аргументы:
// ResultData - данные, предст. результаты исполненной акции
// ResultSize - число байт результата

//ф-ция возвращает True, если транзакция успешно завершена, False - иначе
//ф-ция так же возбуждает исключения ETransportError и EActionError

function TIPCThread.CallAction(Action: TAction; Params: Pointer;
 ParamSize: DWord; out ResultData: Pointer; out ResultSize: DWord): Boolean;
var
 DataBlock: PDataBlock;
 BlockSize: DWord;
 hEvent: THandle;
 List: TList;
 i: Integer;
begin
 Result := False;
 if not FConnected then Exit;
 BlockSize := DataBlockHdrSize + ParamSize;
 GetMem(DataBlock, BlockSize);
 hEvent := CreateEvent(nil, False, False, nil);
 with DataBlock^ do
 begin
   Header.Signature := CallSig;
   Header.Action := Action;
   Header.WaitEvent := hEvent;
   Header.ParamSize := ParamSize;
 end;
 CopyMemory(@DataBlock.Params, Params, ParamSize);
 if not PostThreadMessage(ThreadId, TM_SENDMSG, Cardinal(DataBlock), BlockSize) then
   begin
     CloseHandle(hEvent);
     FreeMem(DataBlock);
     raise ETransportError.Create("Соединение разорвано");
   end;
 DataBlock := nil;
 while True do
   case WaitForSingleObject(hEvent, 10) of
     WAIT_OBJECT_0:
     begin
       List := FRecvQueue.LockList;
       with List do
       try
         for i := 0 to Count - 1 do
           if PDataBlock(Items[i]).Header.WaitEvent = hEvent then
             begin
               DataBlock := Items[i];
               CloseHandle(DataBlock.Header.WaitEvent);
               Delete(i);
               Break;
             end;
           Break;
       finally
         FRecvQueue.UnLockList;
       end;
     end;
     WAIT_FAILED:  raise ETransportError.Create("Соединение разорвано");
     WAIT_TIMEOUT: Continue;
   end;

 if Assigned(DataBlock) then
   try
     if not DataBlock.Header.ExceptionFlag then
       begin
         ResultSize := DataBlock.Header.ParamSize;
         GetMem(ResultData, ResultSize);
         CopyMemory(ResultData, @DataBlock.Params, ResultSize);
         Result := True;
       end
     else
       raise EActionError.Create(StrPas(@DataBlock.Params));
   finally
     FreeMem(DataBlock);
   end;
end;

procedure TIPCThread.DoConnect;
begin
 if hWnd <> 0 then
   PostMessage(hWnd, TM_CONNECT, 0, 0);
end;

продолжение следует ..


 
Digitman ©   (2005-01-21 10:52) [6]

//разрыв трансп.соединения
procedure TIPCThread.DoDisconnect;
begin
 if not FConnected then Exit;
 if FPendingConnect or FPendingRead or FPendingWrite then
   CancelIO(hPipe);
 ClearSendingQueue;
 ClearReceivingQueue;
 ClearPendingQueue;
 FConnected := False;
end;

procedure TIPCThread.DoTerminate;
begin
end;

{ TIPCClientThread }

constructor TIPCClientThread.Create(WndHandle: THandle; ServerName, PipeName: String; ActionHandler: TActionHandler);
begin
 FServerName := Trim(ServerName);
 if FServerName = "" then
   FServerName := ".";
 inherited Create(WndHandle, PipeName, ActionHandler);
end;

procedure TIPCClientThread.DoConnect;
var
 FullPipeName: String;
begin
 FullPipeName := "\\" + FServerName + "\pipe\" + FPipeName;
 if WaitNamedPipe(PChar(FullPipeName), DEFAULT_TIMEOUT) then
   begin
     hPipe := CreateFile(PChar(FullPipeName),
             GENERIC_READ or GENERIC_WRITE, 0, nil,
                     OPEN_EXISTING,
                     FILE_FLAG_NO_BUFFERING
                     or FILE_FLAG_WRITE_THROUGH
                     or FILE_FLAG_OVERLAPPED,
                     0);
     FConnected := hPipe <> 0;
   end;
 if not FConnected and (GetLastError = ERROR_FILE_NOT_FOUND) then
   Sleep(100)
 else
   inherited;
end;

procedure TIPCClientThread.DoDisconnect;
begin
 inherited;
 CloseHandle(hPipe);
 hPipe := 0;
end;

{ TIPCServerThread }

procedure TIPCServerThread.DoConnect;
var
 ovc: TOverlapped;
 WaitResult: DWord;
begin
 if hPipe = 0 then
   begin
     hPipe := CreateNamedPipe(PChar("\\.\pipe\" + FPipeName),
                           PIPE_ACCESS_DUPLEX
                           or FILE_FLAG_WRITE_THROUGH
                           or FILE_FLAG_OVERLAPPED,
                           PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,
                           1, MAX_MSG_SIZE, MAX_MSG_SIZE, DEFAULT_TIMEOUT, nil);

     if hPipe = 0 then Exit;
   end;
 FillChar(ovc, SizeOf(ovc), 0);
 ovc.hEvent := CreateEvent(nil, False, False, nil);
 ConnectNamedPipe(hPipe, @ovc);
 FPendingConnect := GetLastError = ERROR_IO_PENDING;
 while not Terminated and FPendingConnect do
   begin
     WaitResult := MsgWaitForMultipleObjects(1, ovc.hEvent, False, INFINITE, QS_ALLINPUT);
     case  WaitResult of
       WAIT_OBJECT_0:
       begin
         FPendingConnect := False;
         FConnected := GetOverlappedResult(hPipe, ovc, FBytesRead, False);
         if FConnected then
          inherited;
       end;
       WAIT_OBJECT_0 + 1: ProcessMessages;
     end;
   end;
 CloseHandle(ovc.hEvent);
end;

procedure TIPCServerThread.DoDisconnect;
begin
 inherited;
 DisconnectNamedPipe(hPipe);
end;

end.

продолжение следует ..


 
Думкин ©   (2005-01-21 10:56) [7]

Вклинюсь.
> [6] Digitman ©   (21.01.05 10:52)
Такое лучше в статью оформить? Или тут она и будет жить?


 
Skyle ©   (2005-01-21 10:57) [8]

Тут две задачи.
1. Определить, что копия не первая
 CreateMutes + ERROR_ALREADY_EXISTS
2. Активировать имеющуюся копию
 SetForegroundWindow например


 
Fay ©   (2005-01-21 10:59) [9]

2 Fantom   (21.01.05 10:07)
На всякий случай

CreateNamedPipe

Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Unsupported.

З.Ы.
Я бы сделал через мьютекс и бродкастовое сообщение


 
REA   (2005-01-21 11:01) [10]

2Digitman: круто! Надо было еще COM-сервер и клиент добавить для объема.


 
Skyle ©   (2005-01-21 11:05) [11]

> Digitman ©   (21.01.05 10:49) [2] - [6]

А это чё за кампанента такая? Где скачать мона? А она кофя варит?


 
Leshiy ©   (2005-01-21 11:07) [12]

Самый наипростейший способ:

var hMainForm:HWND;
begin
 hMainForm:=FindWindow(nil,"Прога");
 if  hMainForm = 0 then
 begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
 end else MessageBox(Application.Handle,"Программа уже запущена","Внимание",MB_APPLMODAL or MB_ICONWARNING);
end.


 
Digitman ©   (2005-01-21 11:08) [13]

использование NP дает преимущество перед другими сист.объектами синхронизации - позволяет установившим соединение процессам легко и оч быстро обмениваться значительными по размеру блоками инф-ции

в дан.случае применить указанный код можно так :

1. Сразу после старта приложение первым делом создает экз-р класса TIPCClientThread и тут же в цикле ожидает установление св-ва TIPCClientThread.Connected в True .. цикл должен крутиться, скажем, не более 10..20 мс - этого времени достаточно для установления коммуникации с другим процессом того же приложения(если он существует)

2. Если через 10..20 TIPCClientThread.Connected по-прежнему, то экз-р TIPCClientThread уничтожается, а вместо него создается экз-р экз-р класса TIPCServerThread и приложение продолжает свою дальнейшую работу нужным образом

3. Если в ходе цикла было обнаружено TIPCClientThread.Connected = True, то это означает активность другого экз-ра приложения и активность в его процессе серв.части именованого канала .. с пом.метода CallAction(), приложение-клиент посылает приложению-серверу какие-либо данные, по получению которых приложение-сервер выполняет какие-либо действия (например, активизируется и получает фокус).. дождавшись возврата из CallAction() приложение-клиент немедленно завершает работу.


 
Fay ©   (2005-01-21 11:10) [14]

2 Leshiy ©   (21.01.05 11:07) [12]
Это самый плохой способ.


 
Digitman ©   (2005-01-21 11:13) [15]


> Думкин ©   (21.01.05 10:56) [7]


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


> REA   (21.01.05 11:01) [10]


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


 
MetalFan ©   (2005-01-21 11:16) [16]

Digitman ©   (21.01.05 10:49) [2]
в FAQ однозначно!
> З.Ы.
> Я бы сделал через мьютекс и бродкастовое сообщение

а я именно так и делал ) и намана работало!


 
Думкин ©   (2005-01-21 11:18) [17]

> [15] Digitman ©   (21.01.05 11:13)

Статью ИШ знаю. Это понятно. Но получилось так - новое решение старой задачи и объемное. Ведь втупую Copy/Paste произойдет и все.


 
Digitman ©   (2005-01-21 11:24) [18]


> Думкин ©   (21.01.05 11:18) [17]


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


 
Digitman ©   (2005-01-21 11:25) [19]


> Думкин ©   (21.01.05 11:18) [17]


конечно, можно было бы его (код этот) и в кладовку выложить в кач-ве еще одного примера по NP, да вот беда - не работает она ... и давно уже ...


 
Igor_thief   (2005-01-21 11:37) [20]

Думкин ©   (21.01.05 11:18) [17]
100% будет Copy/Paste. Ведь для решения этой задачи можно найти горздо менее объемные подходы и я уверен что они не буду намного хуже.
Я просто в шоке. Столько кода!


 
Leshiy ©   (2005-01-21 11:45) [21]

Fay © (21.01.05 11:10) [14]
я ни на что не претендую ;)


 
Digitman ©   (2005-01-21 11:47) [22]


> Igor_thief   (21.01.05 11:37) [20]


> Я просто в шоке. Столько кода!


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

к.г., "не нравится - не ешь")



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

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

Наверх




Память: 0.58 MB
Время: 0.028 c
4-1103274502
SiDoff
2004-12-17 12:08
2005.02.06
Как получить указатель на pop up ....


1-1106648348
Aleks
2005-01-25 13:19
2005.02.06
Как перехватить ошибку


1-1106402116
Islander
2005-01-22 16:55
2005.02.06
Как проверить, находится ли диск в режиме "Только чтение"?


3-1104398587
Georji
2004-12-30 12:23
2005.02.06
Извлечение месяца


1-1106514807
Raider
2005-01-24 00:13
2005.02.06
Как изменить цвет заголовка окна ?