![]() |
Welches Programm ist wo geöffnet?
Hallo Leute...
Folgende Problemstellung: Wir stellen Delphi-Programme auf einem Server für mehrere Clienten bereit die diese von ihren Rechnern aufrufen. Problem ist jetzt, wenn ich ein Update einspielen will, also Änderungen am Programm vorgenommen habe muss ich diese zentrale .exe ersetzen was aber bekannterweise nur möglich ist wenn diese nirgends mehr geöffnet ist. Und da ich nicht weiß wer es grade offen hat wird das immer ein wahnsinns Aufwand ein Programm zu ändern. Die einzig sinnvolle Lösung die mir bisher eingefallen ist, ist das ich irgendwo an einem zentralen Punkt hinschreibe wer welches Programm grade geöffnet hat. (Falls es hier schon andere Ansatze gibt, nur zu ;)) Nur wie setze ich das am besten um? Wäre eine Möglichkeit einfach im "OnCreate" und "OnClose" eine Datei zu schreiben bzw. zu löschen? Und würde das auch funktionieren wenn das Programm z.B. über den Taskmanager abgeschossen wird? Mir kommt diese Lösung nicht optimal vor :/ |
AW: Welches Programm ist wo geöffnet?
Computerverwaltung > System > Freigegebene Ordner > Geöffnete Dateien. ?
Wenn ein Programm abgeschossen wird, oder wenn die Netzwerkverbindung weg ist, dann kann diese Datei natürlich nicht von den Programmen gelöscht werden. :roll: (du müßtest dann lokal versuchen die Dateien zu löschen) Tipp: Geöffnete Dateien (EXE/DLL) kann man dennoch umbenennen und an deren Stellen die neuen Dateien hinkopieren. Bei den geöffneten Programmen bleiben aber dennoch die alten Dateiversionen geladen. (gibt eventuell Probleme, wenn ein aktives Programm, nach dem Austausch, eine der neuen Dateien laden will ... vorallem bei BPLs knallt es dann im Programm gerne mal) Du könntest du aber auf dem Server eine Serveranwendung laufen lassen, wo sich alle Programme anmelden. Da siehst du, wer wo da ist (du kannst die Programme ja nach Programmverzeichnis, Computer-/Benutzernamen und IP befragen) und den Programmen dauch sagen "fahr runter oder starte dich (z.B. in x Minuten) neu". (Letzteres zusammen mit einer kleinen Hilfsanwendung, oder mit Hilfe der Windows-Aufgabenplanung) |
AW: Welches Programm ist wo geöffnet?
Na wenn das Delphi Programme sind, würde Ich diese Programme um eine Verbindung zu einer Server-App erweitern.
Die Server-App zeigt dir an, welche PC-Namen Verbunden sind und mit welcher Anwendung. Dann kannst du vielleicht noch über diese App eine Message auf den Delphi - Programmen ausgeben. ("Bitte schließen Sie die Anwendung" oder direkt killen :) (nein mach das besser nicht) In der ServerApp kannst du vielleicht noch einstellen das bestimmte Programme direkt beim öffnen wieder geschlossen werden sollen, solange ein öffnen verboten ist. (vllt mit Nachricht an den Benutzer) Naja und wenn dann von einem Delphi Programm keine Verbindungen mehr ausgehen kannst du das Update machen. Meine Gedanken dazu... |
AW: Welches Programm ist wo geöffnet?
Zitat:
Zitat:
Wie können denn 2 Delphi-Programm untereinander kommunizieren um sich beispielsweise an- oder abzumelden? Oder wie kann ich Nachrichten aus der Serveranwednung an die Clients senden? Müsste das alles über "dritte Dateien" laufen die das eine Programm schreibt und das andere permanent überwacht und ausliest? Zitat:
Nur fehlen mir dazu ein paar Grundlagen was die Kommunikation zwischen Applikationen angeht. Ich denke ich werd mich dazu mal etwas belesen. Über direkte Hilfe, vielleicht mit verweisen auf entsprechende Seiten wo ich Informationen bekomme, würd ich mich aber auch nicht beklagen ;) |
AW: Welches Programm ist wo geöffnet?
Zitat:
|
AW: Welches Programm ist wo geöffnet?
Aktuell geht das für alle Dateien, welche nicht per "Dateihandle" (CreateFile, also AssignFile, TFileStream und Co.) geöffnet sind.
EXE/DLL/BPL werden quasi per LoadLibrary als MMF geladen und dort läßt es sich umbenennen. Abgesehn davon, wenn sich Fremdprogramme ala Virenscanner einmischen, oder wenn ein OS glaubt es sei intelligent. z.B. wenn man das Programm "nochmals" läd und das OS denkt "ahh, da ist die Datei ja schon geladen, also verwende ich sie jetzt gleich nochmal", anstatt sich die aktuelle Dateiversion zu holen, aber so intelligent ist Windows nicht. :stupid: Aber wenn's geht: Ja, dann laufen die alten Programme weiter und beim Neustart werden dann die neuen Dateiversionen verwendet. Aktuell = WinNT-Reihe (mindestens WinXP, Win7, Win8, Server2003, Server2008, Server2011 und Server2012) |
AW: Welches Programm ist wo geöffnet?
Grad eben konnte ich sie unbennen (das Programm war definitiv in Benutzung) und jetzt gehts nicht mehr :? Wieder die Meldung das das Programm in Benutzung sei.
Also wäre so eine Serveranwednung wohl doch auch von Nöten. |
AW: Welches Programm ist wo geöffnet?
Man kann auch die Dateiverbindungen, jene über die Netzwerkfreigaben, in der genannten Systemsteuerung trennen.
Man darf sich dann nur nicht wundern, wenn die geöffneten Programme komisch reagieren sollten ... das ist so, als wenn man lokal, via FileUnlocker, einfach so die Dateihandle in fremden Anwendungen schließt, aber die Anwendungen selber erstmal nicht erfahren, daß ihnen jetzt der Dateizugriff fehlt ... bis sie dann mal wieder drauf zugreifen wollen und es knallt. Der Server hat aber den Vorteil, daß man die Programme eben geziehlt informieren und ordnungsgemäß runterfahren/neu starten kann. (praktischer, da sie dann erstmal ihr Aufgaben ordentlich beenden können, vorallem wenn ein Bentuzer davor sitzt) |
AW: Welches Programm ist wo geöffnet?
Es geht auch mit Bordmitteln, die Windows bereitstellt:
Um herauszufinden wo überall das Programm läuft kannst du auch mit ![]()
Code:
Dieses funktioniert auch dann, wenn die Anwendung abstürzt.
FILE_FLAG_DELETE_ON_CLOSE
Jede Programminstanz sollte natürlich logischerweise einen anderen Dateinamen benutzen. |
AW: Welches Programm ist wo geöffnet?
@FILE_FLAG_DELETE_ON_CLOSE: Das funktioniert leider nicht über alle Arten der Netzwerkfreigaben, da das Transportprotokoll dieses explizit unterstützen muß.
Lokal ist das aber eine geile Sache, vorallem für temporäre Dateien, welche auch im Falle eines Programmabsturzes ordentlich entfernt würden. :thumb: |
AW: Welches Programm ist wo geöffnet?
Also ich erstelle für jede laufende EXE eine Datei im zentralen Verzeichnis, da sieht man gut, was wer wo am laufen hat.
Die nächste Stufe mit Nachrichten verschicken vom Update-Prozess an alle Clients, das sie sich mal beenden sollen, ist natürlich genial. Allerdings müssten dann auch die Zustände in den Clients überprüft werden und ggf der Benutzer zurückgefragt werden. Weil einfach mal den Prozess killen ist ja nicht die LÖsung.
Delphi-Quellcode:
initialization AppHandle := CreateFile(PChar(SYS.TmpDir+ MakeFileNameFromTimeReadableCompact(GetLocalComputerName+'_'+GetLocalUserName +'_'+ ExtractFileName(Application.ExeName)+'_','','APP',true)), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE or FILE_ATTRIBUTE_TEMPORARY, 0); if AppHandle = INVALID_HANDLE_VALUE then AppHandle := 0; finalization if (AppHandle <> INVALID_HANDLE_VALUE) and (AppHandle <> 0) then CloseHandle(AppHandle); |
AW: Welches Programm ist wo geöffnet?
Welche uses muss ich für "MakeFileNameFromTimeReadableCompact", "GetLocalComputerName" und "GetLocalUserName" implementieren?
Oder sind das Funktionen welche du dir selbst gestrickt hast? |
AW: Welches Programm ist wo geöffnet?
Wir haben in unserem Apps eine Funktion drin "beende Clienten" und "starte Clienten neu".
Jeweils mit Zeitangabe. Die Benutzer sehen dann einen Dialog mit Timeout "Programm muß neu beendet/gestartet werden" ... 10 ... 9 ... 8 ... (natürlich mit mindestens einer Minute) Bei Neustart starten die Anwendungen dann, nach ablauf des Timeouts, eine billige Autostart.exe, mit ihrem Programmpfad als Startparameter (ParamStr(0) + Parameter "-autostart" + Verzögerungszeit) und beenden sich selber. Die autostart.exe (die darf beim Update nicht angetastet/verändert werden, und wenn doch, dann bevor die Neustart initiiert wird) wartet dann etwas und startet die Clienten wieder. (wichtig für die BDEs, wo nicht immer wer davor steht und vorallem da wo kein Benutzer von irgendwas eine Ahnung hat :stupid: ) [edit] MakeFileNameFromTimeReadableCompact ist bestimmt eine "selbsgeschriebene" Funktion. Und ddas andere: Windows? oder siehe erstmal im MSDN, in welcher Headerdatei das definiert ist. Bzw. über Strg+Shift+F in deinen Delphi-Sourcen danach suchen :zwinker: |
AW: Welches Programm ist wo geöffnet?
Zitat:
|
AW: Welches Programm ist wo geöffnet?
Zitat:
|
AW: Welches Programm ist wo geöffnet?
Zitat:
|
AW: Welches Programm ist wo geöffnet?
Delphi-Quellcode:
CloseHandle kann mit 0 und INVALID_HANDLE_VALUE umgehen. Da könnte man das IF auch weglassen.
if (AppHandle <> INVALID_HANDLE_VALUE) and (AppHandle <> 0) then
CloseHandle(AppHandle); Wobei AppHandle dort ja eh niemals INVALID_HANDLE__VALUE sein dürfte, wegen dem IF in initialization, aber ich würde dieses IF weglassen, dann kann AppHandle niemals 0 sein (nach der Initialization, bzw. hinter Createfile). Also einfach ale diese IF weg und gut ist. PS: Wenn FILE_FLAG_DELETE_ON_CLOSE gesetzt ist und wenn man CloseHandle wegläßt, dann bekommt man sogar mit, wenn die Anwendung beim Runterfahren hängen bleibt, also nach dem "CloseHandle" (wenn man es hingeschrieben hätte). |
AW: Welches Programm ist wo geöffnet?
Zitat:
Um diese Datei dann auch von anderer Stelle öffnen zu können muss die Datei so angelegt werden:
Delphi-Quellcode:
Alle anderen greifen auf die Datei dann so zu:
CreateFile( PChar( FFileName ), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_DELETE, nil, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
Delphi-Quellcode:
Um also nun alle laufenden Instanzen des Programms zu ermitteln öffnet man einfach nacheinander diese Dateien, liest den Inhalt heraus und gibt das Handle wieder frei.
CreateFile( PChar( FFileName ), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
Um in diese Dateien etwas schreiben oder heraus lesen zu können gibt es ![]() |
AW: Welches Programm ist wo geöffnet?
Ich denke ich muss an Inhalt gar nichts in die Dateien schreiben (?).
Ich bekomme als Startparameter sowieso die Benutzerid des aufrufenden Benutzers mitgegeben. Und für den Computernamen hab ich mir auch schon eine Funktion rausgesucht:
Delphi-Quellcode:
Also würde ich den Dateinamen einfach wie folgt zusammenstellen:
function ComputerName: String;
var Size: DWORD; begin Size := MAX_COMPUTERNAME_LENGTH + 1; SetLength(Result, Size); if GetComputerName(PChar(Result), Size) then SetLength(Result, Size) else Result := ''; end;
Delphi-Quellcode:
Damit hätte ich alle Infos direkt im Dateinamen.
'FFileName_'+ComputerName+'_'+Trim(ParamStr(1))+'.pid'
Trotzdem werde ich mich mal mit dem THandleStream auseinandersetzen falls ich doch mal was rein schreiben muss ;) |
AW: Welches Programm ist wo geöffnet?
ich habe extra nix in die Datei geschrieben um mir eine Verwaltung der ganzen Sache mit einem extra Programm erst mal zu vermeiden.
So schau ich einfach in das Verzeichnis und weiss sofort, wer was am laufen hat. |
AW: Welches Programm ist wo geöffnet?
Jo, und wenn das Programm mehrfach von dem Benutzer an dem Rechner gestartet wird, dann klappert das so nicht.
Dein Aufruf müsste dann wie folgt sein:
Delphi-Quellcode:
CreateFile( PChar( FFileName ), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
|
AW: Welches Programm ist wo geöffnet?
Das das Programm an einem Rechner mehrmals gestartet werden kann hab ich schon mit Hilfe von "CreateMutex" unterbunden ;)
|
AW: Welches Programm ist wo geöffnet?
Zitat:
|
AW: Welches Programm ist wo geöffnet?
Zitat:
Wird das letzte Programm beendet, dann wird auch automatisch die Datei gelöscht. FILE_FLAG_DELETE_ON_CLOSE bezieht sich nur auf das erste FileHandle, über welches die Datei erstellt wurde. (danach sollte es IMHO keine Wirkung mehr haben) Und es zeigt erst seine Wirkung, nachdem kein Handle mehr auf die Datei zeigt (egal wem diese Handles gehörten). |
AW: Welches Programm ist wo geöffnet?
Na da hab ich mal wieder was gelernt ;-)
|
AW: Welches Programm ist wo geöffnet?
Zitat:
Man kann solange ein Handle auf diese Datei bekommen, bis der erste das Handle (mit Flag FILE_FLAG_DELETE_ON_CLOSE) schließt. Ab diesem Zeitpunkt hat die Datei den Status "Sobald mich keiner mehr sieht, verdufte ich" und jeder Versuch ein Handle auf diese Datei zu bekommen führt zu einem INVALID_HANDLE_VALUE. Also muss jede Instanz seine eigene Datei verwalten. |
AW: Welches Programm ist wo geöffnet?
Die Idee mit den Files ist nicht schlecht!
Ich habe mal in einer DB-Anwendung infach eine Log-Tabelle eingeführt, in der sich die Clients eintragen und zyklisch einen Zeitstempel aktualisieren (dadurch fallen auch "veraltete" Einträge auf). Beim Schließen tragen sich die Client natürlich aus. Um einen Wartungsmodus einzustellen erzeuge ich eine ReadOnly.txt bei der Exe (da steht drin, dass die Programmdaten nur noch gelesen werden können). In einem Timer wird auf die Existenz der Datei geprüft und dann die Txt angezeigt, die Tabellen auf ReadOnly gesetzt und die Form eingefärbt. Als zweite Möglichkeit wird eine KillAll.txt erzeugt, worauf sich alle Programme beenden (außer meins im AdminModus). Ist nicht wirklich genial, funktioniert aber ganz zuverlässig. |
AW: Welches Programm ist wo geöffnet?
Schreib einen Launcher, der aus einem Ordner jeweils die neueste Version der Software startet.
Laufende Programme werden nicht beachtet. Irgendwann wird der Nutzer das Programm beenden und wenn er es beim nächten mal startet, startet der Launcher das geupdatete Programm. Oder wenn du das auch verhindern willst, lausche mit Indy auf einem beliebigen freigegbenen Port und warte darauf, dass jemand (du) eine Anfrage "Update" sendet. Sobald die Anfrage eintrifft, öffne eine MessageBox, die dem Nutzer sagt, dass er seine Anwendung gefälligst neuzustarten hat. (der Vorschlag von Jonas Shinaniganz) |
AW: Welches Programm ist wo geöffnet?
Um zu bestimmen, ob die lokale EXE ein Update benötigt, lesen wir vor jedem Start die Versionsnummer der zentralen Exe aus und vergleichen. Unterscheiden sie sich, ist ein Update nötig. In den Delphi-Einstellungen muss dazu das Häkchen gesetzt werden, das mit jedem Build die Versionsnummer automatisch erhöht wird.
Und auf ungleich prüfen, so können auch ältere Versionen wieder reaktiviert werden. Ist also die Version unterschiedlich, wird vor dem Start die Exe in den lokalen Cache kopiert. Ist das nicht möglich, weil z.B. noch eine Instanz geöffnet ist, dann wird solange die neue Version vom Server direkt gestartet, bis wieder kopiert werden kann. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:41 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