Updater basteln



  • Bei mir sind's dann zwei 😞

    - Wollen Sie Update installieren?

    - CUA-Klick auf ja (aber den Klick hat man ja selbst mit mehr Sicherheitsbedürfnis gewählt) [wobei ich es - siehe QT-Thread - nicht hinbekomme die exe mit CUA so zu starten, dass der Benutzer auch gefragt wird! system geht auch nicht :(]


  • Administrator

    @Shade Of Mine,
    Der User hat keine Rechte nach "Programme" zu schreiben, aber er soll die Möglichkeit bekommen, Updates zu installieren? Ist das nicht irgendwie widersprüchlich? Sogar fast schon eine Sicherheitslücke?

    Wenn jemand keine Schreibrechte in "Programme" hat, dann soll er auch nicht in der Lage sein, irgendwelche Updates zu installieren. Dann benötigt es jemand, welcher diese Recht auch besitzt und nicht irgendwelche Lösungen, welche diese Sicherheitsmassnahmen umgehen.

    Ich würde daher im Fall eines User ohne Rechte beim ersten Mal nach dem Aufstarten der Applikation einen klaren Hinweis geben, dass ein Update vorhanden ist, aber dazu jemand mit entsprechenden Rechten benötigt wird. Falls der User das Update nicht durchführt, soll fortan irgendwo ein dezenter Hinweis in der Applikation platziert werden.

    Grüssli



  • Hi,

    nochmal eine Frage: Mein Updater funktioniert soweit prima (ein Klick für Ok, einer für CUA). Aber wenn er im Updater eine DLL ersetzen möchte, die das (bereits beendete!) Hauptprogramm nutzt, kommt es manchmal vor, dass er die nicht überschreiben kann, sprich: die Datei ist noch geöffnet. Wieso, wenn doch die exe schon beendet wurde? Laufen die Aufräumarbeiten von exe und dll parallel und nicht voneinander abhängig?

    Wie kann ich das Problem lösen/umgehen?



  • Einfachste Variante: Retry-Schleife 🙂



  • Alternativ geht auch oft ein rename der DLL und diese dann spaeter mal loeschen.



  • Retry-Schleife, hm... das hatte ich im Kopf, aber war unsicher, ob es nicht zu wenig elegant wäre. Aber gut, werde es wohl so umsetzen. 🙂

    Zudem will ich verstehen, wieso die DLL noch geöffnet ist, obwohl die übergeordnete EXE ja schon beendet wurde.

    Aber kann ich eine noch geöffnete DLL umbenennen? Wie löse ich damit das Problem?



  • Eisflamme schrieb:

    Retry-Schleife, hm... das hatte ich im Kopf, aber war unsicher, ob es nicht zu wenig elegant wäre. Aber gut, werde es wohl so umsetzen. 🙂

    Naja, gibt sicher elegantere Möglichkeiten, aber die sind dann vermutlich auch komplizierter 🙂

    Aber kann ich eine noch geöffnete DLL umbenennen?

    Kommt drauf an wie die geöffnet ist.
    Eine .exe die gerade ausgeführt wird kann man normalerweise umbenennen. Eine geladene DLL dann vermutlich auch.
    Wenn das File mit CreateFile geöffnet wurde geht es allerdings nicht.

    Wie löse ich damit das Problem?

    * Alle alten .exen/.dlls umbenennen (irgend ein generierter Filename, halt irgendwas was es in dem Verzeichnis nicht schon gibt).
    * Alle umbenannten Files löschen
    * Wenn ein File dabei nicht gelöscht werden konnte => mit MoveFileEx(name, 0, MOVEFILE_DELAY_UNTIL_REBOOT) zum Löschen beim nächsten Start markieren
    * Neue Files mit den "normalen" Namen schreiben



  • Okay, danke,. 🙂

    Aber wieso ist die DLL überhaupt noch "geöffnet", weiß das jemand? Wenn die Retry-Schleife sicher ist (scheiß auf die Eleganz *hust* [<- hat nichts mit Deinem Nick zu tun]), nehm ich die (kann ja ein kleines wait einbauen, damit ich nicht währenddessen das System bremse). Aber wenn es andere Gründe gibt außer dass da gerade noch was aufgeräumt wird oder so, dann wäre das ja eben keine sichere Lösung. Aber da das meine selbsterstellte DLL ist, wüsste ich nicht, wer die sonst nutzen könnte. 😞



  • Vielleicht gibt's irgendwelche Effekte durch die die DLL wirklich erst kurz nach Beendigung des Prozesses "frei" wird, keine Ahnung.

    Aber...

    Wie beendest du denn den Prozess? Kooperativ? Wartest du darauf dass er beendet wurde (mit WaitForSingleObject auf das Process Handle)?
    Falls du nicht wartest, dann probier mal das einzubauen, und ob du dann das Access Denied/Sharing-Violation immer noch bekommst.
    (Egal ob du den Prozess "kooperativ" beendest oder mit TerminateProcess draufknallst)

    Ich würde es in der Reihenfolge versuchen:
    * Prozess-Handle besorgen
    * Prozess killen bzw. signalisieren dass er sich beenden soll
    * WaitForSingleObject(processHandle, INFINITE)
    * CloseHandle(processHandle)
    * Anfangen Files zu löschen

    Davon abgesehen wären die üblichen Verdächtigen was "gelockte Files" angeht...
    * Explorer.exe (z.B. um das Icon auszulesen oder sonstige Informationen zu ermitteln)
    * Virenscanner
    * Indexingdienst

    Da alle diese Zugriffe recht kurz sind, würde ich sagen dass du mit einer Retry-Schleife gute Chancen hast.

    Kurzes Delay zwischen den Versuchen hast du ja selbst schon erwähnt. Und ein Timeout sollte her. Also dass der Updater nach ner bestimmten Zeit ne Message-Box anzeigt (Failed to update lalablabla -- "Retry" - "Give up").



  • hustbaer schrieb:

    Vielleicht gibt's irgendwelche Effekte durch die die DLL wirklich erst kurz nach Beendigung des Prozesses "frei" wird, keine Ahnung.

    Window's DLL-Cache nach dem Motto "könnt' man ja noch brauchen" 😉 Offenbar gibt es aber keine Möglichkeit eine bestimmte DLL aus dem Cache zu entladen...



  • Wieso sollte der DLL Cache da ein Problem machen?
    Soweit ich weiss werden da Links verwendet (vermutlich Hardlinks, Symlinks auf Files gab's ja unter XP noch gar nicht soweit ich weiss), und dann immer nur der Link im DLL Cache Verzeichnis "aufgemacht", nie das wo anders liegende "Original". Man sollte das "Original" also problemlos löschen können.

    Probleme dürfte es mMn. eigentlich nur geben wenn man das File mit CreateFile aufmacht, z.B. weil man es direkt überschreiben will (=ohne dabei ein neues File zu erzeugen).

    Oder hast du diesbezüglich irgendwelche Infos die etwas anderes vermuten lassen?



  • /Den/ DLL-Cache auf der Platte meinte ich nicht. IIRC behält windows eine DLL noch eine gewisse Zeit im Speicher nachdem alle reference counts 0 sind. Link dazu hab' ich aber auf die Schnelle nicht parat.

    // edit: Vllt. hilft http://msdn.microsoft.com/en-us/library/ms682604(v=vs.85).aspx



  • Also die DLL wird von der EXE einfach nur dynamisch gelinkt mit Hilfe einer LIB. Ich nutze da keine WinAPI-Funktionen. Die einzige WinAPI-Funktion, der zum Tragen kommt, ist ShellExecute, der ruft meinen Updater auf. Daraufhin beende ich die Applikation. Der Updater benötigt dann zumindest eine Sekunde oder so, bis er loslegt bzw. auch 1-3 Sekunden, um das Updater runterzuladen. Und die Applikation ist inzwischen beendet.

    Das Schreiben der Dateien geschieht wegen so einer Unzip-API über Befehle wie _wmakepath und Konsorten...



  • Swordfish:
    Vielen Dank für den Link, dort finde ich genau das, was ich brauche!

    Es nützt also nichts einfach mit jeweils verdoppelten Delay mehrfach zu probieren eine Datei zu löschen. Die bleibt manchmal minutenlang geöffnet, obwohl der Prozess, der sie vorher genutzt hat, bereits lange beendet ist. Niemand versteht das, aber der MSDN-Eintrag sollte das Problem lösen, Mal versuchen. 🙂

    Edit: Versucht und es funktioniert hervorragend. Die Dateien werden beim nächsten Systemstart erfolgreich gelöscht.


Anmelden zum Antworten