2009-06-17 4 views
6

Sto usando Microsoft Visual Studio 2008 con una distribuzione di destinazione di Windows. Come faccio a far sì che un file si "aggiorni da solo"? Ho già ottenuto la parte "trasmittente su una rete", ma come faccio a scrivere un eseguibile su se stesso?Come faccio ad aggiornare automaticamente un file (Native C++)

In sostanza, voglio scrivere un aggiornamento automatico per una directory che include anche l'auto-aggiornamento e il programma di aggiornamento deve aggiornare TUTTO nella directory.

Forse un modo per sospendere le modifiche al file fino al rilascio del blocco file funzionerebbe. Se dovessi farlo, probabilmente lo seguirò con una hot-patch.

+0

Possibile Dupe: http://stackoverflow.com/questions/250175/writing-my-own-auto-updater – crashmstr

+1

Non una vittima, questo è specificamente C++ nativo. –

risposta

5

Scrivere un nuovo file eseguibile ed eliminare o salvare una copia di quello vecchio: è possibile inviare un diff sulla rete e disporre di un terzo programma, il monitor di aggiornamento o qualsiasi altra cosa, per applicarlo. Sarebbe solo un piccolo script che potrebbe essere avviato dall'app remota quando si rende conto che è disponibile un aggiornamento. Il programma di aggiornamento può rinominare se stesso a $ UPDATER_OLD_VERSION o qualsiasi altra cosa, scrivere una copia aggiornata di se stesso con il nome appropriato e, quando viene eseguito il nuovo programma di aggiornamento, controllare se esiste un file denominato $ UPDATER_OLD_VERSION nella directory dell'app ed eliminarlo. Tutti gli altri file potrebbero essere semplicemente aggiornati/sovrascritti.

+0

No.Quella soluzione è troppo caotica per me. Preferirei non avere "dati temporanei" in giro. Cosa succede se il computer si blocca nel mezzo! –

+3

@wowus - Molto meglio che si blocca scrivendo dati temporanei che sovrascrivendo l'exe effettivo. Inoltre, la correzione è semplice: scrivi su un file temporaneo, quindi chiama MoveFile per metterlo nella sua posizione finale. Nello stesso volume, MoveFile è atomico, quindi un crash non lo lascerà in uno stato incoerente. – Michael

+0

Il suggerimento di SoloBold è come generalmente si fa questo genere di cose. L'app che stai aggiornando non può aggiornarsi. Come dici tu, e se il computer si blocca nel mezzo? –

2

Lo faccio utilizzando un InnoSetup setup.exe che viene avviato in modo silenzioso e chiude l'app prima che inizi l'installazione dei nuovi file. Ho dovuto aggiungere sezioni Pascal [codice] personalizzate per garantire che tutto si arresti, ma fa il lavoro.

+0

A parte scrivere un driver di periferica o hackerare il sistema operativo, penso che alcuni schemi come questo siano l'unico modo per farlo. Quando si esegue un eseguibile sotto Windows, il sistema operativo lo mantiene aperto, bloccato in scrittura. –

3

In genere non è possibile modificare un'app mentre è in esecuzione. È necessario chiudere il programma originale e modificarlo da un'altra posizione.

2

Non è possibile sovrascrivere un file mentre è in esecuzione, ma è possibile rinominarlo. Nel mio programma di aggiornamento, rinominare l'exe esistente in qualcosa di significativo (oldname_dateandtime), quindi scrivere la nuova copia in. Quindi, chiudere automaticamente il sistema e riavviarlo da un servizio. All'avvio dell'app, è in esecuzione la nuova versione.

+0

Faccio lo stesso, e pulisco le vecchie versioni all'avvio. –

+0

Lasciamo i vecchi in giro in modo che i nostri tecnici di assistenza sul campo possano tornare in caso di problemi. Certo, abbiamo il lusso degli ingegneri del servizio sul campo :-). Le vecchie versioni vengono ripulite al prossimo aggiornamento. –

0

Quando ho creato un programma di aggiornamento, dovrei separare il programma diversi. Il motivo principale era esattamente come quello che vuoi fare. Basta dire, B aggiorna l'applicazione di destinazione più A e A aggiorna B. Ho provato a trovare un altro modo, ma quello che ho fatto è stato reso extra piccolo e semplice. :(

0

penso che si sta parlando di versioni di file e updaters. come hai detto è necessario autoupdater.So è necessario creare un servizio che monitora la directory di installazione e confronta la versione del file sul disco con il server.

volta non corrispondente accade si può chiedere più recenti dati dal server. Se i file che vanno da sostituire sono in uso bisogna segnarli per l'eliminazione/annullamento della registrazione durante il prossimo riavvio e si può parlare di questi utilizzando registro di sistema.

È possibile copiare tutti i file nella cache e in seguito durante il riavvio copiarli per installare la directory

4

Ecco come l'ho fatto di recente. C'è una breve sovrapposizione tra il vecchio programma in esecuzione e la nuova programmazione in esecuzione. Fa uso del trucco che è possibile rinominare l'eseguibile corrente e portare il nuovo file in posizione prima di chiudere il vecchio. Questo non è sicuro al 100%, ma l'unico modo in cui questo potrebbe "brick" la tua applicazione è se CopyFile fallisce.

#include <windows.h> 
#include <iostream> 
#include <fstream> 

void UpgradeService::UpgradeSelf() { 

    std::string temp = root   + "\\myprogram_tmp.exe"; 
    remove(temp.c_str()); // ignore return code 

    std::string src = upgradeFolder + "\\myprogram.exe"; 
    std::string dst = root   + "\\myprogram.exe"; 


    rename(dst.c_str(),temp.c_str()); 
    CopyFile(src.c_str(),dst.c_str(),false); 
    static char buffer[512]; 
    strcpy(buffer,dst.c_str()); 

    /* CreateProcess API initialization */ 
    STARTUPINFO siStartupInfo; 
    PROCESS_INFORMATION piProcessInfo; 
    memset(&siStartupInfo, 0, sizeof(siStartupInfo)); 
    memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 
    siStartupInfo.cb = sizeof(siStartupInfo); 

    ::CreateProcess(buffer, // application name/path 
    NULL, // command line (optional) 
    NULL, // no process attributes (default) 
    NULL, // default security attributes 
    false, 
    CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE, 
    NULL, // default env 
    NULL, // default working dir 
    &siStartupInfo, 
    &piProcessInfo); 


    ::TerminateProcess(GetCurrentProcess(),0); 
    ::ExitProcess(0); // exit this process 

    // this does not return. 
}