2010-02-02 67 views
15

Recientemente he pasado por un montón de aplicaciones de utilidad independientes escritas en VB6 para asegurarme de que la virtualización de registro esté desactivada para Windows Vista y superior. Creé un archivo de manifiesto independiente para cada exe, establecí el requestedExecutionLevel de forma adecuada (algunos de ellos necesitan modificar las claves de registro HKEY_LOCAL_MACHINE, otros no) y los probé. Todos parecen funcionar correctamente.Incrustar un manifiesto de aplicación en un exe VB6

Me queda solo 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á de forma silenciosa en la clave de registro virtualizada en lugar de la 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 le dicen incrustar el recurso de la siguiente 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 los 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 manera de hacer funcionar un manifiesto incrustado en un exe VB6, o debería simplemente seguir con un archivo externo?

ACTUALIZA 1

El texto anterior es dado todo el contenido del archivo .rc. Compilo en un archivo .res así:

"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"

e incrustarlo en el archivo de proyecto de VB6 así:

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 leí el compilado exe en el editor de recursos VS2008, se se parece a esto:

RegistryTestVB6.exe 
    Icon 
     1 [Neutral] 
    RT_MANIFEST 
     1 [English (United States)] 
    Version 
     1 [English (United States)] 

Cuando construyo una aplicación VB.NET prueba equivalente exacto en VS2008, a continuación, cargar en el que edito de recursos r, parece que esta vez:

RegistryTestNET.exe 
    Icon 
     32512 [Neutral] 
    RT_MANIFEST 
     1 [Neutral] 
    Version 
     1 [Neutral] 

ACTUALIZACIÓN 2

de prueba - el exe .NET funciona muy bien tanto en Windows XP y Windows 7. Sin embargo, el exe VB6 produce el siguiente error en XP :

Esta aplicación no se ha podido iniciar 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 pudo iniciar 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 evento de registro veo la siguiente entrada:

generar el 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 utilicé para .NET exe, y eso funciona.

RESOLUCIÓN

El compilador de VB6 en efecto, se requiere que el 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 ambos como la respuesta!

+0

No estoy seguro de cuál es tu problema, pero no es el ícono. cada clase de recurso (RT_MANIFEST, RT_ICON) tiene su propio espacio de nombre de identificación. ¿Puedes darnos más del texto del archivo .rc? –

+0

Recuerdo vagamente algo sobre XP y Vista que desean el manifiesto en diferentes identificadores de recursos. intente usar RESOURCE_ID 2, o posiblemente ponga el mismo manifiesto en ID 1 e ID 2. –

+0

@JohnKnoeller Los ID de recursos en realidad tienen un significado y pueden producir resultados diferentes, consulte [aquí] (http://blogs.msdn.com/b /junfeng/archive/2007/06/26/rt-manifest-resource-and-isolation-aware-enabled.aspx) para más detalles. – takrl

Respuesta

8

Curiosamente, tuve que hacer exactamente lo mismo recientemente. Siguiendo los pasos que Christian describió, conseguí que funcionara la primera vez. Para propsperity, aquí está todo el flujo de trabajo Seguí:

  1. creado un archivo RC como se describe en la pregunta original
  2. Creado un app.manifest con el siguiente contenido:

ManifestImage http://img638.imageshack.us/img638/3364/manifesta.png La imagen usada para preservar los caracteres de espacios en blanco, que son MUY IMPORTANTES para que esto funcione. Como se indica en las respuestas anteriores, el tamaño del archivo debe ser un múltiplo de 4.

  1. Ran rc.exe como se describe en la pregunta original en contra del rc para generar el archivo .res
  2. editado mi archivo Project.VBP para incluir la siguiente línea en la parte superior:

ResFile32 = "resources.res"

  1. EXE incorporado en la norma vb6 e entorno. 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:

alt text http://img688.imageshack.us/img688/4879/finalresources.png

Si sigue teniendo problemas, hágamelo saber y voy a compartir todo lo que pueda contigo.Aparte de eso, no estoy seguro de qué decirle aparte de Works on my Machine!

+0

Gracias Mike. No he tenido la oportunidad de probar esto todavía, así que le pregunto: ¿su manifiesto incluye la marca de orden de bytes UTF-8 al inicio del archivo o no? –

+0

Christian - No, no es así. De hecho, Notepad ++ me dice que la codificación en mi archivo app.manifest es ANSI. –

8

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 VB6 IDE 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.

+0

Lo siento, quise decir, rellenar el MANIFEST en un múltiplo de 4. –

+0

Gracias Jim, no lo sabía. Por pura coincidencia, mi entrada de recurso manifiesto ya era un múltiplo exacto de 16 bytes según el visor hexadecimal VS2008. Sospecho que puede ser un problema de codificación. Estoy probando diferentes combinaciones para ver qué funciona, y actualizaré mi publicación más adelante. –

+0

@JimMack Sé que esto es verdad según mi propia experiencia, pero ¿lo ha visto documentado de forma autorizada en cualquier lugar (por ejemplo, por parte de Microsoft)? –

6

El uso del Resource Compiler (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. The Manifest Tool (mt.exe) se escribió específicamente para incrustar 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: Yo personalmente he estado usando esto en un proceso de construcción automatizado con los ejecutables 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.

+0

Gracias John, siempre es útil saber sobre herramientas como esta. –

Cuestiones relacionadas