AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!
Thema durchsuchen
Ansicht
Themen-Optionen

1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

Ein Thema von RSE · begonnen am 4. Mär 2013 · letzter Beitrag vom 6. Mär 2013
Antwort Antwort
Seite 1 von 2  1 2      
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#1

1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 16:00
Hallo,

unser Programm darf nur 1x geöffnet werden. Dazu verwenden wir ein benanntes Mutex-Objekt (Win32-API-Call CreateMutex). Für den Fall, dass ich von GetLastError = ERROR_ALREADY_EXISTS zurückbekomme, möchte ich gerne die erste Instanz des Programms nach vorne holen - unabhängig davon, was da gerade für Fenster offen sind. Allerdings scheitere ich schon daran, die Prozess-ID oder irgendetwas anderes von dem Prozess, der das Mutex-Objekt besitzt (also die erste Instanz des Programms), herauszubekommen. Der Grund ist einfach meine Unkenntnis der Win-API. Wahrscheinlich verwende ich nicht die richtigen Suchbegriffe.

Ich möchte nicht nach einem Fenster mit einem bestimmten Caption suchen, dann würde ich es lieber lassen. Allerdings bin ich mir sicher, dass es durchaus elegantere Wege gibt als diesen.
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#2

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 16:04
Für den Fall, dass ich von GetLastError = ERROR_ALREADY_EXISTS zurückbekomme, möchte ich gerne die erste Instanz des Programms nach vorne holen - unabhängig davon, was da gerade für Fenster offen sind.
Die Jedi Code Library enthält eine hilfreiche Klasse (TJclAppInstances), die diese Funktion implementiert. Als Basis für eigenen Code ist diese Klasse eventuell einen Blick wert (Open Source).
Michael Justin
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#3

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 16:45
Fenster kann man nicht nur anhand der Caption, sondern auch anhand des Klassennamens suchen, das ist schon deutlich eindeutiger.

Ansonsten: ne Pipe? Darüber können ggfls. auch gleich Parameter übermittelt werden (etwa wenn die zweite Instanz mit nem Dateinamen zum Öffnen als Parameter gestartet wird - soll dann ja die erste Instanz diese Datei wahrscheinlich öffnen), und die erste Instanz kann sich einfach selbst wieder in den Vordergrund holen.
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#4

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 17:31
@mjustin:
TJclAppInstances war prinzipiell eine gute Idee zum Nachforsten, aber ich steige da überhaupt nicht durch. Da wird irgendetwas mit File Mapping gemacht - kenne ich bisher nicht, scheint aber eine gemeinsame Datei vorauszusetzen, die von mehreren Prozessen gleichzeitig benutzt wird und in der dann Informationen gesammelt werden. Das Ganze erscheint mir zu aufwendig für meinen Einsatzzweck.

@CCRDude:
Von Pipes habe ich bisher auch nichts gewusst, aber folgendes scheint ein einfacher und zielführender Weg zu sein:
Bei Programmstart versuche ich eine Pipe mit dem Parameter FILE_FLAG_FIRST_PIPE_INSTANCE zu erstellen. Gelingt das, so ist es die erste Programminstanz. Schlägt das fehl, so verbinde ich zu der bestehenden Pipe und informiere die erste Instanz, dass sie sich nach vorn bringen soll (Application.BringToFront) und beende die aktuelle (zweite) Instanz.

Ich werde mich morgen mit dem Handling der Pipes genauer auseinandersetzen, habe jetzt nur überflogen, was Pipes sind Wenn dabei für mich unlösbare Probleme auftreten, melde ich mich nochmal, ansonsten: Danke für die Lösung!
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.445 Beiträge
 
Delphi 12 Athens
 
#5

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 17:40
Der Ansatz, daß sich die erste Instanz selbst in den Vordergrund bringt, wird in den meisten Fällen schief gehen. Windows erlaubt es nämlich i.A. nicht, daß ein Prozess sich selbst in den Vordergrund drängelt (da könnte ja jeder kommen). Dies ist unter anderem aber dem Prozess erlaubt, der gerade gestartet wurde - also der zweiten Instanz. Ich empfehle daher, das so zu implementieren, daß doch die zweite Instanz die erste in den Vordergrund holt.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#6

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 5. Mär 2013, 12:27
Also das mit den Pipes habe ich jetzt implementiert. Selbst ohne Kommunikation durch die Pipes kann ich folgendes erreichen:
  • Nur die Erste Instanz startet normal - nur dann ist CreateNamedPipe mit FILE_FLAG_FIRST_PIPE_INSTANCE erfolgreich - Jede weitere Instanz erkennt, dass bereits eine andere Instanz läuft und kann darauf reagieren
  • Eine zweite Instanz kann die erste Instanz folgendermaßen ermitteln: Sie verbindet sich mit CreateFile mit den Parametern GENERIC_READ und OPEN_EXISTING auf die Pipe und erhält das Pipe-Handle. Damit kann sie mittels GetNamedPipeServerProcessId die Prozess-ID der ersten Instanz ermitteln
  • Eine dritte Instanz braucht keine Meldung mehr ausgeben, dass bereits eine Instanz läuft, da das bereits die zweite Instanz tut. Dieser Fall könnte z.B. eintreten, wenn bereits eine Instanz hinter anderen Fenstern verborgen läuft und das Programm ungeschickt gleich mehrfach geöffnet wird. Dieser Fall wird als Nebeneffekt erkannt, wenn das Verbinden auf die bestehende Pipe nicht gelingt (weil Instanz 2 bereits verbunden ist). Das Programm kann in diesem Fall ohne weitere Handlungen beendet werden.
Offen bleibt also jetzt nur noch das In-den-Vordergrund-bringen der ersten Instanz durch die zweite Instanz. Dazu benötige ich offenbar ein Fenster-Handle der ersten Instanz, welches ich dann an SetForegroundWindow übergeben kann. Gefunden habe ich bei einer ersten Suche die GetGUIThreadInfo Funktion (benötigt die Thread-ID, welche man mittels der Prozess-ID ermitteln können sollte), welche mir eine GUITHREADINFO structure mit dem Handle des im Thread aktiven Windows liefert. Ist das ein guter Ansatz, oder gibt es bessere/bevorzugenswertere?

Ich sehe folgende Probleme incl. Lösungen bei meinem Ansatz:
  • Der Zielprozess hat wahrscheinlich mehrere Threads. In diesem Fall würde ich alle Threads durchsuchen, bis ich einen finde, der ein aktives Fenster besitzt und dieses in den Vordergrund bringen.
  • Zwischen der Ermittlung des aktiven Fensters und dem Aufruf/Umsetzung von SetForegroundWindow könnte das Fenster wieder verschwunden sein (Aufruf von Hide), falls es sich dummerweise gerade um mein "Bitte warten Sie, bis die lange Operation beendet wurde"-Fenster handelt. Ich nehme an, dass SetForegroundWindow in diesem Fall einen entsprechenden Rückgabewert liefert, damit ich den Vorgang auf einem neuen aktiven Fenster wiederholen kann.

So, jetzt habe ich euch erstmal mit aktuellen Infos versorgt und werde mittagessen gehen. Wenn bis danach keine Einwände gegen das Vorgehen gepostet wurden, werde ich die Umsetzung dann angehen

Mahlzeit!
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#7

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 5. Mär 2013, 15:39
Fast geschafft... Fast! Hier ist mein Code:
Delphi-Quellcode:
var
  PID: ULONG; // Process-ID von 1. Instanz
  HPipe: THandle = INVALID_HANDLE_VALUE; // wird für Server (= 1. Instanz, CreateNamedPipe) und für Client (= 2. Instanz, CreateFile) verwendet
  HSnap: THandle = INVALID_HANDLE_VALUE;
  ThreadEntry: TThreadEntry32; // aus Unit TlHelp32
  GUIThreadInfo: TGUIThreadInfo;

function GetNamedPipeServerProcessId(hNamedPipe: THandle;
  out ServerProcessId: ULONG): BOOL; stdcall;
  external kernel32 name 'GetNamedPipeServerProcessId';

initialization

  HPipe := CreateNamedPipe(PipeName,
    PIPE_ACCESS_OUTBOUND or FILE_FLAG_FIRST_PIPE_INSTANCE,
    PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT, 1, 4, 4, 0, nil); // erste Pipe-Instanz erstellen
  if HPipe = INVALID_HANDLE_VALUE then
  begin // wenn Pipe bereits besteht
    HPipe := CreateFile(PipeName, GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); // auf Pipe verbinden
    if HPipe <> INVALID_HANDLE_VALUE then
    begin
      if GetNamedPipeServerProcessId(HPipe, PID) then // Prozess-ID des Pipe-Servers erfragen (= 1. Instanz)
      begin
        FillChar(ThreadEntry, SizeOf(ThreadEntry), 0);
        ThreadEntry.dwSize := SizeOf(ThreadEntry);
        HSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PID); // Schnappschuss aller Threads erstellen
        if (HSnap <> INVALID_HANDLE_VALUE) and
           Thread32First(HSnap, ThreadEntry) then
          repeat // Threads durchlaufen
            if ThreadEntry.th32OwnerProcessID = PID then
            begin // wenn Thread zu Prozess der 1. Instanz gehört
              FillChar(GUIThreadInfo, SizeOf(GUIThreadInfo), 0);
              GUIThreadInfo.cbSize := SizeOf(GUIThreadInfo);
              // bis hierhin klappt alles wunderbar
              if GetGUIThreadInfo(ThreadEntry.th32ThreadID, GUIThreadInfo) then // GUIThreadInfo beschaffen
              begin
                if (GUIThreadInfo.hwndActive > 0) then
                begin // wenn aktives Fenster gesetzt ist - ist immer null - Warum? #####
                  SetForegroundWindow(GUIThreadInfo.hwndActive); // Fenster in Vordergrund holen
                  Break;
                end;
              end
              else // beim 3. Durchlauf/Thread kommt ERROR_INVALID_PARAMETER - Warum? #####
                ShowMessage('GetGUIThreadInfo is unsuccessful: ' + IntToStr(GetLastError));
            end;
          until not Thread32Next(HSnap, ThreadEntry); // nächsten Thread untersuchen
      end;
    end;
    // wenn Verbindung zur Pipe erfolgreich, Meldung anzeigen -> aktuelle Instanz ist die 2.
    // wenn Verbindung zur Pipe nicht erfolgreich, dann Meldung anzeigen wenn GetLastError <> ERROR_PIPE_BUSY -> keine Meldung für die 3. Instanz, die gleichzeitig geöffnet ist
    if (HPipe <> INVALID_HANDLE_VALUE) or (GetLastError <> ERROR_PIPE_BUSY) then
      ShowMessage('Das Programm läuft bereits');
    Halt;
  end;

finalization

  // Pipe-Handle freigeben - Server und Client
  if (HPipe <> INVALID_HANDLE_VALUE) and CloseHandle(HPipe) then
    HPipe := INVALID_HANDLE_VALUE; // Falls es sich um Client/2. Instanz handelt, dann ist die Pipe trotzdem weiterhin besetzt (weitere/spätere Verbindungsversuche verursachen ERROR_PIPE_BUSY) - Warum? #####

end.
Ich habe mein Bestes gegeben, Google und MSDN gelesen, aber an den 3 Punkten oben, die mit ##### gekennzeichnet sind, komme ich nicht weiter.
  • Punkt1: In keinem der untersuchten Threads gibt es ein aktives Fenster. Der Thread, in dem die 1. Instanz zum Testzeitpunkt definitiv ein Fenster anzeigt, ist dabei der zuerst durchsuchte Thread - hier müsste also ein Handle eingetragen sein, wenn ich MSDN richtig verstanden habe. Zitat: "A handle to the active window within the thread." - offenbar aber doch nur für den fall, dass dieses Fenster gerade das eine im System aktive Fenster ist, das den Eingabefokus besitzt. Was gibt es für Alternativen, um an ein sichtbares oder minimiertes Fenster des Prozesses zu kommen?
  • Punkt2: Nach meinem Wissen gibt es 2 Threads in meinem Programm: Den Delphi-Hauptthread und einen von mir erstellten LogThread. Weitere Threads könnten z.B. im Hintergrund von irgendwelchen (DB)Komponenten erstellt worden sein. Warum aber plötzlich die Parameter nicht mehr stimmen sollen, ist mir schleierhaft.
  • Punkt3: Ich wäre davon ausgegangen, dass die Pipe wieder frei ist, wenn die Verbindung durch das Freigeben des Handles beendet wurde. Was muss ich tun, um die Pipe wieder freizumachen?
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."

Geändert von RSE ( 5. Mär 2013 um 15:47 Uhr)
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#8

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 5. Mär 2013, 18:02
Um die offenen Fragen aus meinem letzten Post zu umgehen, habe ich nun umgebaut:
Delphi-Quellcode:
var
  PID: ULONG; // Process-ID von 1. Instanz
  HPipe: THandle = INVALID_HANDLE_VALUE; // wird für Server (= 1. Instanz, CreateNamedPipe) und für Client (= 2. Instanz, CreateFile) verwendet

function GetNamedPipeServerProcessId(hNamedPipe: THandle;
  out ServerProcessId: ULONG): BOOL; stdcall;
  external kernel32 name 'GetNamedPipeServerProcessId';

function EnumWindowsProcCallback(HWnd: THandle; PID: LPARAM): BOOL; stdcall;
var
  WinPID: DWORD;
begin
  GetWindowThreadProcessId(HWnd, WinPID);
  Result := WinPID <> (PULONG(PID))^;
  if not Result then
    SetForegroundWindow(HWnd);
end;

initialization

  HPipe := CreateNamedPipe(PipeName,
    PIPE_ACCESS_OUTBOUND or FILE_FLAG_FIRST_PIPE_INSTANCE,
    PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT, 1, 4, 4, 0, nil); // erste Pipe-Instanz erstellen
  if HPipe = INVALID_HANDLE_VALUE then
  begin // wenn Pipe bereits besteht
    HPipe := CreateFile(PipeName, GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); // auf Pipe verbinden
    if HPipe <> INVALID_HANDLE_VALUE then
    begin
      if GetNamedPipeServerProcessId(HPipe, PID) then // Prozess-ID des Pipe-Servers erfragen (= 1. Instanz)
        EnumWindows(@EnumWindowsProcCallback, LPARAM(@PID)); // Fenster durchforsten
    end;
    // wenn Verbindung zur Pipe erfolgreich, Meldung anzeigen -> aktuelle Instanz ist die 2.
    // wenn Verbindung zur Pipe nicht erfolgreich, dann Meldung anzeigen wenn GetLastError <> ERROR_PIPE_BUSY -> keine Meldung für die 3. Instanz, die gleichzeitig geöffnet ist
    if (HPipe <> INVALID_HANDLE_VALUE) or (GetLastError <> ERROR_PIPE_BUSY) then
      MessageBox(0, 'Das Programm läuft bereits', '',
        MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST);
    Halt;
  end;

finalization

  // Pipe-Handle freigeben - Server und Client
  if (HPipe <> INVALID_HANDLE_VALUE) and CloseHandle(HPipe) then
    HPipe := INVALID_HANDLE_VALUE; // Falls es sich um Client/2. Instanz handelt, dann ist die Pipe trotzdem weiterhin besetzt (weitere/spätere Verbindungsversuche verursachen ERROR_PIPE_BUSY) - Warum? #####

end.
Dadurch erübrigen sich 2 der 3 Punkte, aber einer bleibt bestehen:
  • Punkt3: Ich wäre davon ausgegangen, dass die Pipe wieder frei ist, wenn die Verbindung durch das Freigeben des Handles beendet wurde. Was muss ich tun, um die Pipe wieder freizumachen?
An diesem Punkt bitte ich um eure Hilfe, es fällt mir dazu nichts weiter ein.
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
ASM

Registriert seit: 16. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#9

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 5. Mär 2013, 18:49
Anstelle mit Hilfe von Pipes lässt sich das Problem auch grundsätzlich anders lösen:
Man kann in den diversen Formfenstern des Programms individuelle Hooks der jeweiligen WndProc setzen. Dann ist es möglich, dort die beim Start der 2.Instanz abgesetzte HWND_BROADCAST-Message abzufangen und geeignet zu behandeln:

// in der MainForm:
Delphi-Quellcode:
Interface

const
  // z.B. mit GUI-Code zweifelsfrei individualisieren
  UniqueAppTitle = 'MyApp#21218E21-EF54-45D9-AAA0-8F4E7455D5AE';
var
  UniqueAppMsg: DWord;
  
Implementation

{...}
  
initialization
  UniqueAppMsg := RegisterWindowMessage(pChar(UniqueAppTitle));
end.
// in jeder einzelnen Form-Unit (hier exemplarisch "FormX"):
Delphi-Quellcode:
Implementation

uses Mainunit; // unit der Mainform

var
  OriginalWndProc: Pointer;
  CurrentFormHandle: hWnd;

function FormX_HookedWndProc(FormHandle: hWnd; MessageID: LongInt;
  ParamW: LongInt; ParamL: LongInt): LongInt stdcall;
begin
  if MessageID = UniqueAppMsg then
  begin
    SendMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
    SetForegroundWindow(Application.Handle);
    SendMessage(CurrentFormHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
    Result := 0;
  end
  else
   Result := CallWindowProc(OriginalWndProc, FormHandle, MessageID, ParamW, ParamL);
end;

procedure TFormX.FormCreate(Sender: TObject);
begin
  CurrentFormHandle:=FormX.Handle;
  OriginalWndProc := Pointer(SetWindowLong(CurrentFormHandle, GWL_WNDPROC,
    LongInt(@FormX_HookedWndProc)));
end;

procedure TFormX.FormDestroy(Sender: TObject);
begin
  SetWindowLong(CurrentFormHandle, GWL_WNDPROC, LongInt(OriginalWndProc));
end;
// im Projektfile:
Delphi-Quellcode:
Uses Windows, ...;
var
  Mutex: THandle;

begin
  Mutex := CreateMutex(nil, True, UniqueAppTitle);
  if (Mutex = 0) or (GetLastError = ERROR_ALREADY_EXISTS) then
  begin
    SendMessage(HWND_BROADCAST, UniqueAppMsg, 0, 0);
    Halt(0);
  end
  else
  try
    Application.Initialize;
    {...}
  finally
    if Mutex <> 0 then CloseHandle(Mutex);
  end;
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#10

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 6. Mär 2013, 08:04
@ASM: Uwe Raabe hat dazu oben etwas wichtiges gesagt: evtl. kann sich ein Programm gar nicht selber in den Vordergrund holen (ich mache das auch nicht so, dachte nur, dass das noch praktischer wäre, deswegen schrieb ich das als Vorschlag).

Aus eigener Erfahrung möchte ich noch ein paar wichtige Sachen ergänzen:

Fast User Switching und Terminal Services / Remote-Desktop-Zugriff ermöglichen es, dass theoretisch verschiedene Benutzer (oder verschiedene Instanzen desselben Benutzers ein Programm auf demselben Rechner nutzen wollen. Wäre blöd, wenn Benutzer A ein Dokument öffnen will und es bei Benutzer B aufgeht, weil der die erste Instanz offen hat.

Deswegen reicht ein UniqueAppTitle wie von ASM beschrieben auf keinen Fall aus! Session-ID und Username gehören da mit rein. Am besten noch den Namen des Desktops. Zusätzlich könnte der Prefix Local\ helfen, um das Mutex definitiv innerhalb der Session zu erzeugen (kommt halt drauf an, wofür man es will). Steht alles in der Hilfe zu MSDN-Library durchsuchenCreateMutex

Gleiches gilt natürlich auch für den Namen der Pipe - sicherstellen, dass da keine Übergriffe stattfinden können!

Negativbeispiel: Adobe Reader (über mehrere Versionen, nicht sicher ob noch in aktueller). Admin A startet den Adobe Reader, um ein PDF zu lesen. DAU D, ein eingeschränkter Benutzeraccount, surft im Netz und öffnet im Browser ein PDF. Das Adobe Reader-Plugin ist so "intelligent", sich an den von A gestarteten Reader anzuflanschen. Jetzt hat D über die Öffnen-Funktion vollen Administrator-Zugriff.


Und wenn das Programm u.U. auch elevated sein kann, muss man planen, wie man damit umgeht, weil der BROADCAST u.U. nicht in beide Richtungen funktioniert (Programm, die elevated sind, sollen ja eben nicht per Window Messages von nicht elevateten Programmen "gesteuert" werden können).
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 18:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz