Manifest-Hölle „…MSVCR80.dll nicht gefunden…“

Mir ist wieder einmal ein Projekt untergekommen, das in der Debug Version nicht starten wollte. Ursache diese Fehlermeldung:
„Die Anwendung konnte nicht gestartet werden, weil MSVCR80.dll nicht gefunden wurde. Neuinstallation der Anwendung könnte das Problem beheben.“

Der Grund für diesen Fehler war in diesem Fall ein Manifest, dass selbst geschrieben wurde und nicht durch den Manifest Compiler erzeugt wurde.

Der Reihe nach:

  • Es wurde ein Projekt gebaut, das eine externe Library benutzte
  • Diese externe Library wurde mit dem selben Compiler erzeugt. Sowohl als Debug, als auch als auch Release Version. (ZLib)
  • Alle Projekte verwenden dynamische Bindung an die CRT.
  • Der Entwickler machte nun aber einen kleinen Fehler. Im Debug Build instruierte er den Linker so, dass die Release Version der Library verwendet wurde. BTW: Ein Grund mehr immer #pragma comment(lib,…) zu verwenden, dann kann man in den Projekteinstellungen keinen Mist machen.
  • Wie ich schon erwähnte wurde nun das Manifest mit der Hand erzeugt um die entsprechenden Abhänigkeiten und auch das Trustinfo Manifest korrekt zusammenzubauen, bzw. weil nicht mit MT.EXE aus dem Vista SDK verwendet wurde (siehe mein Blog).
    Die Release CRT wurde natürlich nicht mit angegeben (obwohl verwendet), aber dessen war sich natürlich keiner im Team bewusst.

Nun kam es zu dem Effekt, dass dieses Projekt im Debug Modus nicht starten wollte, weil die MSVCR80.DLL nicht gefunden wird. Ja und das stimmt, denn diese DLL kann nicht gefunden werden, da Sie nicht in den entsprechenden Manifesten definiert wurde.

Wie findet man so einen Fehler?
Herausbekommen habe ich das durch die Verwendung von DEPENDS.EXE. Damit konnte ich erstmal ermitteln wer, wen, wann laden möchte und wo das Laden letzten Endes fehlschlägt. 
Dann habe ich die entsprechenden Module (DLLs und EXE Dateien) in den Resource-Editor geladen. Dort habe ich die entsprechenden Manifeste kontrolliert.

Nachtrag 22.03.2007 (als Kommentar wird es evtl. übersehen)
Ich habe aktuell auch in einem anderen Fall ähnliches herausbekommen. Hier wurde auch eine alte ZLib-Release Version (und andere) in ein Debug Projekt eingebaut. Nur waren diese Libraries im Projekt nicht mit VS-2005 kompiliert worden, denn sonst wären entsprechende Manifest Einträge eingeflossen. Soweit ich das Projekt sehen konnte wurde _CRT_NOFORCE_MANIFEST auch nicht verwendet, was die Erzeugung der Manifest Einträge verhindert hätte.
Das Resultat auch hier. Eine MSVCRT80.DLL wird vom Linker verlangt, aber es existiert kein Manifest dazu. Die entsprechende gleiche Fehlermeldung auch hier.
Ein Rebuild der entsprechenden Libraries und des Projektes lies das Programm dann zwar starten, aber dennoch wurden in diesem Falle gleichzeitig Debug-CRT und Release-CRT verwendet, was sicher nicht im Sinne der Programmierer war.

Wir lernen daraus wieder einmal: Achte streng auf die Trennung von Release und Debug Libraries. 😉

Gründe für den R6034 bei der VC 8.0 DLL CRT

Warum lässt sich die neue VC 8.0 CRT eigentlich nicht ohne Manifest verwenden?
Schauen wir uns also mal an was passiert wenn eine Applikation oder eine DLL geladen wird, die die VC 8.0 CRT als DLL verwendet:

Die DllMain der CRT wird aufgerufen. Bei der C-Runtime DLL ist dies die Funktion _CRTDLL_INIT die sofort die Funktion __CRTDLL_INIT aufruft.

Diese Funktion sorgt nun der Reihe nach dafür, dass:

  • die aktuelle Windows Version bestimmt wird
  • der Heap initialisiert wird
  • die TLS Bereiche für multithreading angelegt werden
  • das Environment und die Befehlszeile bestimmt werden
  • die MBCS Umwandlungstabellen angelegt werden
  • alles was mit atexit, floating-point math etc. initialisiert wird
  • und… jetzt wird es spannend… die Funktion _check_manifest aufgerufen wird.

In der Funktion _check_manifest wird der Code ausgeführt der zum Runtime Fehler R6034 „The application has attempted to load the runtime library incorrectly. Contact support for more information“ führen kann, nämlich genau dann, wenn diese Funktion FALSE zurück gibt.

Was macht diese Funktion nun?
Im Source-Code der CRT ist dies wunderbar dokumentiert:

  1. if (pre-fusion OS)
      return TRUE; [no need to check]

    Das bedeutet nichts anderes, als das die nachfolgenden Tests nur auf XP/Vista/2003 und folgenden OS durchgeführt werden. Also im Klartext unter Windows 2000 kann dieser Runtime Error nicht auftreten.
  2. if dll is being loaded by instrumented-mscoree.dll.
      return TRUE;
    OK. Ein Speziallfall. Im Kontext der .NET CLR und des Profilers ist auch ales erlaubt. Also wenn sich MSCoree.dll (Microsoft .NET Runtime Execution Engine) und PGORT80.dll (Profile Guided Optimization Instrumentation Runtime) im Speicher befinden ist auch alles paletti.
  3. if (dll is loaded from system32)
      return FALSE;
    Dies ist interessant. In keinem Fall darf diese DLL im Windows\System32 stehen! Oder wenn Sie von dort geladen wird fielgt einem der R6045 um die Ohren.
  4. if (!(loaded through a manifest))
      return FALSE;

    Hier wird über die Funktion FindActCtxSectionStringW geprüft ob diese DLL über ein Manifest geladen wird. ActCtx ist die Abkürzung für Activation Context.
    Wurde kein solcher Activation Context gefunden (also kein Manifest), dass für diese DLL verantwortlich ist, dann heißt das auch R6045.
  5. if (loaded from %SystemRoot%\WinSxS)
      return TRUE; [loaded from the WinSxS cache]

    Wird die DLL aus den Side by Side Verzeichnissen geladen ist schon alles gut.
    Aber auch das geht nur mit gültigem Manifest.
  6. if (manifest is in the same folder as the dll)
      return TRUE;
    Auch das ist interessant. Das Manifest muss zwingend im selben Verzeichnis wie diese DLL liegen, denn sonst sind wir fertig
  7. return FALSE; [loaded with another manifest]
    und nun schlägt das Laden fehl, da das Manifest offensichtlich nicht im DLL Verzeichnis liegt. Auch hier ein R6045.

Zurück noch mal zum Fall 2. Was macht dieser Test „if dll is being loaded by instrumented-mscoree.dll“? Er macht nichts anderes als zu prüfen ob die beiden DLLs im Speicher sind.

BTW: Man könnte nun ganz frech zwei leere DLLs mit diesen Namen erzeugen und diese in ein Projekt implizit laden lassen… und siehe da, die Applikation benötigt auf einmal kein Manifest mehr…
Aber warum sich das ganze verbietet ist auch klar. DLLs mit den oben genannten Namen zu erzeugen, kann ganz schön verwirrend und problematisch werden.
Und warum zwei leere DLLs in einen Prozess laden, wenn es reicht ein Manifest zu ergänzen? 😉

VS-2005 SP1 für Vista bringt kein Update für die MT.EXE

In meinem Beitrag UAC Trustinfo Manifest in ein VC-2005 SP1 Projekt einfügen habe ich berichtet wie man auf einfache Art und Weise ein UAC-Trustinfo-Manifest in ein VS2005 Projekt einbauen kann.

Dazu musste jedoch die MT.EXE aus dem Vista SDK in das entsprechende VC-Programmverzeichnis kopiert werden.

Ich hatte dies auch als Bug gemeldet und habe gehofft, dass dies auch im VS2005 SP1 für Vista noch behoben wird. Dem ist aber nicht so.
Die MT.EXE bleibt unverändert die Datei aus dem SP1 für VS2005. Und damit verbunden bleibt auch weiterhin das Versions Chaos. Wie schon berichtet haben beide Versionen aus dem Vista SDK und dem VS2005 SP1 die gleiche Versionsnummer. Wobei aber nur die Version aus dem Vista-SDK tut was man von ihr erwartet.

Skibo, Young, Johnson: Arbeiten mit Microsoft Visual Studio 2005

Der Titel, ist etwas irreführend. Man muss hier den Untertitel ernst nehmen, der klarer sagt um was es geht: „Mit Makros und individueller Konfiguration Visual Studio 2005 optimieren“. Leider steht dieser Untertitel nirgendwo klar lesbar.
Das muss dem Leser/Interessenten von Anfang an klar sein!
Es geht hier weniger um das Arbeiten mit Visual Studio, als viel mehr um die Möglichkeiten, das bestehende Visual Studio 2005 anzupassen, zu erweitern und durch Makros Und Add-Ins Arbeiten zu automatisieren..

Das Ganze schließt Makros, Add-Ins, Assistenten ein und wir wollen die Starter-Kits nicht vergessen, auf die mich erst dieses Buch hingewiesen hat. Ein großer Part des Buches behandelt von der Erstellung von Add-Ins und später ein weitere großer Teil die Anpassungsmöglichkeiten von Visual Studio durch Makros.
Die Beispiele sind hauptsächlich in C# und bei den Makros natürlich in Visual Basic geschrieben. Man erhält einen relativ guten Einblick in das Objektmodell, das dem Entwickler zur Verfügung steht um Visual Studio an die eigenen oft speziellen Bedürfnisse anzupassen.
Beim „Tieftauchen“ habe ich allerdings gemerkt, dass trotz großem Angebot, doch Manches nicht möglich ist. Das liegt allerdings nicht an dem Buch, sondern an dem was die Entwickler von Microsoft in Visual Studio hineingepackt haben.

Am Ende wird das Buch leider zu einer besseren und ausführlichen Beschreibung der Makro Schnittstellen. Hier wären praktische Beispiele besser als nur zu zeigen wie, was, wo angesprochen wird. Ich vermute, dass die Autoren selbst von den Möglichkeiten überwältigt waren und sich dadurch (leider) auf das Nötigste beschränkten.

Trotz Übersetzung ist der Text flüssig und gut zu lesen, wobei der erste Teil ganz klar besser ist als der letzte. Da ich normalerweise englische Originale bevorzuge muss ich den Übersetzern ein Lob aussprechen. Der Ton hätte sicherlich an manchen Stellen etwas weniger trocken sein können. Aber das lag sicherlich auch an der Vorlage. Ich bin in letzter Zeit etwas mehr Humor auch bei technischen Büchern von MS-Press gewöhnt.

Als C++ Entwickler möchte ich darauf hinweisen, dass viele der beschriebenen Features wie z.B. das Exportieren von Vorlagen in C++ nicht zur Verfügung steht. Auch die sehr interessante Funktion zum Erzeugen von „Community-Content“ und Starter-Kits bleibt leider nur C#, J# und VB Programmierern zugänglich. Ein C++ Programmierer wird also beim Lesen dieses Buches öfters eifersüchtig werden.

3 Sterne

http://www.amazon.de/Arbeiten-Microsoft-Visual-Studio-2005/dp/3866454007

Visual Studio 2005 zeigt keine Symbole für die MFC80U/MFC80UD DLLs

Beim Testen auf meinem Laptop wundere ich mich, dass ich nicht mehr in die MFC80UD.DLL tracen kann. Die Routinen der MFC werden einfach übersprungen, auch, wenn ich mit der F11 einen Step Into machen möchte.
Was ist das? 😕

Ich habe auf meinem Rechner einen Symbolserver eingerichtet. Dazu habe ich eine Environment Variable definiert.
_NT_SYMBOL_PATH=symsrv*symsrv.dll*c:\Temp\localsymbols*http://msdl.microsoft.com/download/symbols

Soweit gut. Unter den Einstellungen im Visual Studio unter Tools -> Options -> Debugging -> Symbols, ist nichts eingetragen.
Das führt nun dazu, dass die Symbole aus dem Internet geladen werden. Dort sind jedoch für die MFC-DLLs keine Symbolinformationen vorhanden. Durch die Installation von Visual Studio befinden sich die Symboldateien unter C:\Windows\Symbols\DLL! Dieses Verzeichnis wird aber nicht mehr durchsucht.

Also einfach das Verzeichnis C:\Windows\Symbols\DLL in die Liste der Symbol-Verzeichnisse als erstes eingetragen und siehe da, alles funktioniert wieder wie gewünscht.

Es geht übrigens in VS 2005 noch eleganter als mit der _NT_SYMBOL_PATH Environment-Variable. Einfach in die Liste der Pfade http://msdl.microsoft.com/download/symbols, des schon erwähnten Dialoges, eintragen.
Wichtig ❗ Natürlich hinter dem Pfad C:\Windows\Symbols\DLL.
Auch das Verzeichnis für den lokalen Cache wird hier unter „Cache symbols from symbol server to this directory“ eingetragen.

Tipp: Sollte evtl. im Cache schon eine Version der MFC80 geladen worden sein, dann muss man diese Version evtl. manuell aus dem Cache entfernen, damit die Version aus C:\Windows\Symbols\DLL verwendet wird.

UAC Trustinfo Manifest in ein VC-2005 SP1 Projekt einfügen

An sich ist die Sache ganz einfach. Man erzeugt eine Manifest-Datei z.B. mit dem Namen Trustinfo.manifest, die nur den entsprechenden <trustinfo> Block enthält (und nicht mehr). Um die anderen Manifest Daten für CRT und COMCTL32 v6.0 kümmert man sich erstmal nicht, das soll ja MT.EXE und der Linker machen. Diese Datei fügt man in das Projekt ein. VS erkennt die Endung und der Manifest-Compiler soll diese Datei nun mit den anderen Manifest Daten mischen und das finale Manifest erzeugen.
Man wirft den Compiler an und… 🙄 … erhält die Fehlermeldung:
.\TrustInfo.manifest : manifest authoring warning 81010002: Unrecognized Element „requestedPrivileges“ in namespace „urn:schemas-microsoft-com:asm.v3“.

Entsprechende Recherche ergab, dass nur die MT.EXE aus dem Vista SDK dieses Manifest korrekt einmischt. Die funktionierende MT.EXE hat es nicht in das 2005 SP1 gepackt 🙁 .

OK also Vista SDK herunterladen installieren. MT.EXE ansehen und… 🙄
Die MT.EXE aus 2005 SP1 ist vom 2006-12-02 07:17,
die MT.EXE aus dem Vista SDK ist vom 2006-10-19 14:52,
beide haben eine Größe von 727.552 Bytes und haben die gleiche Versionsnummer 5.2.3790.2075. Es ist nicht zu fassen.

OK packen wir also trotzdem die MT.EXE aus dem Vista SDK in das Verzeichnis C:\Program Files\Microsoft Visual Studio 8\VC\bin

Nun kompilieren wir das Projekt noch einmal und nun… :mrgreen:
wunderbar, das Projekt kompiliert wie erwartet. Das Manifest wird eingefügt. Die erzeugte EXE hat alle entsprechenden Manifeste eingebettet.

Wen es interessiert, die Bug-Meldung bzgl. der Versionsnummer ist hier zu finden:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=258108

Es sei noch angemerkt: Mein Testrechner ist ein Vista-Ultimate Laptop. Installiert war auch das VS-2005 SP1 Beta für Vista. Auch diese Version enthält keine kompatible MT.EXE!
Danke Jochen für den Hinweis!

Was mit Visual Studio 2005 SP1 unter Vista zu beachten ist

Ganz Allgemein hier eine kleine Sammlung wertvoller Links für die Nutzung von Visual Studio 2005 unter Vista. Besonders der zweite Link ist wichtig nach meiner Meinung.

Installationshinweise:
http://support.microsoft.com/kb/929470/en-us

Visual Studio 2005 on Windows Vista Issue List – Running with normal user permissions http://msdn2.microsoft.com/en-us/vstudio/aa972193.aspx

Visual Studio 2005 on Windows Vista Issue List – Running with elevated administrator permissions http://msdn2.microsoft.com/en-us/vstudio/aa964140.aspx

Visual Assist X unter Vista mit VS2005 und SP1

Meine ersten Gehversuche und Test mit VS2005 unter Vista waren gut. Aber da ich mich ohne Visual Assist X gleich fühle als man man mir drei Finger an jeder Hand amputiert hat war ich sehr frustriert als ich merkte, dass VA-X nicht ganz so funktionierte wie es das sonst auf XP tat.

Ein ALT+G, also ein GotoDefinition lies nur einen lästigen Beep hören. Ich befürchtete ohne eine der Hauptfunktionen von VA-X auskommen zu müssen.

Nach einigen Tests merkte ich auch, dass VisualStudio 2005 auch nicht korrekt beendet wurde. Es war zwar nicht mehr sichtbar auf dem Monitor, aber im Taskmanager blieb die Applikation immer noch aktiv und lies sich nur durch den Taskmanager beenden.

Nun das ganze war kein Problem mehr, wenn man VisualStudio mit erweiterten Rechten (also mit Run as Administrator) startet. Aber genau das wollte ich nicht. Zudem mag ich keine überflüssigen Fragen beim Programmstart.

Nach kurzem Nachdenken war mir klar, dass VA-X seine Daten im Programm-Verzeichnis ablegt. Nun und das ist in Vista nun mal nicht gerne gesehen, denn auch als Administator hat man auf diese Verzeichnisse nur mit angehobenen Rechten Schreibzugriff.

Also habe ich die Rechte für das Verzeichnis C:\Programme\Visual Assist X einfach auch für den normalen Benutzer erweitert und auch Änderungsrechte vergeben. Und siehe da, alles funktioniert jetzt ohne Probleme.

BTW: Wer Visual Assist X nicht kennt, der sollte ganz schnell http://www.wholetomato.com besuchen und sich eine Demo besorgen.
Kein Tool mit dem ich arbeite ist so sehr sein Geld wert wie dieses!

Der # operator im RC-Compiler arbeitet inkonsistent

Heute ist mir ein übler Fehler des Ressourcen Compilers untergekommen.

Beabsichtigt war es einen #define in einen Text umzuwandeln, der als Ressourcen-String abgelegt wird.

Das ganze wurde so implementiert:

#define _MYSTRING(x)   #x
#define MYSTRING(x)    _MYSTRING(x)
STRINGTABLE
BEGIN
4713 MYSTRING(0409)
4714 MYSTRING(040E)
END

Alles kein Geheimnis, nur macht der Ressource-Compiler was er will. Der erste String wird korrekt angelegt. Beim zweiten wird wie durch Zauberhand noch eine 0 angehängt.

Das ganze Problem konnte ich auf allen VS-Systemen (VS2003, VS2003SP1, VS2005 und VS2005 SP1) nachvollziehen.

Gemeldet für Microsoff-Feedback unter:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=252616