1
0
mirror of synced 2024-11-09 14:49:15 +00:00

Changed: named pipes are now prefixed with "X2Log.", to accomodate:

Added: TX2LogNamedPipeClient.ActiveServers class function
Fixed: renamed madExceptHandler unit applied to test application
This commit is contained in:
Mark van Renswoude 2014-08-18 12:07:33 +00:00
parent 3b635b3454
commit 4efc4000ff
6 changed files with 235 additions and 9 deletions

View File

@ -10,7 +10,7 @@ uses
X2Log.Observer.Event in '..\X2Log.Observer.Event.pas', X2Log.Observer.Event in '..\X2Log.Observer.Event.pas',
X2Log.Observer.Custom in '..\X2Log.Observer.Custom.pas', X2Log.Observer.Custom in '..\X2Log.Observer.Custom.pas',
X2Log.Exception.Default in '..\X2Log.Exception.Default.pas', X2Log.Exception.Default in '..\X2Log.Exception.Default.pas',
X2Log.Exception.madExcept in '..\X2Log.Exception.madExcept.pas', X2Log.Exception.madExceptHandler in '..\X2Log.Exception.madExceptHandler.pas',
X2Log.Observer.LogFile in '..\X2Log.Observer.LogFile.pas', X2Log.Observer.LogFile in '..\X2Log.Observer.LogFile.pas',
X2Log.Constants in '..\X2Log.Constants.pas', X2Log.Constants in '..\X2Log.Constants.pas',
X2Log.Observer.NamedPipe in '..\X2Log.Observer.NamedPipe.pas', X2Log.Observer.NamedPipe in '..\X2Log.Observer.NamedPipe.pas',

View File

@ -179,7 +179,7 @@
<DCCReference Include="..\X2Log.Observer.Event.pas"/> <DCCReference Include="..\X2Log.Observer.Event.pas"/>
<DCCReference Include="..\X2Log.Observer.Custom.pas"/> <DCCReference Include="..\X2Log.Observer.Custom.pas"/>
<DCCReference Include="..\X2Log.Exception.Default.pas"/> <DCCReference Include="..\X2Log.Exception.Default.pas"/>
<DCCReference Include="..\X2Log.Exception.madExcept.pas"/> <DCCReference Include="..\X2Log.Exception.madExceptHandler.pas"/>
<DCCReference Include="..\X2Log.Observer.LogFile.pas"/> <DCCReference Include="..\X2Log.Observer.LogFile.pas"/>
<DCCReference Include="..\X2Log.Constants.pas"/> <DCCReference Include="..\X2Log.Constants.pas"/>
<DCCReference Include="..\X2Log.Observer.NamedPipe.pas"/> <DCCReference Include="..\X2Log.Observer.NamedPipe.pas"/>

View File

@ -130,13 +130,25 @@ object MainForm: TMainForm
end end
object tsNamedPipe: TTabSheet object tsNamedPipe: TTabSheet
Caption = 'Named Pipe' Caption = 'Named Pipe'
ExplicitLeft = 16
ExplicitTop = 33
DesignSize = (
587
299)
object lblPipeName: TLabel object lblPipeName: TLabel
Left = 12 Left = 8
Top = 64 Top = 64
Width = 53 Width = 53
Height = 13 Height = 13
Caption = 'Pipe name:' Caption = 'Pipe name:'
end end
object lblNamedPipeServers: TLabel
Left = 8
Top = 108
Width = 73
Height = 13
Caption = 'Active servers:'
end
object btnNamedPipeStart: TButton object btnNamedPipeStart: TButton
Left = 8 Left = 8
Top = 8 Top = 8
@ -163,6 +175,25 @@ object MainForm: TMainForm
TabOrder = 2 TabOrder = 2
Text = 'X2LogTest' Text = 'X2LogTest'
end end
object btnNamedPipeRefresh: TButton
Left = 502
Top = 96
Width = 75
Height = 25
Anchors = [akTop, akRight]
Caption = '&Refresh'
TabOrder = 3
OnClick = btnNamedPipeRefreshClick
end
object lbNamedPipeServers: TListBox
Left = 8
Top = 132
Width = 569
Height = 157
Anchors = [akLeft, akTop, akRight, akBottom]
ItemHeight = 13
TabOrder = 4
end
end end
end end
object pnlButtons: TPanel object pnlButtons: TPanel

View File

@ -7,9 +7,10 @@ uses
Vcl.Controls, Vcl.Controls,
Vcl.ExtCtrls, Vcl.ExtCtrls,
Vcl.Forms, Vcl.Forms,
Vcl.ImgList,
Vcl.StdCtrls, Vcl.StdCtrls,
X2Log.Intf, Vcl.ImgList; X2Log.Intf;
type type
@ -55,6 +56,9 @@ type
pnlObservers: TPanel; pnlObservers: TPanel;
bvlObservers: TBevel; bvlObservers: TBevel;
btnGraphic: TButton; btnGraphic: TButton;
lblNamedPipeServers: TLabel;
btnNamedPipeRefresh: TButton;
lbNamedPipeServers: TListBox;
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject); procedure FormDestroy(Sender: TObject);
@ -72,6 +76,7 @@ type
procedure btnNamedPipeStopClick(Sender: TObject); procedure btnNamedPipeStopClick(Sender: TObject);
procedure btnBinaryRawByteStringClick(Sender: TObject); procedure btnBinaryRawByteStringClick(Sender: TObject);
procedure btnGraphicClick(Sender: TObject); procedure btnGraphicClick(Sender: TObject);
procedure btnNamedPipeRefreshClick(Sender: TObject);
private private
FLog: IX2Log; FLog: IX2Log;
FEventObserver: IX2LogObserver; FEventObserver: IX2LogObserver;
@ -89,10 +94,11 @@ uses
Winapi.Windows, Winapi.Windows,
X2Log, X2Log,
X2Log.Client.NamedPipe,
X2Log.Constants, X2Log.Constants,
X2Log.Details.Default, X2Log.Details.Default,
X2Log.Details.Intf, X2Log.Details.Intf,
X2Log.Exception.madExcept, X2Log.Exception.madExceptHandler,
X2Log.Observer.Event, X2Log.Observer.Event,
X2Log.Observer.LogFile, X2Log.Observer.LogFile,
X2Log.Observer.MonitorForm, X2Log.Observer.MonitorForm,
@ -314,4 +320,22 @@ begin
end; end;
end; end;
procedure TMainForm.btnNamedPipeRefreshClick(Sender: TObject);
var
server: TX2LogNamedPipeServerInfo;
begin
lbNamedPipeServers.Items.BeginUpdate;
try
lbNamedPipeServers.Items.Clear;
for server in TX2LogNamedPipeClient.ActiveServers do
lbNamedPipeServers.Items.Add(server.DisplayName + ' (' + server.PipeName + ')');
finally
lbNamedPipeServers.Items.EndUpdate;
end;
end;
end. end.

View File

@ -10,6 +10,18 @@ uses
type type
TX2LogNamedPipeServerInfo = class(TObject)
private
FDisplayName: string;
FPipeName: string;
public
constructor Create(const APipeName: string);
property DisplayName: string read FDisplayName;
property PipeName: string read FPipeName;
end;
TX2LogNamedPipeClient = class(TX2LogBaseClient, IX2LogBase) TX2LogNamedPipeClient = class(TX2LogBaseClient, IX2LogBase)
private private
FWorkerThread: TThread; FWorkerThread: TThread;
@ -18,12 +30,16 @@ type
public public
constructor Create(const APipeName: string); constructor Create(const APipeName: string);
destructor Destroy; override; destructor Destroy; override;
class function ActiveServers: IEnumerable<TX2LogNamedPipeServerInfo>;
end; end;
implementation implementation
uses uses
System.SyncObjs, System.SyncObjs,
System.StrUtils,
System.SysUtils, System.SysUtils,
System.Types, System.Types,
Winapi.Windows, Winapi.Windows,
@ -69,8 +85,50 @@ type
end; end;
TX2LogNamedPipeServerInfoList = class(TInterfacedObject, IEnumerable<TX2LogNamedPipeServerInfo>, IEnumerable)
private
FServers: TList<TX2LogNamedPipeServerInfo>;
protected
{ IEnumerable }
function GetEnumerator: IEnumerator;
function IEnumerable<TX2LogNamedPipeServerInfo>.GetEnumerator = GetGenericEnumerator;
function GetGenericEnumerator: IEnumerator<TX2LogNamedPipeServerInfo>;
procedure EnumerateServers;
property Servers: TList<TX2LogNamedPipeServerInfo> read FServers;
public
constructor Create;
destructor Destroy; override;
end;
TX2LogNamedPipeServerInfoEnumerator = class(TInterfacedObject, IEnumerator<TX2LogNamedPipeServerInfo>, IEnumerator)
private
FList: TList<TX2LogNamedPipeServerInfo>;
FEnumerator: TEnumerator<TX2LogNamedPipeServerInfo>;
protected
{ IEnumerator }
function GetCurrent: TObject;
function MoveNext: Boolean;
procedure Reset;
function IEnumerator<TX2LogNamedPipeServerInfo>.GetCurrent = GetGenericCurrent;
function GetGenericCurrent: TX2LogNamedPipeServerInfo;
property List: TList<TX2LogNamedPipeServerInfo> read FList;
property Enumerator: TEnumerator<TX2LogNamedPipeServerInfo> read FEnumerator;
public
constructor Create(AList: TList<TX2LogNamedPipeServerInfo>);
destructor Destroy; override;
end;
const const
PipeNamePrefix = '\\.\pipe\'; PipePrefix = '\\.\pipe\';
PipeNamePrefix = 'X2Log.';
TimeoutBusyPipe = 5000; TimeoutBusyPipe = 5000;
TimeoutNoPipe = 1000; TimeoutNoPipe = 1000;
@ -95,6 +153,12 @@ begin
end; end;
class function TX2LogNamedPipeClient.ActiveServers: IEnumerable<TX2LogNamedPipeServerInfo>;
begin
Result := TX2LogNamedPipeServerInfoList.Create;
end;
{ TX2LogNamedPipeClientWorkerThread } { TX2LogNamedPipeClientWorkerThread }
constructor TX2LogNamedPipeClientWorkerThread.Create(AClient: TX2LogNamedPipeClient; const APipeName: string); constructor TX2LogNamedPipeClientWorkerThread.Create(AClient: TX2LogNamedPipeClient; const APipeName: string);
begin begin
@ -152,7 +216,7 @@ var
begin begin
while not Terminated do while not Terminated do
begin begin
FPipeHandle := CreateFile(PChar(PipeNamePrefix + PipeName), GENERIC_READ or FILE_WRITE_ATTRIBUTES, FPipeHandle := CreateFile(PChar(PipePrefix + PipeNamePrefix + PipeName), GENERIC_READ or FILE_WRITE_ATTRIBUTES,
0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); 0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if PipeHandle = INVALID_HANDLE_VALUE then if PipeHandle = INVALID_HANDLE_VALUE then
@ -162,7 +226,7 @@ begin
case lastError of case lastError of
ERROR_PIPE_BUSY: ERROR_PIPE_BUSY:
{ Pipe exists but is connecting to another client, wait for a new slot } { Pipe exists but is connecting to another client, wait for a new slot }
WaitNamedPipe(PChar(PipeNamePrefix + PipeName), TimeoutBusyPipe); WaitNamedPipe(PChar(PipePrefix + PipeNamePrefix + PipeName), TimeoutBusyPipe);
ERROR_FILE_NOT_FOUND: ERROR_FILE_NOT_FOUND:
{ Pipe does not exist, try again later } { Pipe does not exist, try again later }
@ -345,4 +409,108 @@ begin
end; end;
end; end;
{ TX2LogNamedPipeServerInfoList }
constructor TX2LogNamedPipeServerInfoList.Create;
begin
inherited Create;
FServers := TObjectList<TX2LogNamedPipeServerInfo>.Create(True);
EnumerateServers;
end;
destructor TX2LogNamedPipeServerInfoList.Destroy;
begin
FreeAndNil(FServers);
inherited Destroy;
end;
procedure TX2LogNamedPipeServerInfoList.EnumerateServers;
var
searchRec: TSearchRec;
begin
if System.SysUtils.FindFirst(PipePrefix + '*', faAnyFile, searchRec) = 0 then
try
repeat
if StartsText(PipeNamePrefix, searchRec.Name) then
Servers.Add(TX2LogNamedPipeServerInfo.Create(searchRec.Name));
until System.SysUtils.FindNext(searchRec) <> 0;
finally
System.SysUtils.FindClose(searchRec);
end;
end;
function TX2LogNamedPipeServerInfoList.GetEnumerator: IEnumerator;
begin
Result := GetGenericEnumerator;
end;
function TX2LogNamedPipeServerInfoList.GetGenericEnumerator: IEnumerator<TX2LogNamedPipeServerInfo>;
begin
Result := TX2LogNamedPipeServerInfoEnumerator.Create(Servers);
end;
{ TX2LogNamedPipeServerInfoEnumerator }
constructor TX2LogNamedPipeServerInfoEnumerator.Create(AList: TList<TX2LogNamedPipeServerInfo>);
begin
inherited Create;
FList := AList;
Reset;
end;
destructor TX2LogNamedPipeServerInfoEnumerator.Destroy;
begin
FreeAndNil(FEnumerator);
inherited Destroy;
end;
function TX2LogNamedPipeServerInfoEnumerator.GetCurrent: TObject;
begin
Result := GetGenericCurrent;
end;
function TX2LogNamedPipeServerInfoEnumerator.MoveNext: Boolean;
begin
Result := Enumerator.MoveNext;
end;
procedure TX2LogNamedPipeServerInfoEnumerator.Reset;
begin
FreeAndNil(FEnumerator);
FEnumerator := List.GetEnumerator;
end;
function TX2LogNamedPipeServerInfoEnumerator.GetGenericCurrent: TX2LogNamedPipeServerInfo;
begin
Result := Enumerator.Current;
end;
{ TX2LogNamedPipeServerInfo }
constructor TX2LogNamedPipeServerInfo.Create(const APipeName: string);
begin
inherited Create;
FPipeName := APipeName;
if StartsText(PipeNamePrefix, APipeName) then
FDisplayName := Copy(APipeName, Succ(Length(PipeNamePrefix)), MaxInt)
else
FDisplayName := APipeName;
end;
end. end.

View File

@ -101,6 +101,9 @@ const
SDDL_REVISION_1 = 1; SDDL_REVISION_1 = 1;
PipeNamePrefix = '\\.\pipe\X2Log.';
{ TX2LogNamedPipeObserver } { TX2LogNamedPipeObserver }
constructor TX2LogNamedPipeObserver.Create(const APipeName: string; ALogLevels: TX2LogLevels); constructor TX2LogNamedPipeObserver.Create(const APipeName: string; ALogLevels: TX2LogLevels);
@ -442,7 +445,7 @@ begin
nil) then nil) then
begin begin
try try
pipe := CreateNamedPipe(PChar('\\.\pipe\' + PipeName), PIPE_ACCESS_OUTBOUND or FILE_FLAG_OVERLAPPED, pipe := CreateNamedPipe(PChar(PipeNamePrefix + PipeName), PIPE_ACCESS_OUTBOUND or FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
BufferSize, BufferSize, DefaultTimeout, @security); BufferSize, BufferSize, DefaultTimeout, @security);
finally finally