Incrustar un manifiesto de aplicación en un exe VB6
resources uac (3)
VB6 tiene la peculiaridad de que cualquier elemento de recurso debe ser un múltiplo exacto de 4 de longitud. Intente rellenar el archivo .RC con espacios y ver si eso cambia el comportamiento.
Además, puede agregar el recurso usando el IDE VB6 en lugar de editar el VBP. El efecto puede ser el mismo, pero el editor de recursos es el medio estándar para hacer esto.
Recientemente revisé un conjunto de aplicaciones de utilidad independientes escritas en VB6 para asegurarme de que la virtualización del registro esté desactivada para Windows Vista y versiones posteriores. Creé un archivo de manifiesto independiente para cada ejecutable, establecí apropiadamente el nivel de ejecución requestedExecutionLevel
(algunos de ellos necesitan modificar las claves de registro HKEY_LOCAL_MACHINE
, otros no) y los probé. Todos parecen funcionar correctamente.
Solo me queda un pequeño problema. Dado que son utilidades independientes, las personas están acostumbradas a copiarlas por la red y ejecutarlas manualmente. Si alguien olvida copiar el archivo de manifiesto así como el exe, el exe escribirá silenciosamente en la clave de registro virtualizada en lugar del real y causará problemas difíciles de solucionar.
La solución obvia es incorporar el manifiesto en el exe como recurso. Todos los artículos que he leído en la red te dicen que incrustes el recurso de esta manera:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
Esto debería funcionar bien, excepto que el compilador de VB siempre crea el icono de la aplicación con el ID de recurso = 1. Cuando probé el código anterior, Windows se negó a ejecutar el exe, quejándose de un error de recurso (actualizaré esta publicación con el detalles más adelante). Traté de cambiar el ID del recurso a otro número, luego de lo cual Windows ejecutó el programa con éxito pero no reconoció el contenido del manifiesto.
¿Alguien sabe de una forma de hacer funcionar un manifiesto incrustado en un exe VB6, o debería simplemente seguir con un archivo externo?
ACTUALIZACIÓN 1
El texto dado arriba es todo el contenido del archivo .rc
. Lo compilo en un archivo .res
como este:
"%ProgramFiles%/Microsoft Visual Studio/VB98/Wizards/rc.exe" /r /fo "Resources.res" "Resources.rc"
E incrústelo en el archivo de proyecto VB6 de esta manera:
Type=Exe
Reference=*/G{00020430-0000-0000-C000-000000000046}#2.0#0#../../../../../../../../WINDOWS/system32/stdole2.tlb#OLE Automation
Form=Main.frm
ResFile32="Resources.res"
IconForm="FMain"
Startup="FMain"
HelpFile=""
Title="Windows Vista Registry Test - VB6"
ExeName32="RegistryTestVB6.exe"
Path32=""
Command32=""
Name="RegistryTestVB6"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionComments="Windows Vista Registry Test - VB6"
VersionCompanyName=""
VersionFileDescription="Windows Vista Registry Test - VB6"
VersionLegalCopyright=""
VersionProductName="Windows Vista Registry Test - VB6"
CondComp=""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
Cuando leo el archivo ejecutable en el editor de recursos VS2008, se ve así:
RegistryTestVB6.exe
Icon
1 [Neutral]
RT_MANIFEST
1 [English (United States)]
Version
1 [English (United States)]
Cuando construyo una aplicación de prueba VB.NET equivalente exacta en VS2008, luego la carga en el editor de recursos, se ve así en su lugar:
RegistryTestNET.exe
Icon
32512 [Neutral]
RT_MANIFEST
1 [Neutral]
Version
1 [Neutral]
ACTUALIZACIÓN 2
Pruebas: el .NET exe funciona bien en Windows XP y Windows 7. Sin embargo, el exe de VB6 produce el siguiente error en XP:
Esta aplicación no ha podido iniciarse porque la configuración de la aplicación es incorrecta. Reinstalar la aplicación podría resolver el problema.
y el siguiente error en 7:
La aplicación no ha podido iniciarse porque su configuración lado a lado es incorrecta. Consulte el registro de eventos de la aplicación o use la herramienta de línea de comandos sxstrace.exe para obtener más detalles.
Mirando en el registro de eventos, veo la siguiente entrada:
La generación del contexto de activación falló para "RegistryTestVB6.exe". Error en el archivo de manifiesto o de política "RegistryTestVB6.exe" en la línea 10. Sintaxis Xml no válida.
Huelga decir que el XML no es inválido, es exactamente el mismo archivo con la misma codificación que usé para el exe .NET, y ese funciona.
RESOLUCIÓN
El compilador VB6 realmente requiere que un archivo de texto arbitrario incluido en un recurso debe ser un múltiplo exacto de 4 bytes. Simplemente agregué espacios al XML hasta que Notepad ++ me dijo que el tamaño total del archivo, incluida la lista de materiales, era un múltiplo de 4.
Gracias a Michael y a Jim por señalarme en la dirección correcta. Es una lástima que no pueda marcarlos a los dos como la respuesta.
Curiosamente, tuve que hacer exactamente lo mismo recientemente. Siguiendo los pasos que Christian describió, conseguí que funcionara la primera vez. Para la propsperity, aquí está todo el flujo de trabajo que seguí:
- Creó un archivo RC como se describe en la pregunta original
- Creado un app.manifest con los siguientes contenidos:
ManifestImage http://img638.imageshack.us/img638/3364/manifesta.png Imagen utilizada para conservar caracteres en espacios en blanco, que son MUY IMPORTANTES para que esto funcione. Como se indicó en las respuestas anteriores, el tamaño del archivo debe ser un múltiplo de 4.
- Ran RC.EXE como se describe en la pregunta original contra el rc para generar el archivo .res
- Edité mi archivo Project.VBP para incluir la siguiente línea cerca de la parte superior:
ResFile32 = "Recursos.res"
- Construido EXE en entorno vb6 estándar. Cuando se despliega en una máquina vista o win7, aparece el escudo y se solicita al usuario que se ejecute como administrador. Al abrir el archivo EXE en el estudio, veo los siguientes recursos:
texto alternativo http://img688.imageshack.us/img688/4879/finalresources.png
Si todavía tiene problemas, hágamelo saber y compartiré con usted todo lo que pueda. ¡Aparte de eso, no estoy seguro de qué decirle aparte de Works on my Machine!
El uso del compilador de recursos (rc.exe) va por un largo camino. Hay una opción mucho más simple para incrustar un manifiesto de aplicación dentro de un ejecutable, ya sea C ++ o VB6 o casi cualquier otro idioma. La herramienta Manifest (mt.exe) se escribió específicamente para integrar manifiestos dentro de binarios y se proporciona de forma gratuita con el SDK de Windows. El beneficio adicional de usar mt.exe es que maneja automáticamente cualquier relleno necesario.
Simplemente ejecute la siguiente línea de comando después de compilar el binario. He utilizado la convención de nomenclatura usada internamente por el compilador de Visual C ++ 2005, donde el nombre del archivo de manifiesto contiene el nombre completo del programa con ".intermediate.manifest" adjunto.
mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1
Actualización: he estado usando esto en un proceso de compilación automatizado con los ejecutables de VB6 durante más de dos años. Ha sido tan exitoso que hemos eliminado las pruebas de compatibilidad de SO (específicas de los manifiestos) de nuestras pruebas de regresión.