Hallo in die Runde
,
ich muss die Gemeinde mal wieder mit einem Problem belästigen, das ich selbst weder verstehe noch ohne Hilfe weiter untersuchen kann.
Kurz zur Vorgeschichte: Ich stieß kürzlich auf ein sehr merkwürdiges Verhalten einer meiner Applikationen unter Win7 mit IE10 und IE11 (mit IE8 oder IE9 trat das nicht auf), das irgendwie so aussah, als ob die benutzte Named Pipe blockiert ist. Also hab ich das genauer untersucht und eine Testapplikation geschrieben und das Problem dort in ähnlicher Art nachstellen können.
Was ist das Problem?
Jedes Senden eines Strings durch den Client erhöht die Anzahl der Instanzen auf der Pipe, wie man mit
Sysinternals PipeList nachvollziehen kann, obwohl der Client direkt nach dem Senden des Strings und Flushen der Buffer die Verbindung mit Disconnect wieder trennt. Soweit sieht das erstmal nach keinem Problem aus, nur ist es so, dass sich der Pipe-Server in einer solchen Situation nicht mehr schließen lässt, weil dieser unendlich wartet, bis die Clients weg sind, obwohl das schon längst der Fall ist (Client-Prozess wurde beendet).
Lustigerweise tritt es mit der Testapplikation auch mit IE8 auf. Und es wird noch kurioser: es kommt nur zum Problem, wenn der Pipe-Server ein Manifest benutzt, das einerseits Laufzeit-Themes aktiviert und andererseits Kompatibilität mit Win7 beinhaltet; sobald eine der beiden Bedingungen nicht mehr zutrifft, ist das Problem verschwunden. Unter XP lässt sich das Problem gar nicht nachvollziehen; andere Windows-Versionen hab ich mit den Testprogrammen nicht getestet.
Aber kommen wir zum Wesentlichen: Ich benutze die Pipes-Komponente von Russell Libby, die man z.B. von
dieser Seite bekommt. Als Beispielprogramme sollen diese beiden dienen:
Server:
Delphi-Quellcode:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Pipes, StdCtrls;
type
TForm1 =
class(TForm)
Memo1: TMemo;
PipeServer1: TPipeServer;
Button1: TButton;
Edit1: TEdit;
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
procedure PipeServer1PipeMessage(Sender: TObject; Pipe: Cardinal;
Stream: TStream);
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{$R XP.res}
procedure TForm1.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
PipeServer1.Active:= False;
end;
procedure TForm1.PipeServer1PipeMessage(Sender: TObject; Pipe: Cardinal;
Stream: TStream);
var text:
string;
dummy: integer;
buffer:
array of char;
begin
SetLength(buffer, Stream.Size);
dummy:= Stream.
Read(buffer[0], Stream.Size);
text:=
String(PChar(buffer));
SetLength(buffer, 0);
Memo1.Lines.Add(text);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Add(IntToStr(PipeServer1.ClientCount) + '
clients connected');
PipeServer1.Active:= False;
PipeServer1.PipeName:= Edit1.Text;
PipeServer1.Active:= True;
end;
end.
Client:
Delphi-Quellcode:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Pipes, StdCtrls;
type
TForm1 =
class(TForm)
PipeClient1: TPipeClient;
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var myString:
string;
iLength: integer;
begin
if PipeClient1.Connect(5000)
then
begin
myString:= Edit1.Text;
iLength:=Length(myString);
// Send pipe message
if PipeClient1.
Write(mystring[1], iLength)
then
begin
// Flush the pipe buffers
PipeClient1.FlushPipeBuffers;
end;
PipeClient1.Disconnect;
end;
end;
end.
Kann das Problem jemand nachvollziehen? Hatte das jemand bereits? Wie kann ich weiter vorgehen?
MfG Dalai