L'app non funziona con le DLL VS 2008 SP1, la versione precedente funziona con le versioni RTM

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

  •  09-06-2019
  •  | 
  •  

Domanda

Dal momento del passaggio da Visual Studio 6 a Visual Studio 2008, abbiamo utilizzato MFC90.dll e msvc[pr]90.dlls insieme ai file manifest in una configurazione affiancata privata in modo da non preoccuparci delle versioni o installandoli nel sistema.

Prima dell'SP1 funzionava bene (e funziona ancora bene sui nostri computer di sviluppo).Ora che abbiamo fatto alcuni test post-SP1 mi sto strappando i capelli da ieri mattina.

Prima di tutto, il nostro script di installazione NSIS estrae le DLL e i file manifest dalla cartella redist.Questi non erano più corretti, poiché l'app è ancora collegata alla versione RTM.

Quindi ho aggiunto la definizione for _BIND_TO_CURRENT_VCLIBS_VERSION=1 a tutti i nostri progetti in modo che utilizzino le DLL SP1 nella cartella redist (o successive man mano che escono nuovi service pack).Mi ci sono volute ore per trovarlo.

Ho ricontrollato i file manifest generati nella cartella dei file intermedi dalla compilazione e elencano correttamente le versioni 9.0.30729.1 SP1.Ho ricontrollato e triplicato dipende da una macchina pulita:tutto si collega alle DLL locali senza errori.

L'esecuzione dell'app riceve ancora il seguente errore:

L'applicazione non è stata inizializzata correttamente (0xc0150002).Fare clic su OK per terminare l'applicazione.

Nessuna delle ricerche che ho effettuato su Google o Microsoft ha prodotto nulla che riguardasse i miei problemi specifici (ma ci sono riscontri fino al 2005 con questo messaggio di errore).

Qualcuno ha avuto problemi simili con SP1?

Opzioni:

  • Trova il problema e risolvilo in modo che funzioni come dovrebbe (preferito)
  • Installa il redist
  • estrarre le vecchie dll RTM e i file manifest e rimuovere #define per utilizzare quelli attuali.(Li ho in una build di installazione precedente, dal momento che Microsoft li elimina dalla cartella redist!)

Modificare: Ho provato a ricostruire con la definizione disattivata (collegamento alle DLL RTM) e funziona finché le DLL RTM sono installate nella cartella.Se le dll SP1 vengono inserite, viene visualizzato il seguente errore:

c:\Programmi\...\...\X.exe

Impossibile avviare l'applicazione perché la configurazione dell'applicazione non è corretta.Reinstallare l'applicazone potrebbe risolvere questo problema.

Nessun altro ha dovuto affrontare questo problema?

Modificare: Tanto per sorridere, ho scaricato ed eseguito vcredist_x86.exe per VS2008SP1 sul mio computer di prova. Esso lavori.Con le DLL SP1.E la mia app collegata RTM.Ma NON in una distribuzione privata affiancata che funzionava prima di SP1.

È stato utile?

Soluzione

Ho affrontato personalmente questo problema la settimana scorsa e ora mi considero una specie di esperto ;)

Sono sicuro al 99% che non tutte le DLL e le librerie statiche sono state ricompilate con la versione SP1.Devi mettere

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

in ogni progetto che stai utilizzando.Per ogni progetto di dimensioni reali, è molto facile dimenticare qualche piccola libreria che non è stata ricompilata.

Sono disponibili più flag che definiscono a quali versioni eseguire l'associazione;è documentato http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx .In alternativa alle righe precedenti si può anche mettere

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

che si collegherà all'ultima versione di tutte le librerie VC (CRT, MFC, ATL, OpenMP).

Quindi, controlla cosa dice il manifest incorporato.Scarica l'editor di risorse XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.Apri ogni DLL ed exe nella tua soluzione.Guarda sotto "Manifesto tema XP".Verifica che l'attributo "versione" sul lato destro sia "9.0.30729.1".Se è "9.0.21022", alcune librerie statiche stanno inserendo il manifest per la vecchia versione.

Quello che ho scoperto è che in molti casi, Entrambi le versioni erano incluse nel manifest.Ciò significa che alcune librerie utilizzano la versione sp1 e altre no.

Un ottimo modo per eseguire il debug di quali librerie non hanno le direttive del preprocessore impostate:modifica temporaneamente le intestazioni della piattaforma in modo che la compilazione si interrompa quando tenta di incorporare il vecchio manifest.Aprire C:\Programmi\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.Cerca la stringa "21022".In quella definizione, inserisci qualcosa di non valido (cambia 'define' in 'blehbleh' o qualcosa del genere).In questo modo, quando stai compilando un progetto in cui il file _BIND_TO_CURRENT_CRT_VERSION il flag del preprocessore non è impostato, la tua compilazione si fermerà e saprai che devi aggiungerli o assicurarti che siano applicati ovunque.

Assicurati inoltre di utilizzare Dependency Walker in modo da sapere quali DLL vengono inserite.La soluzione più semplice è installare una nuova copia di Windows XP senza aggiornamenti (solo SP2) su una macchina virtuale.In questo modo sai con certezza che non c'è niente nella cartella SxS che viene utilizzato al posto delle DLL affiancate che hai fornito.

Altri suggerimenti

Per comprendere il problema, penso che sia importante rendersi conto che esistono quattro numeri di versione coinvolti:

  • (A) La versione dei file di intestazione VC in cui è compilato il file .exe.
  • (B) La versione del file manifest incorporato nella sezione delle risorse di quel file .exe.Per impostazione predefinita, questo file manifest viene generato automaticamente da Visual Studio.
  • (C) La versione delle .DLL VC (parte dell'assembly side-by-side) copiata nella stessa directory del file .exe.
  • (D) La versione dei file manifest VC (parte dell'assembly side-by-side) copiata nella stessa directory del file .exe.

Sono disponibili due versioni delle DLL di VC 2008:

  • v1:9.0.21022.8
  • v2:9.0.30729.4148

Per chiarezza, utilizzerò la notazione v1/v2.La tabella seguente mostra una serie di possibili situazioni:

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

I risultati di queste situazioni quando si esegue il file .exe su un'installazione pulita di Vista SP1 sono:

  • Situazione 1:viene visualizzato un popup che dice:"Impossibile individuare il punto di ingresso della procedura XYZXYZ nella libreria di collegamento dinamico".

  • Situazione 2:sembra che non accada nulla quando si esegue il file .exe, ma il seguente evento viene registrato nel "Visualizzatore eventi/Registro applicazione" di Windows:

    Generazione del contesto di attivazione non riuscita per "C:\Path\file.exe".Errore nel file manifest o dei criteri "C:\Path\Microsoft.VC90.CRT.MANIFEST" alla riga 4.L'identità del componente trovata nel manifest non corrisponde all'identità del componente richiesto.Il riferimento è Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8".La definizione è Microsoft

  • Situazione 3:tutto sembra funzionare bene.Questo è la soluzione di remicles2.

  • Situazione 4:questo è come dovrebbe essere fatto.Purtroppo, come indica Roel, può essere piuttosto difficile da implementare.

Ora, la mia situazione (e penso che sia la stessa di crashmstr's) è il numero 1.Il problema è che Visual Studio per un motivo o per l'altro genera codice client (A) per v2, ma per un motivo o per l'altro genera un file manifest v1 (B).Non ho idea di dove sia possibile configurare la versione (A).

Nota che tutta questa spiegazione è ancora nel contesto di assemblee private.

Aggiornamento:finalmente inizio a capire cosa sta succedendo.Apparentemente, Visual Studio genera il codice client (A) per v2 per impostazione predefinita, contrariamente a quanto ho letto su alcuni blog Microsoft.Il flag _BIND_TO_CURRENT_VCLIBS_VERSION seleziona solo la versione nel file manifest generato (B), ma questa versione verrà ignorata durante l'esecuzione dell'applicazione.

Conclusione

Un file .exe compilato da Visual Studio 2008 si collega alle versioni più recenti delle DLL VC90 per impostazione predefinita.Puoi utilizzare il flag _BIND_TO_CURRENT_VCLIBS_VERSION per controllare quale versione delle librerie VC90 verrà generata nel file manifest.Ciò infatti evita la situazione 2 in cui viene visualizzato il messaggio di errore "il manifesto non corrisponde all'identità del componente richiesto".Spiega anche perché la situazione 3 funziona correttamente, poiché anche senza il flag _BIND_TO_CURRENT_VCLIBS_VERSION l'applicazione è collegata alle versioni più recenti delle DLL VC.

La situazione è ancora più strana con gli assembly affiancati pubblici, in cui è stato eseguito vcredist, inserendo le DLL VC 9.0 nella directory SxS di Windows.Anche se il file manifest dell'exe indica che devono essere utilizzate le versioni precedenti delle DLL (questo è il caso quando il flag _BIND_TO_CURRENT_VCLIBS_VERSION non è impostato), Windows ignora questo numero di versione per impostazione predefinita!Invece, Windows utilizzerà una versione più recente se presente nel sistema, tranne quando un "file di configurazione dell'applicazione" si usa.

Sono l'unico a pensare che questo sia fonte di confusione?

COSÌ In sintesi:

  • Per gli assembly privati, utilizzare il flag _BIND_TO_CURRENT_VCLIBS_VERSION nel progetto .exe e Tutto progetti .lib dipendenti.
  • Per gli assembly pubblici ciò non è necessario, poiché Windows selezionerà automaticamente la versione corretta delle DLL dalla directory SxS.

Mi sono appena ricordato di un altro trucco che ho usato per scoprire quali librerie statiche si comportavano male:'grep' attraverso le librerie statiche per la stringa '21022'.TUTTAVIA, non utilizzare gli strumenti grep "normali" come Wingrep perché non ti mostreranno queste stringhe (pensano che sia un file binario e cercano la stringa grezza, non Unicode).Usa l'utilità 'strings' dal Resource Kit (ora nel sito Russinovich, credo).Quello eseguirà il grep attraverso i binari ok.Quindi lasci che queste "stringhe" passino attraverso l'intero albero dei sorgenti e vedrai i file binari (dll e librerie statiche) che contengono riferimenti al manifest sbagliato (o al manifest con la versione sbagliata al suo interno).

Un altro strumento utile per visualizzare i manifest exe e dll è Vista manifesta, che opportunamente non funzionerà con un'installazione pulita di XP, perché Esso dipende da 9.0.21022.

Per la terza opzione, probabilmente puoi trovare le DLL e i manifest per la versione 9.0.21022 nella directory C:\WINDOWS\WinSxS sul tuo computer di sviluppo.Se puoi, puoi configurare la tua directory redist e installare quei file con la tua app.

In alternativa, puoi utilizzare quelli 9.0.30729.1 forniti con Visual Studio e falsificare il manifesto installato con l'app per segnalare che fornisce le DLL 9.0.21022 e non 9.0.30729.1.Al linker di runtime non sembra importare.Guarda questo blog, che è stato estremamente utile per risolvere questi problemi, per ulteriori informazioni.

Entrambe le soluzioni alternative hanno risolto i problemi riscontrati con la distribuzione delle DLL come assembly privati ​​con VS2008 Express.

La risposta di Roel è la strada da percorrere per la tua prima opzione ("aggiustala bene"), ma se dipendi da una libreria che dipende da 9.0.21022 (e il tuo manifest quindi elenca entrambe le versioni), allora la terza opzione potrebbe essere l'unica strada da percorrere se non vuoi eseguire vcredist_x86.exe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top