La aplicación no se ejecuta con las DLL de VS 2008 SP1, la versión anterior funciona con las versiones RTM

StackOverflow https://stackoverflow.com/questions/59635

  •  09-06-2019
  •  | 
  •  

Pregunta

Desde nuestro cambio de Visual Studio 6 a Visual Studio 2008, hemos estado usando MFC90.dll y msvc[pr]90.dll junto con los archivos de manifiesto en una configuración privada en paralelo para no preocuparnos por las versiones. o instalarlos en el sistema.

Antes de SP1, esto funcionaba bien (y todavía funciona bien en nuestras máquinas de desarrollo).Ahora que hemos hecho algunas pruebas post-SP1, me he estado arrancando los pelos desde ayer por la mañana.

En primer lugar, nuestro script de instalación de NSIS extrae los archivos DLL y de manifiesto de la carpeta redist.Estos ya no eran correctos, ya que la aplicación todavía enlaza con la versión RTM.

Entonces agregué la definición para _BIND_TO_CURRENT_VCLIBS_VERSION=1 a todos nuestros proyectos para que utilicen las DLL SP1 en la carpeta redist (o las posteriores a medida que salgan nuevos paquetes de servicio).Me tomó horas encontrar esto.

Revisé dos veces los archivos de manifiesto generados en la carpeta de archivos intermedios de la compilación y enumeran correctamente las versiones 9.0.30729.1 SP1.He comprobado dos y tres veces que depende de una máquina limpia:Todo se vincula a los archivos DLL locales sin errores.

Al ejecutar la aplicación todavía aparece el siguiente error:

La aplicación no pudo inicializarse correctamente (0xc0150002).Haga clic en Aceptar para terminar la aplicación.

Ninguna de las búsquedas que he realizado en Google o Microsoft ha arrojado nada relacionado con mis problemas específicos (pero hay resultados que se remontan a 2005 con este mensaje de error).

¿Alguien tuvo algún problema similar con SP1?

Opciones:

  • Encuentre el problema y solucionelo para que funcione como debería (preferido)
  • Instalar el redist
  • Extraiga los archivos DLL y de manifiesto de RTM antiguos y elimine #define para usar los actuales.(¡Los tengo en una versión del instalador anterior, ya que Microsoft los elimina de su carpeta de redistribución!)

Editar: Intenté reconstruir con la definición desactivada (enlace a DLL de RTM), y eso funciona siempre que los DLL de RTM estén instalados en la carpeta.Si se colocan los archivos DLL de SP1, aparece el siguiente error:

c:\Archivos de programa\...\...\X.exe

Esta aplicación no pudo iniciarse porque la configuración de la aplicación es incorrecta.Reinstalar la aplicación podría resolver el problema.

¿Nadie más ha tenido que lidiar con este problema?

Editar: Solo para sonreír, descargué y ejecuté vcredist_x86.exe para VS2008SP1 en mi máquina de prueba. Él obras.Con las DLL SP1.Y mi aplicación vinculada a RTM.Pero NO en una distribución privada en paralelo que funcionaba antes del SP1.

¿Fue útil?

Solución

Yo mismo luché contra este problema la semana pasada y ahora me considero un experto;)

Estoy 99% seguro de que no todos los archivos DLL y bibliotecas estáticas se volvieron a compilar con la versión SP1.necesitas poner

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

en cada proyecto que estás utilizando.Para cada proyecto de tamaño real, es muy fácil olvidar alguna pequeña biblioteca que no se recopiló.

Hay más indicadores que definen a qué versiones vincularse;está documentado en http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx .Como alternativa a las líneas anteriores, también puedes poner

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

que se vinculará a la última versión de todas las bibliotecas de VC (CRT, MFC, ATL, OpenMP).

Luego, verifique lo que dice el manifiesto incrustado.Descargue el editor de recursos XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.Abra todos los dll y exe de su solución.Busque en 'Manifiesto del tema XP'.Compruebe que el atributo 'versión' en el lado derecho sea '9.0.30729.1'.Si es '9.0.21022', alguna biblioteca estática está incorporando el manifiesto de la versión anterior.

Lo que encontré es que en muchos casos, ambos Las versiones se incluyeron en el manifiesto.Esto significa que algunas bibliotecas usan la versión sp1 y otras no.

Una excelente manera de depurar qué bibliotecas no tienen configuradas las directivas de preprocesador:Modifique temporalmente los encabezados de su plataforma para que la compilación se detenga cuando intente incrustar el manifiesto anterior.Abra C:\Archivos de programa\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.Busque la cadena '21022'.En esa definición, coloque algo no válido (cambie 'definir' a 'blehbleh' más o menos).De esta manera, cuando estás compilando un proyecto donde el _BIND_TO_CURRENT_CRT_VERSION El indicador del preprocesador no está configurado, su compilación se detendrá y sabrá que necesita agregarlos o asegurarse de que se aplique en todas partes.

También asegúrese de utilizar Dependency Walker para saber qué archivos DLL se están incorporando.Es más fácil instalar una copia nueva de Windows XP sin actualizaciones (sólo SP2) en una máquina virtual.De esta manera, estará seguro de que no hay nada en la carpeta SxS que se esté utilizando en lugar de los archivos DLL en paralelo que proporcionó.

Otros consejos

Para entender el problema, creo que es importante darse cuenta de que hay cuatro números de versión involucrados:

  • (A) La versión de los archivos de encabezado VC en los que se compila el .exe.
  • (B) La versión del archivo de manifiesto que está incrustado en la sección de recursos de ese .exe.De forma predeterminada, Visual Studio genera automáticamente este archivo de manifiesto.
  • (C) La versión de los .DLL de VC (parte del ensamblado en paralelo) que copia en el mismo directorio que el .exe.
  • (D) La versión de los archivos de manifiesto de VC (parte del ensamblado en paralelo) que copia en el mismo directorio que el .exe.

Hay dos versiones de las DLL de VC 2008 en ejecución:

  • v1:9.0.21022.8
  • v2:9.0.30729.4148

Para mayor claridad, usaré la notación v1/v2.La siguiente tabla muestra una serie de situaciones posibles:

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

Los resultados de estas situaciones al ejecutar el .exe en una instalación limpia de Vista SP1 son:

  • Situación 1:Se muestra una ventana emergente que dice:"El punto de entrada del procedimiento XYZXYZ no se pudo ubicar en la biblioteca de vínculos dinámicos".

  • Situación 2:Parece que no sucede nada al ejecutar el .exe, pero el siguiente evento se registra en el "Visor de eventos/registro de aplicaciones" de Windows:

    Error en la generación del contexto de activación para "C:\Path\file.exe". Error en el archivo de manifiesto o política "C:\Path\Microsoft.VC90.CRT.MANIFEST" en la línea 4.La identidad del componente encontrada en el manifiesto no coincide con la identidad del componente solicitado.La referencia es Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8".La definición es Microsoft.

  • Situación 3:Todo parece funcionar bien.Esto es la solución de remicles2.

  • Situación 4:esto es como se debe hacer.Lamentablemente, como indica Roel, puede resultar bastante difícil de implementar.

Ahora bien, mi situación (y creo que es la misma que crashmstr) es el número 1.El problema es que Visual Studio, por una razón u otra, genera código de cliente (A) para v2, pero por una razón u otra, genera un archivo de manifiesto v1 (B).No tengo idea de dónde se puede configurar la versión (A).

Nota que toda esta explicación todavía está en el contexto de asambleas privadas.

Actualizar:Finalmente empiezo a entender lo que está pasando.Aparentemente, Visual Studio genera código de cliente (A) para v2 de forma predeterminada, al contrario de lo que he leído en algunos blogs de Microsoft.El indicador _BIND_TO_CURRENT_VCLIBS_VERSION solo selecciona la versión en el archivo de manifiesto generado (B), pero esta versión se ignorará al ejecutar la aplicación.

Conclusión

Un .exe compilado por Visual Studio 2008 se vincula a las versiones más recientes de las DLL de VC90 de forma predeterminada.Puede utilizar la bandera _BIND_TO_CURRENT_VCLIBS_VERSION para controlar qué versión de las bibliotecas VC90 se generará en el archivo de manifiesto.De hecho, esto evita la situación 2 en la que aparece el mensaje de error "el manifiesto no coincide con la identidad del componente solicitado".También explica por qué la situación 3 funciona bien, ya que incluso sin el indicador _BIND_TO_CURRENT_VCLIBS_VERSION la aplicación está vinculada a las versiones más recientes de las DLL de VC.

La situación es aún más extraña con los ensamblados públicos en paralelo, donde se ejecutó vcredist, colocando las DLL de VC 9.0 en el directorio SxS de Windows.Incluso si el archivo de manifiesto del .exe indica que se deben usar las versiones antiguas de las DLL (este es el caso cuando el indicador _BIND_TO_CURRENT_VCLIBS_VERSION no está configurado), Windows ignora ¡Este número de versión es predeterminado!En su lugar, Windows utilizará una versión más reciente si está presente en el sistema, excepto cuando un "archivo de configuración de la aplicación" se utiliza.

¿Soy el único que piensa que esto es confuso?

Entonces en resumen:

  • Para ensamblados privados, use el indicador _BIND_TO_CURRENT_VCLIBS_VERSION en el proyecto .exe y todo proyectos .lib dependientes.
  • Para ensamblados públicos, esto no es necesario, ya que Windows seleccionará automáticamente la versión correcta de los archivos .DLL del directorio SxS.

Acabo de recordar otro truco que utilicé para descubrir qué bibliotecas estáticas se comportaban mal:'grep' a través de las bibliotecas estáticas para la cadena '21022'.SIN EMBARGO, no utilice las herramientas grep "normales" como wingrep porque no le mostrarán estas cadenas (piensan que es un archivo binario y buscan la cadena sin formato, no Unicode).Utilice la utilidad 'cadenas' del kit de recursos (creo que ahora está en el sitio de Russinovich).Ese buscará en los binarios.Entonces, deja que estas 'cadenas' recorran todo el árbol fuente y verás los archivos binarios (dlls y bibliotecas estáticas) que contienen referencias al manifiesto incorrecto (o al manifiesto con la versión incorrecta).

Otra buena herramienta para ver manifiestos exe y dll es Vista de manifiesto, que apropiadamente no se ejecutará en una instalación limpia de XP, porque él Depende de 9.0.21022.

Para su tercera opción, probablemente pueda encontrar las DLL y los manifiestos para la versión 9.0.21022 en el directorio C:\WINDOWS\WinSxS de su máquina de desarrollo.Si puede, puede configurar su propio directorio de redistribución e instalar esos archivos con su aplicación.

Alternativamente, puede usar los 9.0.30729.1 suministrados con Visual Studio y falsificar el manifiesto que instala con su aplicación para informar que proporciona las DLL 9.0.21022 y no 9.0.30729.1.Al vinculador en tiempo de ejecución no parece importarle.Mira esto Blog, que ha sido de gran ayuda para resolver estos problemas, para obtener más información.

Ambas soluciones solucionaron los problemas que tenía al implementar las DLL como ensamblados privados con VS2008 Express.

La respuesta de Roel es el camino a seguir para su primera opción ("arreglarlo bien"), pero si depende de una biblioteca que depende de 9.0.21022 (y su manifiesto, por lo tanto, enumera ambas versiones), entonces la tercera opción puede ser la única. camino a seguir si no desea ejecutar vcredist_x86.exe.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top