2011-10-12 28 views
7

Deseo invocar un actualizador para buscar actualizaciones (no para hacer la actualización, solo verificar si hay alguna). Me gustaría hacer esto en segundo plano y en silencio. Si hay una actualización, le pediría al usuario permisos elevados y ejecutaría el actualizador con eso. La verificación implica leer un archivo en el directorio de la aplicación y comparar la versión que se encuentra con la de un sitio web.¿Cómo ejecutar una aplicación sin elevación?

¿Cómo puedo ejecutarlo sin elevación solo para verificar? QProcess::start() falla porque necesita permiso elevado y ShellExecute solo funciona si agrego el verbo "runas" por la misma razón (lo cual solo quiero si realmente estaría escribiendo en ese directorio, es decir, quiero realizar una actualización). Supongo que necesito agregar algún tipo de manifiesto, pero no sé su contenido.

Respuesta

10

Así que resultó que tenía otro error que causaba que la rama de ejecución no elevada se ejecutara en todos los casos. El modelo que describí en la publicación funciona. Para evitar que Windows infiera la necesidad de permisos elevados, debe agregar un recurso de manifiesto. (Por ejemplo, si el nombre de su exe aplicación contiene la palabra "actualizador" que se activará)

El contenido del manifiesto son los siguientes:

<?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> 

Compilarlo a su .exe depende el compilador y el medio ambiente, por lo que sólo estoy mostrando la mía: Qt Creator y MinGW gcc-:

Crear un fichero rc de los recursos con el siguiente contenido:

1 24 DISCARDABLE manifest.xml 

Añadir este archivo rc para sus .pro así:

win32:RC_FILE = resources.rc 

Después de esto, ShellExecute sin el verbo parametro se ejecutará sin elevación, y el uso de "runas" se ejecutará con la elevación.

+0

Esto es más o menos lo que dije. –

+3

Me gusta esta respuesta mejor. Menos conversación, más código. –

0

Es mejor utilizar uno de estos escenarios:

  • poner ese archivo en el perfil de usuario en lugar de la ruta de la aplicación
  • contenido
  • copia de ese archivo al perfil de usuario en caso de que está en modo de sólo lectura a continuación, ejecutar QProcess::start()
  • incluyen dentro de ese archivo .qrc archivo y extraerlo en el perfil de usuario en caso de defecto de leer o ejecutar QProcess::start()
4

El aviso de elevación aparece cuando su aplicación lo solicita, por alguna razón. Puedes controlarlo con el manifiesto de la aplicación. Consulte el artículo Create and Embed an Application Manifest (UAC) para obtener detalles sobre cómo agregar el manifiesto.

Yo te sugeriría lo siguiente:

  1. separar su Updater y Update Checker, por lo que están en diferentes archivos .EXE.
  2. UpdateChecker.exe no requiere privilegios de administrador y, por lo tanto, el elemento requestedExecutionLevel del manifiesto tiene el nivel asInvoker.
  3. Updater.exe requiere privilegios de administrador porque escribe el archivo de la aplicación actualizada en Archivos de programa. Por lo tanto, el elemento requestedExecutionLevel de su manifiesto tiene el nivel requireAdministrator.

En su programa puede ejecutar UpdateChecker.exe de la manera que desee. Para iniciar Updater.exe, deberá usar ShellExecute; si la aplicación tiene el manifiesto (y recomiendo encarecidamente que se incorpore el manifiesto) mostrará el mensaje de UAC para elevación si la aplicación desea privilegios de administrador. No es necesario usar el verbo runas.

Como alternativa, puede verificar si la actualización está disponible o no desde su aplicación principal. Y ejecute Updater.exe solo cuando haya una nueva versión en el servidor.


Otra opción sería hacer Updater.exe el registro de entrada para la actualización y aplicarlo si hay uno, al igual que lo hace ahora. En este caso, Updater.exe debería tener el nivel asInvoker en su manifiesto. Cuando se inicia, sin los parámetros, comprueba si hay una nueva versión en el servidor.Si encuentra una versión más nueva, se vuelve a lanzar a sí mismo con privilegios de administrador y pasa un parámetro de línea de comandos, por ejemplo /doUpdate, que le indica que realice la actualización real.

Con el fin de relanzar sí elevada, se tiene que utilizar ShellExecute función y runas verbo, porque ShellExecute será incapaz de detectar automáticamente su Updater.exe ahora requiere privilegios administrativos.

Tenga en cuenta que el significado del verbo runas difiere entre Windows XP y Windows Vista/7, por lo que debe manejar esta situación si desea admitir versiones anteriores de Windows. El primer enfoque que describí funcionará en Windows XP sin manejo adicional.

+0

¡Gracias por la respuesta detallada! Investigaré más el problema el lunes y podría ir con la solución de división. Comprobé el manifiesto en wyUpdate (un actualizador comercial) que hace tanto la comprobación como la actualización y está configurado en el nivel de permiso "asInvoker", que es el más bajo posible. Podría haber pasado por alto algo, podría funcionar como originalmente había planeado. Yo lo haré saber. –

+0

Lo hice, si estás interesado, echa un vistazo a mi respuesta a continuación. –

+0

@ TamásSzelei Gracias por publicar la actualización. –

Cuestiones relacionadas