AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint
Thema durchsuchen
Ansicht
Themen-Optionen

Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

Ein Thema von Hobbycoder · begonnen am 15. Nov 2018 · letzter Beitrag vom 17. Nov 2018
Antwort Antwort
Hobbycoder

Registriert seit: 22. Feb 2017
1.016 Beiträge
 
#1

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 15. Nov 2018, 23:50
ilInformation Ist eine TImageList. Die wird ja in in bmp kopiert, welches nach dem finally auch wieder freigegeben wird.
FastMM und ReportMemoryLeaksOnShutdown habe ich schon mit mäßigem Erfolg ausprobiert. Leider liefern die mir auch (nicht wenige) MemoryLeaks von UniDAC, zu denen ich aber keine Sources habe. Früher hatte ich mal Zeos verwendet. uniDAC verwende ich im dem Projekt das erste mal.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.228 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 07:35
Leider liefern die mir auch (nicht wenige) MemoryLeaks von UniDAC, zu denen ich aber keine Sources habe.
Wir haben auch Unidac und nutzen auch FastMM und uns ist bisher kein MemoryLeak von Unidac (Oracle + MySQL) aufgefallen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.016 Beiträge
 
#3

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 08:17
Leider liefern die mir auch (nicht wenige) MemoryLeaks von UniDAC, zu denen ich aber keine Sources habe.
Wir haben auch Unidac und nutzen auch FastMM und uns ist bisher kein MemoryLeak von Unidac (Oracle + MySQL) aufgefallen.
Gut. Aber wenn ich meine Anwendung kurz starte, dann bekomme ich eine ganz Liste (ReportMemoryLeaksOnShutDown, FastMM muss ich noch mal ausprobieren für mehr Details).
Und da mach ich dann noch nicht mal viel. Die Connection wird geöffnet, es werden 2-3 Query abgefragt, 2 Threads laufen durch. Das wars. Da sind ein paar Einträge, über deren Klassennamen kann meine Klassen erkennen. Das meiste stammt von UniDAC.
Ich will aber nicht ausschließen, dass es mein Fehler ist. Ich arbeite grundsätzlich über Klassen, in denen die Datenbankabfragen laufen. Alles ist über Try..Finally abgesichert, dass jedes object auch wieder freigegeben wird (kann höchstens sein, dass ich es mal an einer Stelle übersehen habe. Aber soweit ich das bisher gesichtet habe, sollte das nicht der Fall sein).

Die Connection halte in einer globalen Klasse, die beim Programmstart erzeugt wird und übergebe die halt immer an die Querys.
Hier mal ein Beispiel für eine Query-Klasse:
Delphi-Quellcode:
procedure TZeitenList.LoadFromDB(Con: TUniConnection; Betriebguid: TGUID);
var
  q: TUniQuery;
  z: TZeiten;
begin
  q:=TUniQuery.Create(nil);
  try
    self.Clear;
    q.Connection:=Con;
    q.SQL.Text:='Select * from zeiten where betriebguid=:betriebguid order by ID';
    q.Params.ParamValues['betriebguid']:=Betriebguid.ToString;
    q.Active:=True;
    while not q.Eof do
    begin
      z:=TZeiten.Create;
      z.ID:=q.FieldByName('ID').AsInteger;
      z.guid:=StringToGUID(q.FieldByName('guid').AsString);
      z.betriebguid:=StringToGUID(q.FieldByName('betriebguid').AsString);
      z.zeitstr:=q.FieldByName('zeitstr').AsString;
      self.Add(z);
      q.Next;
    end;
    q.active:=False
  finally
    q.Free;
  end;
end;
Ungefähr so sehen alle Abfragen aus.
Und meine globale Klasse sieht so aus:
Delphi-Quellcode:
unit Data.tpdbaccess;

interface

uses Classes, System.SysUtils, Data.DB, DBAccess, Uni, Tools.globalTypes, MySQLUniProvider, Local.ConnectionList, Tools.globalConst,
  MemData;

type
  TOnConnect=procedure(Verindungsname: string) of object;
  TOnDisconnect=procedure of object;
  TOnSendDBUpdateMessage=procedure(Msg: string; Append: Boolean) of object;

  TDBAccess=class
  private
    class var FCon: TUniConnection;
    class var FConnectionList: TConnectionList;
    class var FVerbindungsname: string;
    class var FOnConnect: TOnConnect;
    class var FOnDisconnect: TOnDisconnect;
    class var FOnSendDBUpdatemessage: TOnSendDBUpdateMessage;
    class constructor Create; overload;
    class procedure SetConnectionList(const Value: TConnectionList); static;
    class procedure SetVerbindungsname(const Value: string); static;
    class procedure DoConnect(Verbindungsname: string);
    class procedure DoDisconnect;
    class procedure AfterConnect(Sender: TObject);
    class procedure BeforeDisconnect(Sender: TObject);
    class procedure ConnectionLost(Sender: TObject; Component: TComponent; ConnLoseCouse: TConnLostCause; RetryMode: TRetryMode);
  public
    constructor Create(ConnectionItem: TConnectionItem); overload;
    destructor Destroy; override;
    class function open: Boolean; overload;
    class function open(ConnectionItem: TConnectionItem): Boolean; overload;
    class procedure Close;
    class property ConnectionList: TConnectionList read FConnectionList write SetConnectionList;
    class property Verbindungsname: string read FVerbindungsname write SetVerbindungsname;
    class procedure DoSendDBUpdateMessage(Msg: string; Append: Boolean = False);
    class property OnConnect: TOnConnect read FOnConnect write FOnConnect;
    class property OnDisconnect: TOnDisconnect read FOnDisconnect write FOnDisconnect;
    class property OnSendDBUpdateMessage: TOnSendDBUpdateMessage read FOnSendDBUpdatemessage write FOnSendDBUpdatemessage;
    class procedure GetTables(Strings: TStrings);
    class function ExecuteStatement(Statement: string): Variant; overload;
    class function ExecuteStatement(Statement: string; Params: array of Variant): Variant; overload;
    class function GetNewGUID: TGUID;
    class property Con: TUniConnection read FCon;
  end;

const
  NullGUID='{00000000-0000-0000-0000-000000000000}';

implementation

{ TDBAccess }

class constructor TDBAccess.Create;
begin
  inherited;
  FCon:=TUniConnection.Create(nil);
  FCon.AfterConnect:=AfterConnect;
  FCon.BeforeDisconnect:=BeforeDisconnect;
// FCon.OnConnectionLost:=ConnectionLost;
  FConnectionList:=TConnectionList.Create(true);
end;

class procedure TDBAccess.AfterConnect(Sender: TObject);
begin
  DoConnect(FVerbindungsname);
end;

class procedure TDBAccess.BeforeDisconnect(Sender: TObject);
begin
  DoDisconnect;
end;

class procedure TDBAccess.Close;
begin
  FCon.Disconnect;
  FVerbindungsname:='';
end;

class procedure TDBAccess.ConnectionLost(Sender: TObject; Component: TComponent;
  ConnLoseCouse: TConnLostCause; RetryMode: TRetryMode);
begin
  RetryMode:=rmReconnect;
end;

constructor TDBAccess.Create(ConnectionItem: TConnectionItem);
begin
  self.Create;
  FCon.ProviderName:=TTPConnectionTypeStr[integer(ConnectionItem.ConnectionType)];
  FCon.Server:=ConnectionItem.Hostname;
  FCon.Port:=ConnectionItem.Port;
  FCon.Database:=ConnectionItem.Database;
  FCon.Username:=ConnectionItem.UserName;
  FCon.Password:=ConnectionItem.Password;
  FVerbindungsname:=ConnectionItem.ConnectionName;
  open;
end;

destructor TDBAccess.Destroy;
begin
  if FCon.Connected then FCon.Disconnect;
  FConnectionList.Free;
  FCon.Free;
  inherited;
end;

class procedure TDBAccess.DoConnect(Verbindungsname: string);
begin
  if Assigned(FOnConnect) then
    FOnConnect(Verbindungsname);
end;

class procedure TDBAccess.DoDisconnect;
begin
  if Assigned(FOnDisconnect) then
    FOnDisconnect;
end;

class procedure TDBAccess.DoSendDBUpdateMessage(Msg: string; Append: Boolean);
begin
  if Assigned(FOnSendDBUpdatemessage) then
    FOnSendDBUpdatemessage(Msg, Append);
end;

class function TDBAccess.ExecuteStatement(Statement: string;
  Params: array of Variant): Variant;
begin
  Result:=FCon.ExecSQL(Statement, Params);
end;

class function TDBAccess.ExecuteStatement(Statement: string): Variant;
begin
  Result:=FCon.ExecSQL(Statement);
end;

class function TDBAccess.GetNewGUID: TGUID;
begin
  createGUID(Result);
end;

class procedure TDBAccess.GetTables(Strings: TStrings);
begin
  FCon.GetTableNames(Strings);
end;

class function TDBAccess.open: Boolean;
begin
  try
    Try
      FCon.Connect;
    Except
      FVerbindungsname:='';
    End;
  finally
    Result:=FCon.Connected;
  end;
end;

class function TDBAccess.open(ConnectionItem: TConnectionItem): Boolean;
begin
  FCon.ProviderName:=TTPConnectionTypeStr[integer(ConnectionItem.ConnectionType)];
  FCon.Server:=ConnectionItem.Hostname;
  FCon.Port:=ConnectionItem.Port;
  FCon.Database:=ConnectionItem.Database;
  FCon.Username:=ConnectionItem.UserName;
  FCon.Password:=ConnectionItem.Password;
  FVerbindungsname:=ConnectionItem.ConnectionName;
  Result:=open;
end;

class procedure TDBAccess.SetConnectionList(const Value: TConnectionList);
begin
  FConnectionList := Value;
end;

class procedure TDBAccess.SetVerbindungsname(const Value: string);
begin
  FVerbindungsname := Value;
end;

end.
Diese wird im Create der Mainform erzeugt und in deren Destroy auch wieder freigegeben.
(Die Threads erzeugen sich natürlich eine eigene TUniConnection).

Bisher hat das auch recht gut funktioniert. Leider habe ich nicht von Anfang an mit ReportMemoryLeaksOnShutDown gearbeitet. Die größe des Projekt macht es jetzt natürlich umso schwieriger.
Angehängte Grafiken
Dateityp: png ReportMemoryLeaksOnShutDown.png (205,1 KB, 17x aufgerufen)
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
985 Beiträge
 
Delphi 6 Professional
 
#4

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 09:45
Hmm..


Die Connection halte in einer globalen Klasse, die beim Programmstart erzeugt wird und übergebe die halt immer an die Querys.
..
Und meine globale Klasse sieht so aus:
..
Diese wird im Create der Mainform erzeugt und in deren Destroy auch wieder freigegeben.
(Die Threads erzeugen sich natürlich eine eigene TUniConnection).

Wieso ist deine TDBAccess eigentlich komplett 'class xxx'.

Nimm doch mal hier das 'class' vor allen Funktionen weg und mach Dir ein 'echtes' Objecte im Create vom MainForm...

Vielleicht bringt dass das Speichermanagment etwas durcheinander und somit auch FMM..

(Nur so eine Idee von jemandem der 'class var .. ' nicht mag )
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.490 Beiträge
 
Delphi 12 Athens
 
#5

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 08:33
In vstTermineAfterCellPaint wird eine bmp-Variable verwendet, die nicht lokal deklariert ist.
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.277 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 08:42
Hallo,
zumindestens wird ja was angezeigt, aber leider keine Bitmaps.
Die "Ausrede", Projekt ist zu gross, lasse ich nicht gelten

Du kannst es ja abspecken (schrittweise ausklammern).

FastMM4 würde dir die Zeile zeigen, wo die jeweilige Klasse erzeugt wird, die nicht freigegeben wird.
Was schon mal komisch ist, dass er 2 Connections anzeigt.
Kann es sein, das Du deine globale Connection beim Programmende nicht freigibst?

Breakpoint auf destructor TDBAccess.Destroy; setzen und nachschauen
Heiko

Geändert von hoika (16. Nov 2018 um 09:27 Uhr)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 09:08
Die zwei Connections wundern mich auch etwas. Das sollte eigentlich schon die Ursache für die ganzen nachfolgenden Memory Leaks sein.


Aber zurück zur eigentlichen Frage:

Kompiliert denn der SourceCode so überhaupt wie du ihn hier geschrieben hast? Mir fehlt zu dem zweiten try ein except .

Delphi-Quellcode:
      11: begin
          if t.RTFTextList.Items(ttArbeiten)<>Nil then
          begin
            top:=Trunc((CellRect.Height-t.RTFTextList.Items(ttArbeiten).pic.Bitmap.Height)/2);
            BitBlt(TargetCanvas.Handle, CellRect.Left, CellRect.Top+top, CellRect.Width, CellRect.Height, t.RTFTextList.Items(ttArbeiten).pic.Bitmap.Canvas.Handle, 0, 0, SRCAND); //<---- Manchmal aber auch hier
          end;
          bmp:=TBitmap.Create;
          bmp.Height:=ilInformation.Height;
          bmp.Width:=0;
          try
          try
            if t.TB then AddSymbol(SymTB, '', bmp);
            if t.TD then AddSymbol(SymTD, '', bmp);
            if t.FD then AddSymbol(SymFD, '', bmp);
            if t.HB then AddSymbol(SymHB, '', bmp);
            if t.PlainTextList.Items(ttBemerkung)<>nil then
              if t.PlainTextList.Items(ttBemerkung).text<>'then
                AddSymbol(SymBemerkung, '', bmp);
            if t.REgeschrieben then AddSymbol(SymRE, '', bmp);
            if t.dmsAuftragNr<>'then AddSymbol(SymAB, '', bmp);
            top:=Trunc((CellRect.Height-bmp.Height)/2);
            BitBlt(TargetCanvas.Handle, CellRect.Left+CellRect.Width-bmp.Width, CellRect.Top+top, bmp.Width, bmp.Height, bmp.Canvas.Handle, 0, 0, SRCCOPY);
          finally
            bmp.Free;
          end;
        end;


Dinge die du mal noch ausprobieren kannst:

Dann würde ich an deiner Stelle mal Teile der Paint Procedure auskommentieren und schauen, ob der Fehler immer noch auftritt.
Erkennst du den Fehler nur daran, dass die CPU Auslastung nach oben geht? Oder läuft dein RAM irgendwann voll? Kannst du mal testen was passiert, wenn du die AddSymbol Procedure direkt integrierst und das Kopieren des Bitmaps in den var Parameter auslässt und stattdessen direkt auf das Canvas malst?
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.374 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 09:46
Was schon mal komisch ist, dass er 2 Connections anzeigt.
Ich habe mir mal die Doku zu Klassen-Konstruktoren angesehen.
Wenn die korrekt ist, wundert mich das nicht.

Klassen-Konstruktoren werden bei Bedarf automatisch ausgeführt.
Aber in dieser Klasse wird der Klassen-Konstruktor nochmal manuell aufgerufen. Die Folge sind dann offensichtlich zwei Connections.

Ich habe mit Klassen-Konstruktoren noch nicht gearbeitet und komme nur durch die Delphi-Doku auf diese Idee.
http://docwiki.embarcadero.com/RADSt...nkonstruktoren
Peter
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.016 Beiträge
 
#9

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 17. Nov 2018, 14:15
Ich bin jetzt ein kleines Stück weiter. Habe mal alles deaktiviert, alle Threads, so dass am Ende nur der Mainthread über bleibt. Sprich die DB wird geöffnet und bei Programmende wieder geschlossen, ohne dass DB-Abfragen dazwischen laufen. Ergebnis: Keine MemoryLeaks.

Jetzt fange ich an, alles Stück für Stück wieder zu aktivieren, und teste jedes Mal ob und wo ein MemoryLeak auftritt.
Ich bin auch gleich fündig geworden in folgende Methode:

Delphi-Quellcode:
procedure TStamminfos.LoadFromDBByRev(Con: TUniConnection; Betriebguid,
  Refguid: TGUID; Ref: string);
var
  q: TUniQuery;
begin
  q:=TUniQuery.Create(nil);
  try
    q.Connection:=Con;
    if not Con.Connected then exit;
    q.SQL.Text:='Select * from stamminfos where betriebguid=:betriebguid and (Refguid=:refguid or ref=:ref)';
    q.Params.ParamValues['betriebguid']:=Betriebguid.ToString;
    q.Params.ParamValues['Refguid']:=Refguid.ToString;
    q.Params.ParamValues['Ref']:=Ref;
    q.Active:=True;
    if q.RecordCount>0 then
    begin
      Self.ID:=q.FieldByName('ID').AsInteger;
      Self.guid:=StringToGUID(q.FieldByName('guid').AsString);
      Self.betriebguid:=StringToGUID(q.FieldByName('betriebguid').AsString);
      Self.Refguid:=StringToGUID(q.FieldByName('Refguid').AsString);
      Self.Ref:=q.FieldByName('Ref').AsString;
      Self.RTFText.Position:=0;
      (q.FieldByName('RTFText') as TBlobField).SaveToStream(Self.RTFText); //<<--Hier muss der Übeltäter liefen.
      Self.RTFText.Position:=0;
      Self.Text:=q.FieldByName('Text').AsString;
      Self.Level:=TInfosLevel(q.FieldByName('Level').AsInteger);
    end;
    q.active:=False
  finally
    q.Free;
  end;
end;
Kommentiere ich die Zeile SaveToStream aus, so habe ich kein MemoryLeak. Lass ich sie mit ausführe, habe ich ein MemoryLeak.

Ist das Auslesen eines BlobFields denn so falsch? (Self.RTFText ist TMemoryStream, welches auch korrekt erzeugt und freigegeben wird).
Gibt es noch eine andere (bessere) Möglichkeit den Inhalt von BlobFiels auszulesen? Ich kenn nur die.

PS: Die o.g. Methode läuft in einem Thread, der seine eigene Connection hat.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.016 Beiträge
 
#10

AW: Systemressourcen erschöpft beim VirtualStringTree.AfterCellPaint

  Alt 16. Nov 2018, 09:18
In vstTermineAfterCellPaint wird eine bmp-Variable verwendet, die nicht lokal deklariert ist.
Oh, ja, sorry, ich hatte die Funktion leicht gekürzt (einige Case rausgeschissen). und damit es nicht verwirrt auch die Var-Declarationen, die mit dem Fehler nicht zu tun haben können.
Tatsächlich wird die bmp lokal deklariert. (Hab das oben korrigiert)

Hallo,
zumindestens wird ja was angezeigt, aber leider keine Bitmaps.
Doch. Der Fehler tritt ja nicht immer auf. Die Bitmap sehe ich im VST. Und ich kann auch nicht sagen, dass mir da was fehlt, wenn ich im MADExcept auf Continue Klicke. Zur Zeit habe ich das Gefühl, dass mehr Zeile den Fehler eher auftreten lassen. Das ist aber nur gefühlt. Ich bin gerade dabei, das ganze mal so zu ändern, dass ich nur mit 2-3 Zeilen arbeiten kann.

Die "Ausrede", Projekt ist zu gross, lasse ich nicht gelten

Du kannst es ja abspecken (schrittweise ausklammern).
Darauf wird wohl hinauslaufen. Wahrscheinlich muss ich noch back to the roots, und mir das mit der Connection / Globalen Klasse noch mal genau anschauen. Ich glaube fast das da im Constructor/Destructor irgendwas im argen liegt.

FastMM4 würde dir die Zeile zeigen, wo die jeweilige Klasse erzeugt wird, die nicht freigegeben wird.
Was schon mal komisch ist, dass er 2 Connections anzeigt.
Kann es sein, das Du deine globale Connection beim Programmende nicht freigibst?
FastMM werde ich auch noch mal ausprobieren.
Also im Mainthread verwende ich definitiv nur 1 Connection. Ich muss mal die Threads deaktivieren. Möglicherweise stammt die zweite Connection ja von einem der Threads (die eigentlich alle vor Programmende korrekt beendet werden).

Die zwei Connections wundern mich auch etwas. Das sollte eigentlich schon die Ursache für die ganzen nachfolgenden Memory Leaks sein.


Aber zurück zur eigentlichen Frage:

Kompiliert denn der SourceCode so überhaupt wie du ihn hier geschrieben hast? Mir fehlt zu dem zweiten try ein except .
Das war ein Fehler beim zusammen kopieren. Es gibt nur ein Try. Ich hatte die Methode wie oben bereits erwähnt etwas eingekürzt, dass die restlichen Case-Fälle mit dem Fehler nichts zu tun haben können. Zwar wird auch da gezeichnet, aber nur in dieser Spalte tritt der Fehler auf. Das hatte ich durch Auskommentieren bereits getestet.

Dinge die du mal noch ausprobieren kannst:

Dann würde ich an deiner Stelle mal Teile der Paint Procedure auskommentieren und schauen, ob der Fehler immer noch auftritt.
Erkennst du den Fehler nur daran, dass die CPU Auslastung nach oben geht? Oder läuft dein RAM irgendwann voll? Kannst du mal testen was passiert, wenn du die AddSymbol Procedure direkt integrierst und das Kopieren des Bitmaps in den var Parameter auslässt und stattdessen direkt auf das Canvas malst?
Auskommentieren habe ich bereits gemacht und somit auf diese Spalte reduziert. CPU-Auslastung ist normal 3-5 % und auch Ram wird nicht soviel belegt, dass es jetzt irgendwie auffällig wäre. Aber ich werde mal die AddSymbol-Methode ganz auskommentieren und mal schauen was sich verändert.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz