{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvgMailSlots.PAS, released on 2003-01-15. The Initial Developer of the Original Code is Andrey V. Chudin, [chudin att yandex dott ru] Portions created by Andrey V. Chudin are Copyright (C) 2003 Andrey V. Chudin. All Rights Reserved. Contributor(s): Michael Beck [mbeck att bigfoot dott com]. Burov Dmitry, translation of russian text. You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net Known Issues: -----------------------------------------------------------------------------} // $Id: JvgMailSlots.pas 10612 2006-05-19 19:04:09Z jfudickar $ unit JvgMailSlots; {$I jvcl.inc} interface uses {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} Windows, Messages, SysUtils, Classes, Graphics, {$IFDEF USEJVCL} Controls, Forms, Dialogs, ExtCtrls, JvComponentBase; {$ELSE} Controls, Forms, Dialogs, ExtCtrls; {$ENDIF USEJVCL} type TOnNewMessage = procedure(Sender: TObject; MessageText: string) of object; {$IFDEF USEJVCL} TJvgMailSlotServer = class(TJvComponent) {$ELSE} TJvgMailSlotServer = class(TComponent) {$ENDIF USEJVCL} private FMailSlotName: string; FLastMessage: string; FOnNewMessage: TOnNewMessage; FTimer: TTimer; FHandle: THandle; FEnabled: Boolean; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Open; procedure Close; protected procedure Loaded; override; procedure OnTimer(Sender: TObject); published property MailSlotName: string read FMailSlotName write FMailSlotName; property OnNewMessage: TOnNewMessage read FOnNewMessage write FOnNewMessage; end; {$IFDEF USEJVCL} TJvgMailSlotClient = class(TJvComponent) {$ELSE} TJvgMailSlotClient = class(TComponent) {$ENDIF USEJVCL} private FMailSlotName: string; FServerName: string; FOnNewMessage: TOnNewMessage; public constructor Create(AOwner: TComponent); override; function Send(const Str: string): Boolean; protected procedure Loaded; override; procedure ErrorCatch(Sender: TObject; Exc: Exception); published property ServerName: string read FServerName write FServerName; property MailSlotName: string read FMailSlotName write FMailSlotName; property OnNewMessage: TOnNewMessage read FOnNewMessage write FOnNewMessage; end; {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvgMailSlots.pas $'; Revision: '$Revision: 10612 $'; Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} implementation uses {$IFDEF USEJVCL} JvResources, JvConsts, {$ENDIF USEJVCL} JvgUtils, JvgTypes; {$IFNDEF USEJVCL} resourcestring RsETJvgMailSlotServerErrorCreatingChan = 'TJvgMailSlotServer: Error creating channel!'; RsETJvgMailSlotServerErrorGatheringInf = 'TJvgMailSlotServer: Error gathering information!'; RsETJvgMailSlotServerErrorReadingMessa = 'TJvgMailSlotServer: Error reading message!'; {$ENDIF !USEJVCL} constructor TJvgMailSlotServer.Create(AOwner: TComponent); begin inherited Create(AOwner); FEnabled := True; FMailSlotName := 'MailSlot'; FTimer := TTimer.Create(nil); FTimer.Enabled := False; FTimer.OnTimer := OnTimer; end; destructor TJvgMailSlotServer.Destroy; begin FTimer.Free; // закрытие канала { Closing channel [translated] } Close; inherited Destroy; end; procedure TJvgMailSlotServer.Loaded; begin inherited Loaded; Open; end; procedure TJvgMailSlotServer.Open; begin // if not FEnabled then exit; // создание канала с именем MailSlotName - по этому имени к нему // будут обращаться клиенты { Creating channel named MailSlotName - that is the name clients will use to access the channel [translated] } FHandle := CreateMailSlot(PChar('\\.\mailslot\' + MailSlotName), 0, MAILSLOT_WAIT_FOREVER, nil); //FHandle:=CreateMailSlot('\\.\mailslot\MailSlot',0,MAILSLOT_WAIT_FOREVER,nil); if FHandle = INVALID_HANDLE_VALUE then raise Exception.CreateRes(@RsETJvgMailSlotServerErrorCreatingChan); FTimer.Enabled := True; end; procedure TJvgMailSlotServer.Close; begin if FHandle <> 0 then CloseHandle(FHandle); FHandle := 0; end; procedure TJvgMailSlotServer.OnTimer(Sender: TObject); var MsgSize: DWORD; MsgNumber: DWORD; Read: DWORD; MessageText: string; Buffer: PChar; begin // if not FEnabled then exit; MessageText := ''; // определение наличия сообщения в канале { Determining if there's message in channel [translated] } if not GetMailSlotInfo(FHandle, nil, MsgSize, @MsgNumber, nil) then raise Exception.CreateRes(@RsETJvgMailSlotServerErrorGatheringInf); if MsgSize <> MAILSLOT_NO_MESSAGE then begin // (rom) deactivated annoying // Beep; // Allocate memory for the message GetMem(Buffer, MsgSize); try // чтение сообщения из канала и добавление в текст протокола { Reading message from channel and adding it to text of log } if ReadFile(FHandle, Buffer, MsgSize, Read, nil) then MessageText := Buffer else raise Exception.CreateRes(@RsETJvgMailSlotServerErrorReadingMessa); finally FreeMem(Buffer); end; end; if (MessageText <> '') and Assigned(FOnNewMessage) then FOnNewMessage(Self, MessageText); FLastMessage := MessageText; end; //------------------------------------------------------------------------------ constructor TJvgMailSlotClient.Create(AOwner: TComponent); begin inherited Create(AOwner); FMailSlotName := 'MailSlot'; FServerName := ''; end; procedure TJvgMailSlotClient.Loaded; begin inherited Loaded; // (rom) this is not a good idea Application.OnException := ErrorCatch; end; procedure TJvgMailSlotClient.ErrorCatch(Sender: TObject; Exc: Exception); var UserName: PChar; Size: DWORD; begin // получение имени пользователя { Querying user name [translated] } // First query with a buffer too small, to get the required size Size := 0; UserName := nil; GetUserName(UserName, Size); // then allocate some memory for the user name GetMem(UserName, Size); try GetUserName(UserName, Size); Send('/' + UserName + '/' + FormatDateTime('hh:mm', Time) + '/' + Exc.Message); finally FreeMem(UserName); end; // вывод сообщения об ошибке пользователю { Showing message about error to user [translated] } Application.ShowException(Exc); end; function TJvgMailSlotClient.Send(const Str: string): Boolean; var Buffer: PChar; FHandle: THandle; Written: DWORD; begin // открытие канала : MyServer - имя сервера // (\\.\\mailslot\xxx - монитор работает на этом же ПК) // xxx - имя канала { Opening channel: MyServer - name of server (\\.\\mailslot\xxx - monitor is working on the same PC xxx is the name of channel [translated] } if FServerName = '' then FServerName := '.\'; FHandle := CreateFile(PChar('\\' + FServerName + '\mailslot\' + FMailSlotName), GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); if FHandle <> INVALID_HANDLE_VALUE then begin GetMem(Buffer, Length(Str)+1); try StrCopy(Buffer, PChar(Str)); // передача текста ошибки (запись в канал и закрытие канала) { Transmitting text of error (putting into channel and closing channel) [translated] } WriteFile(FHandle, Buffer, Length(Str) + 1, Written, nil); finally CloseHandle(FHandle); FreeMem(Buffer); end; end; Result := FHandle <> INVALID_HANDLE_VALUE; end; {$IFDEF USEJVCL} {$IFDEF UNITVERSIONING} initialization RegisterUnitVersion(HInstance, UnitVersioning); finalization UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} {$ENDIF USEJVCL} end.