Aplikacja nie działa z bibliotekami DLL VS 2008 SP1, poprzednia wersja działa z wersjami RTM

Od czasu przejścia z Visual Studio 6 Na Visual Studio 2008 używamy MFC90.dll i msvc [pr]90.biblioteki DLL wraz z plikami manifest w prywatnej konfiguracji obok siebie, aby nie martwić się o wersje lub instalowanie ich w systemie.

Pre-SP1, to działało dobrze (i nadal działa dobrze na naszych maszyn deweloperskich). Teraz, gdy zrobiliśmy kilka testów po SP1, od wczoraj rano wyrywam włosy.

Po pierwsze, nasz skrypt instalatora NSIS pobiera pliki DLL i manifest z folderu redist. Nie były one już poprawne, ponieważ aplikacja nadal łączy się z wersją RTM.

Dodałem więc definiowanie dla _BIND_TO_CURRENT_VCLIBS_VERSION=1 do wszystkich naszych projektów, aby korzystały z bibliotek DLL SP1 w folderze redist (lub kolejnych, gdy pojawią się nowe pakiety serwisowe). Szukanie tego zajęło mi godziny.

Dwukrotnie sprawdziłem wygenerowane pliki manifestu w folderze pliki pośrednie z kompilacji i poprawnie wyświetlają 9.0.30729.1 SP1 wersje. Sprawdziłem podwójnie i potrójnie, zależy od czystej Maszyny: wszystko łączy się z lokalnymi bibliotekami DLL bez błędów.

Podczas uruchamiania aplikacji nadal występuje następujący błąd:

Nie udało się poprawnie zainicjować aplikacji (0xc0150002). Kliknij OK, aby zakończyć aplikację.

Żadne z wyszukiwań, które zrobiłem w google lub microsoft nie ma nic, co odnosi się do moich konkretnych problemów (ale są hity z powrotem do 2005 z tym komunikat o błędzie).

Ktoś miał podobny problem z SP1?

Opcje:

  • znajdź problem i napraw go tak, aby działał tak, jak powinien (preferowane)
  • zainstaluj redist
  • wykop stare biblioteki DLL RTM i pliki manifestu i usuń # define, aby użyć obecnych. (Mam je we wcześniejszej kompilacji instalatora, Ponieważ Microsoft wyrzuca je z folderu redist!)

Edit: próbowałem ponownie budować z wyłączonym define (link do bibliotek DLL RTM), i to działa tak długo, jak biblioteki DLL RTM są zainstalowane w folderze. Jeśli biblioteki DLL SP1 zostaną upuszczone, zostanie wyświetlony następujący błąd:

C:\Program Files\...\...\X.exe

Ta aplikacja nie została uruchomiona, ponieważ konfiguracja aplikacji jest nieprawidłowa. Ponowna instalacja aplikacji może rozwiązać ten problem.

Czy nikt inny nie miał do czynienia z tym problemem?

Edit: tylko dla grinów, ściągnąłem i uruchomiłem vcredist_x86.exe dla VS2008SP1 na mojej maszynie testowej. Informatyka Działa. Z bibliotekami DLL SP1. I moja aplikacja powiązana z RTM. Ale nie W prywatnej dystrybucji side-by-side, która działała przed SP1.

Author: crashmstr, 2008-09-12

5 answers

Sam walczyłem z tym problemem w zeszłym tygodniu i teraz uważam się za eksperta;)

Jestem w 99% pewien, że nie wszystkie biblioteki DLL i biblioteki statyczne zostały przekompilowane z wersją SP1. Musisz umieścić

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

Do każdego projektu, którego używasz. Dla każdego projektu o rzeczywistej wielkości, bardzo łatwo jest zapomnieć o małej lib, która nie została przekompilowana.

Jest więcej flag, które określają, do jakich wersji należy się wiązać; jest to udokumentowane na http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx . Jako alternatywę dla powyższych linii Możesz również umieścić

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

Który będzie wiązał się z najnowszą wersją wszystkich bibliotek VC (CRT, MFC, ATL, OpenMP).

Następnie sprawdź, co mówi osadzony manifest. Pobierz edytor zasobów XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm . Otwórz wszystkie dll i exe w Twoim rozwiązaniu. Zajrzyj pod "Manifest motywu XP". Sprawdź, czy atrybut "version" na prawa strona to "9.0.30729.1". Jeśli jest to '9.0.21022' , jakaś statyczna biblioteka pobiera manifest dla starej wersji.

Odkryłem, że w wielu przypadkach, obie wersje były zawarte w manifeście. Oznacza to, że niektóre biblioteki używają wersji sp1, a inne nie.

Świetny sposób na debugowanie bibliotek, które nie mają ustawionych dyrektyw preprocesora: tymczasowo zmodyfikuj nagłówki platformy, aby kompilacja zatrzymała się, gdy próbuje osadzić Stary manifest. Open C:\Program Files \ Microsoft Visual Studio 9.0 \ VC \ crt \ include \ crtassem.H. wyszukaj ciąg "21022". W tym zdefiniuj, umieść coś nieprawidłowego (Zmień 'define' na 'blehbleh' lub tak). W ten sposób, gdy kompilujesz projekt, w którym znacznik preprocesora _BIND_TO_CURRENT_CRT_VERSION nie jest ustawiony, kompilacja zostanie zatrzymana i będziesz wiedział, że musisz je dodać lub upewnić się, że jest stosowany wszędzie.

Upewnij się również, że używasz Dependency Walker, aby wiedzieć, jakie biblioteki DLL są wciągane. Najłatwiej jest zainstaluj świeżą kopię systemu Windows XP bez aktualizacji (tylko SP2) na maszynie wirtualnej. W ten sposób masz pewność, że w folderze SxS nie ma nic, co jest używane zamiast dostarczanych bibliotek DLL obok siebie.

 40
Author: Roel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 09:19:35

Aby zrozumieć problem, myślę, że ważne jest, aby uświadomić sobie, że istnieją cztery numery wersji :

  • (A) Wersja plików nagłówkowych VC, do którejexe jest kompilowany.
  • (B) Wersja pliku manifestu, który jest osadzony w sekcji zasobów tego.exe. Domyślnie ten plik manifestu jest automatycznie generowany przez Visual Studio.
  • C) wersja VC .Biblioteki DLL (część zespołu side-by-side) kopiujesz w tym samym katalog jako ... exe.
  • (d) Wersja plików manifestu VC (część zestawu side-by-side) kopiowana w tym samym katalogu co .exe.

Istnieją dwie wersje DLL VC 2008 w uruchomieniu:

  • v1: 9.0.21022.8
  • v2: 9.0.30729.4148
Dla jasności użyję notacji v1/v2. Poniższa tabela przedstawia kilka możliwych sytuacji:
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

Wyniki tych sytuacji podczas uruchamiania .exe na czystym Instalacja Vista SP1 to:

  • Sytuacja 1: wyświetlane jest wyskakujące okienko z napisem: "punkt wejścia procedury XYZXYZ nie może być zlokalizowany w bibliotece linków dynamicznych".

  • Sytuacja 2: wydaje się, że nic się nie dzieje podczas uruchamiania .exe, ale następujące zdarzenie jest rejestrowane w Windows '"Event Viewer / Application log":

    Generowanie kontekstu aktywacji nie powiodło się dla "C:\Path\file.exe".Błąd w pliku manifestu lub polityki "C:\Path\Microsoft.VC90.CRT.MANIFEST" na 4. Komponent tożsamość znaleziona w manifeście nie odpowiada tożsamości żądanego komponentu. Referencja jest Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8". Definition is Microsoft

  • Sytuacja 3: wszystko wydaje się działać dobrze. To jest rozwiązanie remicles2 .

  • Sytuacja 4: to jest Jak to powinno być zrobione . Niestety, jak wskazuje Roel, może być raczej trudno wdrożenie.

Teraz Moja sytuacja (i myślę, że jest taka sama jak crashmstr ' S) jest nr 1. Problem polega na tym, że Visual Studio z tego czy innego powodu generuje kod klienta (A) dla v2, ale z tego czy innego powodu generuje plik manifestu v1 (B). Nie mam pojęcia gdzie można skonfigurować wersję (A).

zauważ , że całe to wyjaśnienie jest nadal w kontekście prywatnych zgromadzeń .

Update: wreszcie zaczynam rozumieć co się dzieje? Najwyraźniej, Visual Studio domyślnie generuje kod klienta (a) dla v2, W przeciwieństwie do tego, co czytałem na niektórych blogach Microsoftu. Znacznik _BIND_TO_CURRENT_VCLIBS_VERSION wybiera tylko wersję w wygenerowanym pliku manifestu (B), ale ta wersja będzie ignorowana podczas uruchamiania aplikacji.

Podsumowanie

An .exe skompilowany przez Visual Studio 2008 domyślnie łączy się z najnowszymi wersjami bibliotek DLL VC90. Możesz użyć Znacznik _bind_to_current_vclibs_version do kontrolowania, która wersja bibliotek VC90 zostanie wygenerowana w pliku manifestu. To rzeczywiście pozwala uniknąć sytuacji 2, w której pojawia się komunikat o błędzie "manifest nie pasuje do tożsamości żądanego komponentu". Wyjaśnia również, dlaczego situation 3 działa poprawnie, ponieważ nawet bez flagi _BIND_TO_CURRENT_VCLIBS_VERSION aplikacja jest powiązana z najnowszymi wersjami bibliotek DLL VC.

Sytuacja jest jeszcze dziwniejsza z publicznymi side-by-side assemblies, gdzie uruchomiony został vcredist, umieszczając biblioteki DLL VC 9.0 w katalogu Windows SxS. Nawet jeśli .plik manifest exe stwierdza, że stare wersje bibliotek DLL powinny być używane (tak jest w przypadku, gdy znacznik _BIND_TO_CURRENT_VCLIBS_VERSION nie jest ustawiony), Windows domyślnie ignoruje ten numer wersji! Zamiast tego System Windows będzie używał nowszej wersji, jeśli jest obecna w systemie, z wyjątkiem , gdy używany jest "plik konfiguracyjny aplikacji" .

Czy tylko ja uważam, że to mylące?

Więc w podsumowaniu :

  • dla zestawów prywatnych, użyj znacznika _BIND_TO_CURRENT_VCLIBS_VERSION w .projekt exe i wszystkie zależne .lib projects.
  • W przypadku zgromadzeń publicznych nie jest to wymagane, ponieważ system Windows automatycznie wybierze poprawną wersję .Biblioteki dll z katalogu SxS.
 14
Author: Dimitri C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:00:17

Przypomniałem sobie kolejną sztuczkę, której użyłem, aby dowiedzieć się, które biblioteki statyczne źle się zachowują: 'grep' poprzez biblioteki statyczne dla ciągu '21022'. Jednak nie używaj 'normalnych' narzędzi grepa, takich jak wingrep, ponieważ nie pokażą ci tych ciągów (uważają, że jest to plik binarny i szukają surowego, nie-unicode). Użyj narzędzia 'strings' z resource kit (teraz chyba na stronie Russinovich). Ten przejrzy binaria ok. Więc puściłeś te "struny" w całym drzewie źródłowym zobaczysz pliki binarne (biblioteki DLL i biblioteki statyczne), które zawierają odniesienia do niewłaściwego manifestu (lub do manifestu z niewłaściwą wersją).

 4
Author: Roel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:04:12

Kolejnym ładnym narzędziem do przeglądania manifestów EXE i dll jest Manifest View, który słusznie nie będzie działał na czystej instalacji XP, ponieważ to zależy od 9.0.21022.

 4
Author: remicles2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-14 17:17:14

Dla trzeciej opcji, prawdopodobnie znajdziesz DLL i manifesty dla wersji 9.0.21022 w C:\WINDOWS\WinSxS katalog na Twojej maszynie deweloperskiej. Jeśli możesz, możesz skonfigurować własny katalog redist i zainstalować te pliki za pomocą aplikacji.

Alternatywnie możesz użyć 9.0.30729.1 dostarczanych z Visual Studio i sfałszować manifest, który instalujesz za pomocą aplikacji, aby zgłosić, że dostarcza biblioteki DLL 9.0.21022, a nie 9.0.30729.1. Linker runtime nie wydaje się umysł. Zobacz ten blog, który był niezmiernie pomocny w rozwiązywaniu tych problemów, aby uzyskać więcej informacji.

Oba obejścia rozwiązały problemy, które miałem z wdrożeniem bibliotek DLL jako prywatnych zestawów z VS2008 Express.

Odpowiedź Roela jest drogą do pierwszej opcji ("fix it right"), ale jeśli polegasz na bibliotece, która zależy od 9.0.21022 (a Twój manifest wymienia obie wersje), wtedy trzecia opcja może być jedynym sposobem, aby przejść, jeśli nie chcesz uruchomić vcredist_x86.exe.

 2
Author: remicles2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-14 17:13:33