Datei (.DLL, .EXE, .LNG, ...) prüfen [ERLEDIGT]

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Datei (.DLL, .EXE, .LNG, ...) prüfen [ERLEDIGT]

Beitrag von Gerd König »

Guten Morgen,

im Rahmen von Programmupdates möchte ich im Vorfeld überprüfen, ob eine Datei von einer Applikation verwendet wird.
Dabei wäre es günstig dem User eine Liste von Applikationen anzuzeigen, die terminiert werden müssen, um das Update auszuführen.

Es gibt doch sicherlich eine API-Funktion (Win XP) mit der das machbar ist, oder?

Im Voraus schon vielen Dank,
Gerd
Zuletzt geändert von Gerd König am Fr, 21. Mai 2010 6:05, insgesamt 1-mal geändert.
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Gerd König »

Hi,

da sich wahrscheinlich noch niemand mit der Problematik beschäftigt hat, werde ich jetzt (erst einmal) einen anderen Lösungsansatz verwenden

In meinem Updateordner sind alle möglichen Programmdateien vorhanden.
Da ich beim Start einer Applikation immer einen applikationsspezifischen Mutex generiere, werde ich vor der Ausführung eines Updates die Existenz der Mutexwerte zu allen möglichen Applikationen (*.exe im Updateordner) prüfen.
Ist kein Mutex vorhanden kann ich das Update ausführen.
Anderenfalls werde ich die Applikationen mit gültigen Mutex anzeigen und das Schließen dieser verlangen. Das ganze werde ich in einer Schleife verpacken, so daß das Update erst nach dem Schließen aller Applikationen ausgeführt wird.

Die Sache hat nur einen Schönheitsfehler:
Es müssen auch die XBase-Programme terminiert werden, welche die zu aktualisierende DLL gar nicht verwenden, aber damit kann ich (und muß der User :lol: ) leben!

Gerd
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Jan »

Gerd,

mit der Problematik habe ich mich bis kurz vor dem Nervenzusammenbruch beschäftigt. Und habe jetzt frustriert eine "Krücke" bei mir eingebaut. Ich schriebe die Updatedateien in ein eigenes Verzeichnis. Wenn dann das Programm gestartet wird und sieht, daß in dem Verzeichnis Dateien drin stehen, dann wird das Programm beendet, eine Batchdatei aufgerufen, die die neuen Datein rüberkopiert, im Updateverteichnis löscht, und mein Programm wieder startet. Wie gesagt, eine Krücke. Und funktioniert auch nur, weil ich nur ein einziges Xbase++-Programm laufen lasse, allerdings bestehend aus einer .exe und einer handvoll .dll.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Gerd König »

Hallo Jan,

meine "Krücke" sieht momentan beim Start einer Applikation im Falle eines Updates so aus:

Ich fange an alle relevanten Dateien vom Server (Updateordner) auf die Festplatte der Arbeitsstation zu kopieren, bis ich auf eine Date stoße, die ich nicht kopieren kann.
Das ist für mich das Zeichen, daß es noch mindestens eine aktive EXE auf der Arbeitsstation gibt, die diese verwendet. Dann breche ich das Update ab, mit der lapidaren Meldung, daß alle relevanten Applikationen zu terminieren sind (natürlich etwas user-freundlicher formuliert).
Nun bleibt es dem User überlassen, welche Programme zu schließen sind! Manche haben daraufhin Windows neu gestartet (führt ja auch zur Lösung des Updateproblems)

Herzlich
Gerd
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Koverhage »

Hallo Gerd,

warum nicht im Updateordner eine Version.txt hinterlegen.
Die Exe prüft beim Start anhand der eigenen Version, ob diese älter als die im Updateordner ist.
Wenn die im Updateordner neuer ist, Programm erst gar nicht starten, sondern Meldung anzeigen,
dass das Programm beendet wird und nach dem Ende neu gestartet werden muss.
Das wäre meines Erachtens die einfachste Lösung.
Die Lösung von Jan funktioniert nur wenn es eine Einzelplatzanwendung ist.
Gruß
Klaus
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Gerd König »

@Koverhage

Im Updateordner befinden sich ca. 20 EXE-Files, ca. 40 DLLs und diverse andere.
Dabei handelt es sich immer um das aktuelle Programmpaket.

Wir haben über 100 Arbeitsstationen, auf denen immer nur einige der vorhandenen Applikationen laufen.
Alle Programme werden über einen Loader gestartet.
Dieser überprüft, ob z.B. DLLs aktualisiert werden müssen.
Ist das der Fall, wird die entsprechende Datei kopiert.

Das Problem dabei ist folgendes:

Es wurde das Programm APP1.EXE gestartet. Dieses Programm benötigt u.a. die LIB1.DLL.
Während das Programm APP1.EXE bereits läuft, wird eine neue Version von LIB1.DLL in den Updateordner gestellt.
Jetzt soll das Programm APP2.EXE gestartet werden.

Die bisherige Loader-Version stellt fest, daß die LIB1.DLL aktualisiert werden soll. Der Kopiervorgang scheitert jedoch,
da LIB1.DLL durch das Programm APP1.EXE gesperrt ist.
In diesem Fall bringe ich eine Meldung, daß alle Applikationen zu beenden und danach neu zu starten sind.
Der Vorgang wird abgebrochen.
Ein Start weiterer Applikationen ist damit nicht möglich!

Jetzt will ich den Loader dahingehend ändern, daß festgestellt wird welche von den zu aktualisierenden DLLs durch laufende Programme
bereits gesperrt sind.
In diesem Fall könnte ich z.B. auf das Beenden von APP1.EXE verzichten und APP2.EXE auf Wunsch (Confirmbox mit 3 Tasten) ohne Update
von LIB1.DLL starten.
Das Update würde erst dann zwangsweise ausgeführt, wenn keine relevante Applikation gestartet wurde.

Gerd
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von AUGE_OHR »

hi,

wenn es um "geladene" Xbase++ DLL geht :

Code: Alles auswählen

PROCEDURE DLLLIST()
LOCAL I, J, DllName, hDll, aVersion, fVersion
LOCAL aDLLFiles := DIRECTORY( "*.DLL" )        // hier nur aktuelles Verzeichniss
LOCAL nCount    := LEN( aDLLFiles )
LOCAL n, nSum, cTest, cVers := ""
LOCAL DllList   := {}

   FOR n := 1 TO nCount
      AADD( DllList, aDLLFiles[ n, F_NAME ] )
   NEXT

   FOR I := 1 TO LEN( DllList )
      DllName := DllList[ I ]
      IF DllInfo( DllName, DLL_INFO_LOADED )
         hDll := DllInfo( DllName, DLL_INFO_HANDLE )
         fVersion := LoadResource( 1, hDll, RES_VERSIONFIXED )
         aVersion := LoadResource( 1, hDll, RES_VERSION )

         * ? ""
         * ? Replicate( "-", 78 )
         * ? ""
         * ? DllName

         IF LEN( fVersion ) > 0
            * ? "Product Version:"+ltrim(str(fVersion[RES_PRODVER_MS]))+ltrim(str(fVersion[RES_PRODVER_LS ]))
            * ? "   File Version:"+ltrim(str(fVersion[RES_FILEVER_MS]))+ltrim(str(fVersion[RES_FILEVER_LS ]))
            * ? "      File Time:"+ltrim(str(fVersion[RES_FILETIME_MS]))+ltrim(str(fVersion[RES_FILETIME_LS]))
         ELSE
         ENDIF

         IF LEN( aVersion ) > 0
            FOR J := 1 TO LEN( aVersion )
               cTest := aVersion[ J ] [ RES_VERSION_KEY ]
               DO CASE
                  CASE cTest = "CompanyName"
                  CASE cTest = "InternalName"
                  CASE cTest = "LegalCopyright"
                  CASE cTest = "OriginalFilename"
                  CASE cTest = "ProductName"
                  CASE cTest = "ProductVersion"
                  CASE cTest = "Comment"
                  CASE cTest = "FileVersion"
                       cVers := aVersion[J][RES_VERSION_VALUE]
                  OTHERWISE
                     // FileDescription
                     *  ? aVersion[J][RES_VERSION_KEY]+": "+aVersion[J][RES_VERSION_VALUE]
                     ? SUBSTR(DllName+SPACE(15),1,15) + ": " +;
                     LTRIM( LTRIM( cVers )+" "+ LTRIM( aVersion[J][RES_VERSION_VALUE] ) )
               ENDCASE
            NEXT
         ELSE
         ENDIF
      ENDIF
   NEXT
RETURN
ich gehe also durch DIRECTORY( "*.DLL" ) jede einzelne DLL an und stelle fest ob sie geladen wurde wobei ich die Runtime DLL im selben Verzeichnis wie die *.EXE habe
gruss by OHR
Jimmy
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Gerd König »

Hallo Jimmy,

die von dir genannte Funktionalität verwende ich um die Datei-Versionen anzuzeigen.
Damit habe ich allerdings noch nicht die zugehörigen auf dieser Maschine gestarteten Programme.

Jetzt habe ich noch folgende Idee:

Ich starte aus dem Loader das Kommando "tasklist /M" und lenke die Ausgabe in eine Datei diese lese ich dann ein und kann den Gesamtstring mit einem Parser analysieren.

Einen Schönheitsfehler hat das Ganze:
Ich erhalte keine Information z.B. über geöffnete .lng-Dateien (von List&Label)
Das sollte aber kein Problem sein, da zumindest die XBase-Runtime und auf jedenfall einige meiner DLLs geladen sind.

Jedenfalls kann ich dann prüfen, welche Programme zu beenden sind, um ein DLL-Update zu starten.
Man könnte noch soweit gehen, die entsprechenden Prozesse programmtechnisch zu killen.

Da das Kommando "tasklist" letztendlich auch nur auf die Windows-API zurückgreift, gibt es sicherlich auch eine Möglichkeit, den Umweg über eine Datei zu vermeiden.

Gerd
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von AUGE_OHR »

Gerd König hat geschrieben:Da das Kommando "tasklist" letztendlich auch nur auf die Windows-API zurückgreift, gibt es sicherlich auch eine Möglichkeit, den Umweg über eine Datei zu vermeiden.
yup

Code: Alles auswählen

#define WM_CLOSE        0x0010
#define WM_QUIT         0x0012

FUNCTION CloseIt( aName )
LOCAL i, nMax
   nMax := LEN( aName )
   FOR i = 1 TO nMax
      CloseNow( aName[ i ] )
   NEXT
RETURN NIL

FUNCTION CloseNow( cName )
LOCAL oDlg
LOCAL aTasklist
LOCAL aSize     := { 0, 0 }
LOCAL aPos      := { 0, 0 }
LOCAL lRunnin   := .F.
LOCAL i
LOCAL nHwnd, cWind

   oDlg := XBPDIALOG() :new( APPDESKTOP(),, aPos, aSize,, .F. )
   oDlg:clipSiblings := .T.
   oDlg:drawingArea:ClipChildren := .T.
   oDlg:create()

   SETAPPFOCUS( oDlg )

   aTasklist := GetTaskList( oDlg:gethWnd() )

   FOR i = 1 TO LEN( aTasklist )
      cWind := TRIM( UPPER( SUBSTR( aTasklist[ i ], 9 ) ) )
      cWind := SUBSTR( cWind, 1, LEN( cWind ) - 1 )
      IF cWind == TRIM( UPPER( cNaam ) )
         lRunnin := .T.
         nHwnd := VAL( LEFT( aTasklist[ i ], 8 ) )
         SendMessageA( nHwnd, WM_CLOSE, 0, 0 ) // evtl WM_QUIT
         RETURN lRunnin
      ENDIF
   NEXT
RETURN lRunnin

FUNCTION gettasklist( hWnd )
LOCAL aList       := {}
LOCAL cWindowName
LOCAL nVisible
   DO WHILE hWnd != 0
      cWindowname := SPACE( 100 )
      IF ( getwindowtexta( hWnd, @cWindowName, LEN( cWindowName ) ) <> 0 )
         nVisible := IsWindowVisible( hWnd )
         IF nVisible == 1
            AADD( aList, STR( hWnd, 8 ) + cWindowname )
         ENDIF
      ENDIF
      hWnd = GetWindow( hWnd, GW_HWNDNEXT )
   ENDDO
RETURN aList

FUNCTION GetWindow( hWnd, uCmd )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindow", hWnd, uCmd )
   DllUnLoad( nDll )
RETURN xRet

FUNCTION GetWindowTextA( hWnd, lPstring, nMax )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindowTextA", hWnd, @lPstring, nMax )
   DllUnLoad( nDll )
RETURN xRet

FUNCTION IsWindowVisible( hWnd )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "IsWindowVisible", hWnd )
   DllUnLoad( nDll )
RETURN xRet
CloseIt( aName ) schliesst alle Programm im Array aName
gruss by OHR
Jimmy
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Re: Datei (.DLL, .EXE, .LNG, ...) prüfen

Beitrag von Gerd König »

Jimmy,

Danke :blob8:
Das ist genau das was ich suche!!!!!!
Gerd
:wav:
Antworten