2011-10-12 12 views
7

Desidero richiamare un programma di aggiornamento per verificare la disponibilità di aggiornamenti (in realtà non eseguire l'aggiornamento ma controllare solo se ce n'è uno). Mi piacerebbe farlo sullo sfondo e in silenzio. Se c'è un aggiornamento, chiederei all'utente autorizzazioni elevate ed esegui il programma di aggiornamento con quello. Il controllo comporta la lettura di un file nella directory dell'applicazione e il confronto tra la versione trovata in esso e quella su un sito web.Come eseguire un'app senza elevazione?

Come posso eseguirlo senza elevazione per il solo controllo? QProcess::start() non riesce perché ha bisogno di autorizzazioni elevate e ShellExecute funziona solo se aggiungo il verbo "runas" per lo stesso motivo (che voglio solo se ci sarebbe effettivamente scritto in quella directory, cioè io voglio eseguire un aggiornamento). Immagino di dover aggiungere qualche sorta di manifest ma non conosco il suo contenuto.

risposta

10

Così si scopre che ho avuto un altro bug che ha causato il ramo non elevati in esecuzione di funzionare in tutti i casi. Il modello che ho descritto nel post funziona. Per evitare che Windows deduca la necessità di autorizzazioni elevate, è necessario aggiungere una risorsa manifest. (Per esempio, se il nome del exe applicazione contiene la parola "aggiornamento" verrà attivato)

Il contenuto del manifesto sono i seguenti:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> 
     <security> 
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> 
       <requestedExecutionLevel level="asInvoker" uiAccess="false" /> 
      </requestedPrivileges> 
     </security> 
    </trustInfo> 
</assembly> 

compilazione al vostro exe dipende il compilatore e l'ambiente, quindi sono solo mostrando la mia: Qt Creator e mingw-gcc:

Creare un file rc per le risorse con il seguente contenuto:

1 24 DISCARDABLE manifest.xml 

Aggiungere questo file rc ai tuoi .pro in questo modo:

win32:RC_FILE = resources.rc 

Dopo questo, ShellExecute senza il verbo paramter verrà eseguito senza elevazione, e l'utilizzo di "runas" verrà eseguito con l'elevazione.

+0

Questo è grosso modo quello che ho detto. –

+3

Mi piace questa risposta meglio. Meno chiacchiere, più codice. –

0

suggerisco di utilizzare uno di questi scenari:

  • messo quel file nel profilo di utente anziché il percorso dell'applicazione
  • contenuti
  • copia di quel file per il profilo di utente in caso di esso è in modalità di sola lettura quindi eseguire QProcess::start()
  • includono il file all'interno di file .qrc poi estrarlo al profilo dell'utente in caso di mancato di leggere o eseguire QProcess::start()
4

La richiesta di elevazione viene visualizzata quando l'applicazione lo richiede, per qualche motivo. Puoi controllarlo con il manifest dell'applicazione. Vedere l'articolo Create and Embed an Application Manifest (UAC) per dettagli su come aggiungere il manifest.

vorrei suggerire quanto segue:

  1. separata tua Updater e Update Checker, in modo che siano in diversi file .EXE.
  2. UpdateChecker.exe non richiede privilegi di amministratore, pertanto l'elemento requestedExecutionLevel del file manifest ha il livello asInvoker.
  3. Updater.exe richiede i privilegi di amministratore perché scrive il file dell'applicazione aggiornato in Programmi. Pertanto l'elemento requestedExecutionLevel del manifest è il livello requireAdministrator.

Nel programma è possibile avviare UpdateChecker.exe in qualsiasi modo. Per avviare Updater.exe dovrai utilizzare ShellExecute; se l'applicazione ha manifest (e consiglio vivamente l'incorporamento di manifest) mostrerà il prompt UAC per l'elevazione se l'applicazione richiede i privilegi di amministratore. Non è necessario utilizzare il verbo runas.

In alternativa è possibile verificare se l'aggiornamento è disponibile o meno dall'applicazione principale. E lanciare Updater.exe solo quando c'è una nuova versione sul server.


Un'altra opzione sarebbe quella di fare Updater.exe sia di controllo per l'aggiornamento e si applica se c'è uno, proprio come si fa ora. In questo caso Updater.exe dovrebbe avere il livello asInvoker nel suo manifest. Quando inizia, senza parametri, controlla se c'è una nuova versione sul server.Se trova la versione più recente, si rilancia con privilegi di amministratore e passa un parametro di riga di comando, ad esempio /doUpdate, che istruisce fare eseguire l'aggiornamento vero e proprio.

Al fine di rilanciare se stessa elevata, deve usare la funzione ShellExecute e runas verbo, perché ShellExecute sarà in grado di rilevare automaticamente l'Updater.exe ora richiede privilegi amministrativi.

Ricordare che il significato del verbo runas differisce tra Windows XP e Windows Vista/7, quindi è necessario gestire questa situazione se si desidera supportare versioni precedenti di Windows. Il primo approccio che ho descritto funzionerà su Windows XP senza ulteriore gestione.

+0

Grazie per la risposta dettagliata! Indagherò il problema ulteriormente lunedì e potrei andare con la soluzione di scissione. Ho controllato il manifest in wyUpdate (un programma di aggiornamento commerciale) che esegue sia il controllo che l'aggiornamento ed è impostato sul livello di autorizzazione "asInvoker" che è il più basso possibile. Potrei aver trascurato qualcosa, potrebbe funzionare come inizialmente previsto. Ti farò sapere. –

+0

Ho fatto, se sei interessato, controlla la mia risposta qui sotto. –

+0

@ TamásSzelei Grazie per aver pubblicato l'aggiornamento. –

Problemi correlati