Skript zum updaten eines Updaters

badday

Commander
Dabei seit
Sep. 2007
Beiträge
3.023
Moin zusammen,

ich schreibe gerade an einem Updater. Dabei stehe ich nun vor dem Problem, dass ich auch den Updater updaten möchte. Dafür habe ich die das binary unter dem Namen "ToUpdate" in dem Verzeichnis des Programms. Der Updater (in C++ geschrieben) prüft zunächst, ob es eine neue Updater-Version gibt. Ist dies der Fall, speichert er sie eben unter "ToUpdate" (das funktioniert bereits). Nun zu dem eigentlichen Problem: Wenn nun der Updater nicht mehr aktuell ist, sollte er beendet werden, durch "ToUpdate" ersetzt werden und neu gestartet. Die Frage ist: Wie mache ich das genau?
Ich dachte mir, es ist am einfachsten, ein Skript zu schreiben, das aufgerufen wird. Anschließend beendet sich der (veraltete) Updater. Nun soll das Skript "ToUpdate" nehmen und damit den Updater überschreiben. Das Problem, das jetzt da ist: Ich kann wohl nicht einfach das binary überschreiben ohne sicher zu sein, dass das Programm beendet ist. Daher müsste ich wohl schauen, ob das Programm beendet ist. Dafür könnte ich an das Skript die ID des Updaters übergeben (vll. via getpid() ?; ist das plattformübergreifend? Wenn nicht, gibt es sowas? Vll. in Boost?).
Danach müsste das Skript solange warten, bis der Updater beendet ist. Wie kann ich das anhand der ID überprüfen?
Nun müsste es nur noch den Updater überschreiben und neu starten.

Das ganze muss plattformübergreifend sein, aber ich gehe fast davon aus, dass ich 2 verschiedene Skripte brauchen werde. Ich habe gehört, bei Unix-artigen OSes sei das überschreiben eines ausführenden Programms möglich?


Vielen Dank.


Gruß,

badday
 

Timmey92

Commodore
Dabei seit
Okt. 2008
Beiträge
4.481
Habe im moment ein ähnliches Problem (dabei soll sich das Programm auch durch eine neuere Version von sich selbst ersetzen).
Hatte bisher dafür keine Idee ...
 

Augen1337

Captain
Dabei seit
Apr. 2008
Beiträge
3.308
Man könnte es mit einer Batch lösen.


Zuerst aus den Umgebungsvariablen lesen, welches Betriebssystem verwendet wird.
Je nach dem müsste ein Pendant zur Batch geöffnet werden.

Die Batch wird gestartet - killt den Updaterprozess - kopiert Daten aus ToUpdate und startet dann die Dateien aus dem Updaterordner.


Zwar nicht grade elegant realisiert, aber so sollte es gehn.
 

badday

Commander
Ersteller dieses Themas
Dabei seit
Sep. 2007
Beiträge
3.023
Du meinst also, ich sollte gar nicht erst auf das beenden warten, sondern vom Skript aus killall(ID) o. Ä. aufrufen?
 
1

1668mib

Gast
Mein Gedankenansatz:
- Updater wird gestartet
- Dieser prüft, ob er selbst aktuell ist
Hier für den Fall dass er nicht aktuell ist:
- er lädt den neuen Updater herunter mit temporärem Namen
- er startet einen Hilfsprozess (also eigenes kleines Programm) und beendet sich dabei selbst, dem Hilfsprozess kann er ja z.B. die Prozess-ID als Parameter mitgeben und auch den temp. Namen
- Hilfsprozess wartet, bis Updater tatsächlich beendet ist
- Hilfsprozess tauscht Updater aus und startet diesen wieder
 

badday

Commander
Ersteller dieses Themas
Dabei seit
Sep. 2007
Beiträge
3.023
Genau an das dachte ich auch. Die Frage ist nur die konkrete Umsetzung.
Bisher passt alles soweit:
- Updater wird gestartet
- Dieser prüft, ob er selbst aktuell ist
Hier für den Fall dass er nicht aktuell ist:
- er lädt den neuen Updater herunter mit temporärem Namen
er startet einen Hilfsprozess (also eigenes kleines Programm) und beendet sich dabei selbst, dem Hilfsprozess kann er ja z.B. die Prozess-ID als Parameter mitgeben und auch den temp. Namen
Der temp. Name ist immer gleich, daher ist nur die ID nötig. Geht das mit getpid()?
- Hilfsprozess wartet, bis Updater tatsächlich beendet ist
Das ist der knifflige Punkt. Wie genau macht man das?

Gruß,

badday
 
1

1668mib

Gast
Wieso muss es denn ein Script sein?
Wieso programmierst du das nicht ebenfalls in C++?
 

badday

Commander
Ersteller dieses Themas
Dabei seit
Sep. 2007
Beiträge
3.023
Das ist eine gute Frage. Du hast recht, ich werde es einfach in C++ machen.
Gibt es einen plattformübergreifenden Weg, die Prozess-ID zu überprüfen?

Gruß,

badday
 

badday

Commander
Ersteller dieses Themas
Dabei seit
Sep. 2007
Beiträge
3.023
Moin,

ich habe das Programm soweit fertig, unter GNU/Linux funktioniert auch das ersetzen, unter Windows allerdings nicht. Ich versuche folgendes:
remove(updatepath.c_str());
Dies ist der "alte" Updater. Allerdings ist hier das Problem, dass er ihn nicht löscht. errno sagt 13, also liegt es offenbar an den Zugriffsrechten, daher gehe ich davon aus, dass das Programm noch läuft und ich es daher nicht löschen darf. Ich gehe des weiteren davon aus, dass system() nicht blockiert, d. h. der "alte" Updater nach einer Zeit beendet wird. Daher dachte ich mir:
int i=1;
for(int a=0;a<5 && i!=0;a++)
{
i = remove(updatepath.c_str());
PortableSleep(30);
}
PortableSlepp() ist lediglich eine Funktion, die dann unter Windows Sleep aufruft. Allerdings ist auch hier nach 5 mal immer noch nicht i!=0. Daher meine Frage: Wie kann ich das anstellen, dass ich die Datei entfernen kann?

Vielen Dank.


Gruß,


badday
 
Top