Selbstgemachter Manifest-Ärger…

In dem C++.de Forum kam dieser Thread Sehr spezielles Problem – (DLL + Manifest) auf!

Man muss den Thread nicht ganz lesen, ich will hier eine kurze Übersicht geben, wie man ein Projekt verbiegen kann, dass es nur noch Ärger macht, den man nur schwer (oder nach langem Suchen) in den Griff bekommt.

Ursprüngliches Problem:
Es ging mal wieder darum eine EXE so zu schreiben, dass Sie nicht von einer VC-2005 Runtime Library Installation (CRT+MFC) abhängig ist. Es ging um ein spezielles Plugin (also eine DLL).

Die Empfehlung war, wie so oft bei Manifest Problemen:
Linke sowohl CRT als auch MFC statisch.

Begründung:
Die DLL benötigt keine weiteren DLLs oder Third Party Libs. Ist also mehr oder weniger standalone. Also warum noch zusätzliche Abhängigkeiten schaffen. Auch wenn dies etwas mehr Hauptspeicher kostet, wenn andere Applikationen die 8.0 Runtime-Libs auch gleichzeitig verwenden können.
Es erübrigt die Installation der VCRedist_x86.exe oder auch andere, komplexere Tricks wie die applikationslokale Installation der Runtime-Libs.

Folgeproblem:
Sowohl für die MFC als auch für die CRT wurde nun statisches Linken im Projekt eingestellt. Aber dennoch wurde weiterhin ein Manifest erzeugt, das die CRT anforderte.
Das erzeugte doch nun einiges Rätselraten bei mir. 😕
Auch die Projektdatei, die mir zugesandt wurde brachte auf den ersten Blick keinen Aufschluss über das Problem.
Weitere Prüfung mit DUMPBIN ergab, dass die Objekt Dateien alle mit einem Manifest Eintrag kompiliert wurden, oder in anderen Worten, das im Sourcecode ein #pragma comment manifest Eintrag drin steht.

Lösung:
Einze kurze Recherche in der crtdefs.h ergab, dass die #pragma Einträge für die Manifeste nur erzeugt werden wenn, _DLL definiert wird. Die Doku sagt klar:

  1. Das ist eine interne, vordefinierte Präprozessor Variable
  2. Diese ist nur bei den Kompileroptionen /MD und /MDd definiert

Derjenige, der dieses Projekt erzeugt hat, hat auch die Präprozessor Variable _DLL vordefiniert. Das Resultat war natürlich, dass Manifest-Einträge erzeugt wurden und weiterhin die CRT-DLLs genutzt wurden.

Merke: Pfusche nie mit internen Nachrichten, Präprozessor-Variablen rum, die einen nichts angehen. Oft genug sind schnelle Workarrounds die man mit so etwas erreicht ein Schuss ins eigene Knie. 🙂

Ach ja! Man hätte übrigens noch weiter Pfuschen können und _CRT_NOFORCE_MANIFEST definieren können :mrgreen: ! Dann hätten wir den einen Pfusch mit einem anderen behoben!

Erste (durchaus positive) Kontakte mit Orcas Beta1 VPC

Ich habe mir mal die Orcas Beta 1 für VPC heruntergeladen und versuche gerade mal, ein paar meiner größeren Projekte damit zu kompilieren.

1. Erfahrung: Ich habe ein VC-2005 Projekt geöffnet um es zu konvertieren. Orcas stürzt ohne Fehlermeldung ab. Erst beim zweiten Versuch klappt es. Gleicher Effekt bei einem anderen Projekt. Scheint irgendwie an den bestehenden temporären Projektdateien zu liegen. Bugreport wurde gesendet. Dem muss ich nochmal nachgehen.

2. Erfahrung: Der Platform SDK Include-Pfad ist in den VS-Einstellungen nicht definiert.
Resultat: Die Datei msdaguid.h wurde nicht gefunden bei einem Programm, dass die ATL OLE-DB Client Templates verwendet. Scheint ein Known-Bug des verwendeten Vista SDKs zu sein. Also am Besten die entsprechenden Einträge konform wie in VS-2005 erzeugen. Man sollte auch gleich das BIN und LIB Verzeichnis kontrollieren. Sonst wundert man sich beim Linken und wenn andere SDK Tools – wie mc.exe – verwendet werden sollen.

3. Erfahrung: Ein Breaking Change für mich. CWnd::GetMenu war bisher nicht virtuell. Jetzt wurde diese Funktion in der neuen MFC 9.0 virtuell. Die Folge: Eine meiner Fensterklassen definierte selbst GetMenu mit HMENU als Returnwert. Ja so was soll man nicht machen, aber man kann es, solange die Funktion nicht virtuell ist. Das Projekt kompiliert nicht mehr.

4. Erfahrung: Ein mittelgroßes Projekt das von VC-2005 umgestellt wurde (ca. 400 Source und Header-Dateien) kompilierte ohne weiteren Fehler. Das macht doch Hoffnung 🙂

Download der Beta1 hier: Visual Studio Code Name „Orcas“ Downloads

MSI.LIB fehlt in VC-2005 Installation

Das verstehe mal wieder wer will 😕 ich verstehe es auf jeden Fall mal nicht.

Die MSI.H Include-Datei  findet sich in der im $(VCInstallDir)PlatformSDK\include Verzeichnis. Die dazu passende MSI.LIB Datei dagegen ist dagegen in $(VCInstallDir)PlatformSDK\lib nicht zu finden. Da spielt es auch keine Rolle ob man VS-2005 RTM oder SP1 hat.

Man muss sich diese Datei aus einem aktuellen SDK besorgen.

Alle Version ab VC6, über VS.NET 2002+2003 verfügen sowohl über Header als auch Lib-Datei.

Heath Stewart beschreibt das zwar in seinem Blog, aber warum das so ist steht dort nicht.

Wie einen Prozess unter Vista mit gehobenen Rechten starten?

Was macht man eigentlich wenn man einen Prozess unter Vista hat, der mit normalen Rechten arbeitet, nun aber einen Prozess starten möchte, der angehobene Rechte (elevated) benutzen soll? Also quasi eine Abkürzung für „rechter Mausklick -> Als Administrator ausführen“.

Das ist ausgesprochen einfach! Man verwendet ShellExecute oder ShellExecuteEx mit dem neuen Verb „runas“.

Der nachfolgende Code startet die Systemsteuerung mit angehobenen (administrativen/elevated) Rechten. Vorher erfolgt natürlich die allseits bekannte UAC Nachricht. Ist der User kein Administrator bekommt er eine Meldung, dass er sich entsprechend anmelden soll. Ansonsten muss er dem Zugriff zustimmen. Bricht der User den Dialog ab wird nichts ausgeführt.

int _tmain(int argc, _TCHAR* argv[])
{
  SHELLEXECUTEINFO shExecInfo;
  
  shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  shExecInfo.fMask = NULL;
  shExecInfo.hwnd = NULL;
  shExecInfo.lpVerb = _T(„runas“);
  shExecInfo.lpFile = _T(„control.exe“);
  shExecInfo.lpParameters = NULL;
  shExecInfo.lpDirectory = NULL;
  shExecInfo.nShow = SW_SHOW;
  shExecInfo.hInstApp = NULL;
  
  ShellExecuteEx(&shExecInfo);
  return 0;
}

❗ PS: Übrigens versteht auch Windows 2003 Server und Windows XP das „runas“ Verb. In diesem Fall wird der entsprechende Anmeldedialog gezeigt, der es erlaubt den aktuellen Benutzer zu verwenden (mit evtl. eingeschränkten Rechten), oder eben einen anderen Account. Nett! 🙂
Nur scheinbar auch ein Feature, dass wieder mal nicht dokumentiert ist.

CFormView in einem CSplitterWnd will keine Mouse Wheel Nachrichten

Wieder mal ein netter Bug in der MFC (VC-2003 Vers. 7.1 und VC-2005 Vers. 8.0).

Platziert man ein CFormView in einem CSplitterWnd dann werden trotz sichtbarer Rollbalken, alle Mouse Wheel Nachrichten geschluckt und ignoriert.
Nachvollziehen kann man das einfach:

  • SDI Applikation im Explorer Stil erzeugen
  • Rechtes Fenster als CFormView
  • Anwendung so klein machen, dass im CFromView ein vertikaler Rollbalken erscheint.
  • Nun versuchen mit dem Mausrad zu rollen.
  • No chance…

Ursache ist der folgende Code in CScrollView:

BOOL CScrollView::OnMouseWheel(UINT fFlags, short zDelta, CPoint point)
{
 // we don’t handle anything but scrolling
 if (fFlags & (MK_SHIFT | MK_CONTROL))
  return FALSE;
 // if the parent is a splitter, it will handle the message
 if (GetParentSplitter(this, TRUE))
  return FALSE;
 // we can’t get out of it–perform the scroll ourselves
 return DoMouseWheel(fFlags, zDelta, point);
}

Wie man unschwer sieht wird bei einem Parent, dass ein CSplitterWnd ist, die Nachricht immer ignoriert. Korrekt wäre dies nur, wenn der Scrollbar nicht dem CScrollView gehört sondern dem CSplitterWnd. Das ist aber bei einem Konstrukt wie hier selten.

Workarround ist relativ simpel!
Einfach selber einen eigenen OnMouseWheel Handler erzeugen, der so aussieht:

BOOL CMyFromView::OnMouseWheel(UINT fFlags, short zDelta, CPoint point)
{
 // we don’t handle anything but scrolling
 if (fFlags & (MK_SHIFT | MK_CONTROL))
  return FALSE;
 // we can’t get out of it–perform the scroll ourselves
 return DoMouseWheel(fFlags, zDelta, point);
}

Hier der Report in connect!
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=276053

❗ PS: Das Problem tritt natürlich auch in anderen Klassen auf die von CScrollView abgeleitet werden!

PRJ0041 in einem simplen Win32 Projekt in VC-2005

Ich habe ein ganz billiges Win32 API Projekt, dass auf den Bugslayer Utilities von John Robbins basiert. Das Projekt wurde jetzt auf VC-2005 umgestellt.

Keine Probleme aber eigentümliche Meldungen PRJ0041 im Buildlog:

Project : warning PRJ0041 : Cannot find missing dependency ‚winwlm.h‘ for file ‚MyProject.rc‘.  Your project may still build, but may continue to appear out of date until this file is found.
Project : warning PRJ0041 : Cannot find missing dependency ‚macwin32.h‘ for file ‚MyProject.rc‘.  Your project may still build, but may continue to appear out of date until this file is found.
Project : warning PRJ0041 : Cannot find missing dependency ‚macwin32.h‘ for file ‚MyProject.rc‘.  Your project may still build, but may continue to appear out of date until this file is found.
Project : warning PRJ0041 : Cannot find missing dependency ‚macwin32.h‘ for file ‚MyProject.rc‘.  Your project may still build, but may continue to appear out of date until this file is found.
und die Liste geht noch weiter

Die meisten dieser Dateien sind irgendwie für den MAC bestimmt. und im normalen SDK gar nicht vorhanden. Scheinbar kommt der Parser des VS-2005 mit diesen Dateien irgendwienicht klar.

Ausgelöst werden sie offensichtlich durch dem #include der windows.h in den Read-Only Symbols directives:

#define APSTUDIO_HIDDEN_SYMBOLS
#include <windows.h>
#undef APSTUDIO_HIDDEN_SYMBOLS
#include <winver.h>

Ich habe alles mögliche versucht diese Fehler weg zu bekommen, aber irgendwie hat alles nichts gebracht. Und langsam wurde ich ungeduldig länger als 30 Minuten an so einem Seiteneffekt zu verbringen.
Schließlich habe ich zu einem kleinen Trick gegriffen und den Parser überlistet:

#define APSTUDIO_HIDDEN_SYMBOLS
/**/ #include <windows.h>
#undef APSTUDIO_HIDDEN_SYMBOLS
/**/ #include <winver.h>

Jetzt ignoriert der Parser die entsprechenden Include-Dateien und das Projekt erzeugt keine Warnungen mehr und wen interessieren schon die Dependencies der windows.h 🙂 ?

Für was ist eigentlich https://connect.microsoft.com/VisualStudio/feedback noch gut?

Aktuell packt mich so richtig die Wut. 👿 (und ich habe ziemlich viel Geduld)

Ich habe in den letzten Wochen zig-Fehler in den Compilern und Libraries von VC gefunden. Das fängt mit VC-2003 an und den hier geschilderten Fehlern in der MFC (siehe CPropertyPage Bug).
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=270493

Dann habe ich schon mehrere Bugs in VC-2005 gefunden. Unter andrem einige Probleme mit Attributed ATL.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98753
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=275256

Oder auch Fehler im Resource Compiler in allen VC-Versionen.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=252616

Ganz zu Schweigen von so netten Sachen wie nicht funktionierende MT.EXE etc.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=258108 

Diese Liste ist bei weitem nicht vollständig, sondern zeigt nur die Erfahrungen der letzten beiden Monate. Ganz schweigen möchte ich von den Bugs, bei denen ich mich eingemischt habe, weil ich sie bestätigen konnte.

Meine Erfahrungen der letzten Zeit machen mich absolut frustig:

  1. Extrem viele Bugs werden einfach so geschlossen als „Nicht reproduzierbar“
  2. Bugs werden geschlossen ohne auch nur einen Kommentar!
  3. Bugs aus VC-2003 werden grundsätzlich abgewiesen, wenn sie in VC-2005 gelöst sind. Meistens werden sie als „nicht reproduzierbar“ gekenzeichnet.
  4. Bugs aus VC-2005 werden auch nicht mehr angenommen, wenn diese in Orcas gefixt sind. Meistens werden auch sie als „nicht reproduzierbar“ gekenzeichnet.
  5. Ideen, werden oft sofort abgetan, erst wenn man etwas mehr Druck als MVP dahinter legt (was ein normaler User nicht kann), wird etwas mehr darüber nachgedacht.
  6. Liefert man einen Workarround zum Bug eines anderen, wird der Bug oft sofort als gelöst geschlossen.

Stellt sich die Frage: Was gehört denn nach Connect?
Na es gibt ja eine Beschreibung. Auf der Seite: https://connect.microsoft.com/availableconnections.aspx
lesen wir zumindest noch folgenden Text:

Visual Studio and .NET Framework Visual Studio and .NET Framework

Bleibt aber die Frage warum VC-2003 und VC-2005 nicht mehr in diese Kategorie zu fallen scheinen. Ist also nur noch das neueste VC (also Orcas) das eigentliche VC, selbst wenn sich das noch in der Beta befindet?

Für was ist also http://connect.microsoft.com noch gut?

Scheinbar weiß bei Microsoft selbst auch niemand so genau, welche Bugs bei Connect eigentlich eingereicht und wie bearbeitet werden dürfen. Aktuell habe ich eine Anfrage laufen, die klären soll, welche Policy eigentlich hinter Connect steht.

Mein Rat: Verwendet den direkten Weg über den Support. Als MSDN-Abonnement  hat man einige Support-Anfragen frei. Als Certfied Partner 5. Nutzt diese, alles andere scheint aktuell eher Zeitverschwendung und bringt einen nur zur Weißglut.

Es ist frustig, frustig, frustig…

Attributed ATL für OLE-DB-Consumer in VC-2005 (db_command)

Ich habe Attributed ATL für OLE-DB-Consumer sehr nett gefunden und in VC.NET 2002 gleich eingebaut. In VC-2003 war auch alles noch OK.

Jetzt rächt sich meine Inovationsfreude in VS-2005! 😥

  1. Der Syntax von VC-2003 nach VC-2005 hat sich geändert! Aller Parameter müssen jetzt als Strings übergeben werden.
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98753
  2. Der Parameter bulk_fetch in db_command wird nicht mehr verstanden. Egal ob man ihn als String oder als Integer angibt.
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=275256

Mein Rat: Man sollte kein Attributed ATL, so schön es auch ist. Man sollte bei den Standard Templates bleiben. Ist etwas mehr Schreibaufwand, aber:

  1. Leichter zu Debuggen
  2. Kompatibel
  3. Leichter kompatibel zu machen. 😉

Anmerkung zum Schluss:
Aus Gerüchten und Diskussionen bei Microsoft habe ich gehört, dass kein weiteres großes Augenmerk auf Attributed ATL gelegt wird.

Anfänglich als großer Wurf gefeiert. Mit der Möglichkeit in Zukunft vielleicht selbst als Entwickler attributierbare Module erzeugen zu können, scheint es jetzt eher ein Auslaufmodell zu werden.
Es gab zu viele Probleme damit und hat sich in der Entwicklung als kryptisch und schwer zu Testen herausgestellt.

Konfusion durch DS_SHELLFONT == (DS_FIXEDSYS | DS_SETFONT)

Ich habe in einem größeren Projekt nach einem Problem gesucht, dass nach der Umstellung auf UNICODE auftrat. Durch Erzeugen von Dialogen mit älteren Visual Studio Editionen wurden manche Dialoge mit dem nachfolgenden Font Eintrag erzeugt:

FONT 8, „MS Sans Serif“, 0, 0, 0x1

Die Folge war eine inkorrekte Anzeige wenn UNICODE Zeichensequenzen eingegeben wurden.
Richtig wäre der folgende Eintrag, wie ich es haben wollte

FONT 8, „MS Shell Dlg“, 0, 0, 0x0

in Verbindung mit den Flags DS_SETFONT und DS_SHELLFONT.
Im Resource-Editor findet sich dazu eine Extra Eigenschaft „Use System Font“ direkt unter der „Font (Size)“ Eigenschaft.

Was steht nun in der Ressourcen Datei, wenn man „Use System Font“ anklickt?

🙄 STYLE DS_SETFONT | DS_FIXEDSYS | …

Und die Doku in der MSDN sagt zu DS_FIXEDSYS:
Causes the dialog box to use the SYSTEM_FIXED_FONT instead of the default SYSTEM_FONT. This is a monospace font compatible with the System font in 16-bit versions of Windows earlier than 3.0.

😮 Habe ich hier einen Bug im Ressoure-Editor entdeckt? Was soll ein altes Windows 3.0 Flag in meinem 32bit Programm?

Die Antwort lautet: Nein!
Das ganze klärt sich auf, wenn man die Definitionen dieser Werte ansieht:

#define DS_SETFONT 0x40L /* User specified font for Dlg controls */
#define DS_FIXEDSYS 0x0008L
#define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS)

Es ist nur einfach verwirrend, weil der Resource Editor aus der Eigenschaft „Use System Font“ und dem Font „MS Shell Dlg“ die Flags DS_SETFONT | DS_FIXEDSYS im STYLE Eintrag macht und die Bits einzeln auflöst.
Es ist natürlich alles OK, aber wirklich sehr verwirrend, aber ich wiederhole mich.

Upps… über 10.000 posting in microsoft.public.de.vc

Meine Güte wo ist die Zeit hin.
Seit 1998 bin ich nun in der Gruppe nntp://microsoft.public.de.vc aktiv und jetzt sind schon über 10.000 Postings aufgelaufen.

Leider sind die Hochzeiten dieser Gruppe wirklich vorbei. Im Jahr 2001 hatten wir zu Boomzeiten über 2200 Posts pro Monat. Das hat sich gedrittelt. Sind evtl. auch die Zeiten für C++ gezählt?
Wahrscheinlich ist dies einfach ein Microsoft Trend der durch den übergroßen .NET Hype ausgelöst wurde. Wer hatte beim Start von VS.NET 2002 geahnt das C# wirklich so schnell eine Trendsprache wird… Ich hätte es nicht gedacht. Spricht hier etwa Melancholie? 😉

Quelle http://groups.google.de/group/microsoft.public.de.vc/about

PS: Es ist interessant über so lange Zeit hinweg immer wieder festzustellen, dass manche Menschen, die ich über die Gruppen kennen lernen durfte nicht nur im Computer existieren; dass manche sogar ein Gesicht haben und ein Real Life, in dem ich auch die Chance sie zu treffen…