Tipps & Tricks: VS-2010 Hilfe aufbohren

Microsoft ist es wirklich gelungen in zwei großen Schritten die VisualStudio Online Hilfe bzw. MSDN Integration von einem brauchbaren Tool in VC6, über VS-2003/5/8 wo es gerade auszuhalten war, in VS-2010 zu einem Ding zu verwandeln, bei dem mir fast die Worte fehlen.
Man schmeiße alle Funktionen des Hilfe-Viewers weg und behalte gerade die F1-Taste… alle Vorteile, die mir als Vorteile verkauft werden (keine separate Installation, alles im gewohnten Browser etc. siehe Video unten), sehe ich nicht als Vorteile gegenüber den Nachteilen, die in Kauf genommen wurden.
Ein vielleicht hartes Urteil, aber es geht seit Jahren in dieser Beziehung leider nur bergab.
– Just my 2 cents – 🙁

Das Erste was ich sofort vermisst habe war in der folgenden Reihenfolge:

  1. Dynamic Help
  2. Table of contents (TOC)
  3. Sync to TOC
  4. Index
  5. Filter
  6. Direkte Suche in VS, oder dem entsprechenden Viewer

Ich bin dann auf im Internet auf die Suche gegangen und wurde mit 2 Tools fündig, die einem hier helfen können:

HelpViewerKeywordIndex

Aber wie angekündigt soll es auch hier Verbesserungen geben. Und das außerhalb der Wartungszyklen des VS (siehe Video unten mit Ryan Linton). Zumindest was den Index betrifft und die Suchmöglichkeit innerhalb von VS betrifft schafft ein kleines Tool von Ryan Linton (wie versprochen seit dem 20.04.) wenigstens etwas Abhilfe, der HelpViewerKeywordIndex.

Mit diesem Tool erhält man zumindest mal wieder den Index und ein Suchfenster in VS.
Auch dass das Sucherergebnis in einen VS-Fenster angezeigt werden kann ist nett. Leider betrifft diese Einstellung nicht die Funktion der F1-Taste. In diesem Fall wird immer noch der externe Browser angeworfen und nicht der interne, oder ich habe die Einstellung nicht gefunden wo man mit der F1-Taste ein Browser Fenster in VS öffnet.
Ganz verstanden habe ich auch die Option „Display TOC in page“ nicht.
Das Tool ist zumindest mal ein kleiner Schimmer eines eventuellen zukünftigen Lichtblicks 😉

Aber wer weiß, vielleicht lässt Version 1.1 von  HelpViewerKeywordIndex nicht lange auf sich warten.

H3Viewer

Mit H3Viewer, von meinem MVP-Kollegen Rob Chandler, bekommt man zumindest mal wieder das, was man in VS-2008 auch hatte. Table of Contents, Sync to contents. Und der Viewer ist nicht im Browser. Mit dem Ding lässt sich leben oder zumindest ersetzt es den Viewer den wir aus VS-2005/8 kannten ziemlich gut. Und ja, es gibt auch hier wieder Bookmarks, die jetzt keine Favoriten Einträge im Browser sein müssen 😉
Besonders gefreut habe ich mich auch über die Funktion im Index die Doubletten zum gleichen Stichwort im Index in einem separaten Fenster wieder angezeigt zu bekommen, denn nicht jeder Treffer zu GetWindowtext ist der den ich suche.
Nett auch die TTS Funktion (Text to Speech)
Hier fehlen jetzt eigentlich nur noch die Filter zum vollständigen Glück.

Aber wer weiß, was Microsoft uns demnächst noch zu bieten hat. Laut der Homepage von H3Viewer hat Microsoft noch bereits einige andere Viewer in der Schublade.

Siehe auch:
http://channel9.msdn.com/posts/kmcgrath/Help-30-New-Help-System-in-Visual-Studio-2010/

Links:
http://visualstudiogallery.msdn.microsoft.com/en-us/4af86641-a302-4edf-9853-007bcc670b30
http://mshcmigrate.helpmvp.com/viewer

VS-2010 steht für MSDN Abonnenten sofort zum Download zur Verfügung

Jetzt wird es ernst 😉
Pünktlich wie angekündigt ist VS-2010 RTM in englisch für MSDN Benutzer verfügbar:
http://msdn.microsoft.com/en-us/subscriptions/downloads/default.aspx?pv=18:370

Die entsprechende Trial Versionen können sofort herunter geladen werden:
http://www.microsoft.com/visualstudio/en-us/download

Auch eine Express Version von VC-2010 ist bereits verfügbar:
http://www.microsoft.com/express/Downloads/

Laut Microsoft sollen Übersetzungen in andere Sprachen noch bis Ende diesen Monates auch zur Verfügung stehen.

Der Visual Studio 2010 Release Candidate ist erschienen

Jetzt geht es in die Schlussphase ❗

Der Release Candidate für VisualStudio 2010 ist nun draußen. MSDN Abonnenten können ihn jetzt schon herunterladen. In den nächsten Tagen wird dann auch ein freier Download zur Verfügung stehen.
http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx

Wie auch schon die Beta 2 gibt es für diesen RC eine Go Live Lizenz, mit der man direkt produktiv entwickeln darf.

Das endgültige Erscheinungsdatum bleibt weiterhin der 12. April 2010

PS: Das jetzt der RC erschienen ist, heißt auch, dass nur noch wirklich extrem gravierende Bugs entfernt werden. Mit dem meisten was wir im RC sehen werden wir wohl auch im fertigen Produkt leben müssen. Ich bin gespannt welche Fehler aus der Beta 2 überlebt haben 😉
Dennoch testen und Fehler melden: https://connect.microsoft.com/VisualStudio?wa=wsignin1.0

VS-Tipps & Tricks: Springe zur nächsten Klammer funktioniert auch für #if, #elif, #else und #endif

Wer sich schon durch die Windows Header gekämpft hat um herauszufinden warum welche Definition einer Struktur oder Funktion in irgend einer Windows Version so oder gar nicht vorhanden ist, der weiß auch wie einem #if, #elif, #else und #endif das Leben schwer machen können, was die Orientierung betrifft.

Netterweise hilft einem eine Funktion, die man nur von Blöcken und verschachtelten Funktionen her kennt Strg+´ (Edit.GotoBrace). Wichtig! Man darf nicht auf der Variable oder Bedingung stehen, sondern muss auf dem Schlüsselwort stehen.

Wenn man auf einer Präprozessor Direktive kann man mit den Tasten die einem zur passenden Klammer bringt zur nachfolgenden Direktive. Und mit dem Festhalten der Umschalttaste kann man den entsprechenden Block auch markieren.

AfxMessageBox versus CWnd::MessageBox

Jeder MFC Entwickler kennt AfxMessageBox. In der Klasse CWnd finden wir auch die Memberfunktion CWnd::MessageBox.
Mancher Entwickler wird sich nun fragen: Wann nehme ich denn nun was?

Kurze Antwort: Meide CWnd::MessageBox und nutze immer AfxMessageBox

Lange Antwort:
CWnd::MessageBox ist einfach nur ein direkter Wrapper für Windows API Funktion MessageBox.
Der Grund warum man AfxMessageBox verwenden sollte liegt darin was AfxMessageBox einfach noch mehr leistet:

  1. AfxMessageBox benutzt die virtuelle Funktion CWinApp::DoMessageBox. Damit kann man zentral eine andere Behandlung für Fehlermeldungen einbauen.
  2. AfxMessageBox sorgt dafür, dass OLE Controls benachrichtigt werden, dass Ihre nicht modalen Dialoge nun deaktiviert werden müssen. Es wäre ja ziemlich heftig, wenn man solche Dialoge trotz aktiver MessageBox noch benutzen könnte. (siehe CWinApp::DoEnableModeless und Implementierung von CWnd::GetSafeOwner)
  3. CWnd::MessageBox benutzt das aktuelle Fensterhandle aus dem es aufgerufen wird als Parent-Handle für die API Funktion MessageBox. Die wenigsten Entwickler kennen, lesen oder beachten den netten Zusatz in der MessageBox Doku:
    If you create a message box while a dialog box is present, use the handle of the dialog box as the hWnd parameter. The hWnd parameter should not identify a child window, such as a control in a dialog box.
    Es ist also gerade zulässig CWnd::MessageBox aufzurufen, denn oft genug haben wir es mit Child-Windows zu tun.
    Netterweise beachtet AfxMessageBox genau das. Es ermittelt das aktuelle aktive Top-Level Fenster und setzt es intern für den Aufruf von MessageBox.
    Das wird auch ganz besonders wichtig, wenn man evtl. mehrere UI Threads hat. AfxMessageBox verwendet automatisch den richtigen. CWnd::MessageBox verwendet den aktuellen Thread aber evtl. als Fenster das Fenster-Handle aus einem anderen Threads.
  4. CWnd:MessageBox hat keine Implementierung für die F1-Taste und die Hilfeimplementierung der MFC.
  5. Ich muss mich nicht um den Titel der MessageBox kümmern, denn AfxMessageBox benutzt den hinterlegten Applikationsnamen (CWinApp::m_pszAppName) der in der MFC hinterlegt und definiert wurde.
  6. Netterweise setzt AfxMessageBox passende Icons wenn nur die Reaktionsform definiert wird, also kein Icon. (MB_OK und MB_OKCANCEL benutzt MB_ICONEXCLAMATION, MB_YESNO und MB_YESNOCANCEL benutzt MB_ICONQUESTION).

HTH

Visual Studio 2010 News

Erstmal die wichtigsten News vorab:

  • Die Beta 2 ist ab heute den 19.10.2009 auf MSDN verfügbar.
  • Für alle die, die kein MSDN haben wird es die Beta 2 vorraussichtlich ab Donnerstag den 22.10.2009 frei für alle verfügbar geben.
  • Das Erscheinungsdatum des Visual Studio 2010 wird voraussichtlich der 22. 03.2010 sein ❗

Die Zusammenstellung der Visual Studio Produkte wird sich komplett ändern. Insbesondere was den Team Foundation Server (TFS) und das Team System selbst bettrifft. Es wird nur noch drei Produkte geben (Professional, Premium, Ultimate) und nicht wie bisher 7 (Standard, Professional, Team System Developer, Test, Database, Architecture  und  Team-Suite) ❗
Das bisherige System mit den unterschiedlichen Rollen in Verbindung mit dem TFS kam nicht an und war unverständlich. Die drei neuen Versionen schließen immer die Leistung aller vorhergehenden Pakete ein. Im Detail sieht das bei den neuen Visual Studio Paketen in etwas so aus:

  • Professional: Alles was man bisher eben auch von der Professional Version kennt plus einige Extras, wie Multi-Monitor Support, Managed Extensibility etc.
  • Premium: Alles was Professional hat, inkl. das was wir bisher so in der Team System Developer, Database und der Tester Version kannte.
  • Ultimate: Alles was Professional und Premium umfasst plus die Team System Architecture Funktionen. Kommt also in etwa auf das hinaus was bisher die Team Suite war.

Auffällig! Es ist keine Visual Studio Standard Version geplant. Visual Studio Standard stirbt.
Aber auch hier soll was preiswertes kommen, so dass die Professional Version erschwinglich wird. So jedenfalls meine Hintergrundinfos.

Aber das aller wichtigste ❗ ❗ ❗

  • Alle Visual Studio 2010 Versionen schließen den TFS und eine CAL mit ein ❗
    (Diese Info ist unter Vorbehalt!)
  • Der TFS bekommt eine neue Installationsform mit dem Namen Basic.

Soweit ich das verstanden habe ist das ein vollständiger TFS, wie wir ihn heute kennen aber ohne Sharepoint Overhead. Das bedeutet einfache Installation in 15 Minuten. Und das läuft auch auf einem DC oder SBS, für alle die, die sich keinen zweiten Server hinstellen wollen. Natürlich eignet sich die Basic Installation auch als Installation für den Einplatz (d.h. auch für jeden XP, Vista und Windows 7 Rechner).
Die TFS Basic Installation bietet alles und viel viel viel viel mehr,  als das was wir bisher mit VSS und Visual Studio erledigt haben.

Microsoft will also ganz klar den TFS pushen und auf jeden Entwickler dazu bringen den TFS zu nuzen. Das heißt natürlich in zweiter Linie eine klare Absage für Visual Source Safe (VSS). Man kann sicherlich den VSS auch weiterhin in 2010 nutzen, wie man das in Visual Studio 2005+2008 her kennt. Aber ich kann nur jedem raten sich schnellstmöglich mit dem TFS anzufreunden.
Der VSS Mainstream Support läuft noch bis 11.04.2011!

Anmerkung zum Schluß:
Die Beta2 schließt bereits eine Go-Live Lizenz mit ein, eigent sich also direkt auch für das produktive Entwickeln.

Nachtrag: Alle Infos zur Lizensierung und Bündelung der Pakete bitte ich noch mit etwas Vorbehalt zubehandeln. Die Informationen wie ich sie hier wiedergebe basieren auf einem Webcast vom letzten Freitag und geben wieder wie was ich verstanden habe.

VS-Tipps & Tricks: Format Specifier in den Debugger Fenstern

Beim Debuggen Variablen im Watch-Window oder im Quick-View anzeigen zu lassen ist gängige Praxis und jeder etwas fortgeschrittene Entwickler wird diese Funktionen des Visual-Studios nutzen.

Üblicherweise wählt der Debugger eine Darstellungsform, die für die Variable geeignet ist. Besonders für STL Datentypen hat sich hier einiges getan seit VC-2005.

Dennoch kann man dem Debugger für manche Datentypen noch einen Format Specifier mitgeben, der einem die Arbeit beim Debuggen extrem erleichert.
Format Specifier erlauben es eine Variable entsprechend Ihrer Verwendung zu interpretieren. Typisch hier wäre eine Windows Nachricht. Als Integer sagt einem 0x0129 nicht viel, aber WM_NCCREATE einiges. Wenn man hinter die Variable nMsg im Watch-Fenster einfach aus nMsg,wm erweitert erhält man sofort die Nachricht als symbolischen Wert angezeigt.

Ich will hier nicht alle aber wenigstens ein paar sehr nützliche und weniger bekannte Format Specifier aufzählen:

! – Raw format
hr – HRESULT in Klartext
su -Unicode
s8 – UTF8
wm – Windowsnachricht
wc – Fensterstil
<n> – Anzahl der Arrayelemente

Am schönsten sieht man die Wirkung an dem folgenden Code und den nachfolgenden Bildern der Watch-Windows:

int g_ai[] =
{
  4711,
  815,
  1234
};

int _tmain(int argc, _TCHAR* argv[])
{
  std::list lst;
  lst.push_back(1);
  lst.push_back(2);
  DWORD dwHResult = 2147943623;
  void *szUnicode = L"Unicode ÄÖÜäöü";
  char *szUTF8Code = "Umlaute AE=\xc3\x84 OE=\xc3\x96 UE=\xc3\x9c.";
  UINT winmsg = 125;
  DWORD winstyle = 0xA6730000;
  int *pi = g_ai;

  DebugBreak();
  return 0;
}

Hier das Ganze die Daten im Watchwindow ohne Formatspecifier:

Watch1

Hier das Ganze mit:

Watch2

Weitere Links dazu:
http://msdn.microsoft.com/en-us/library/75w45ekt.aspx
http://blogs.msdn.com/vcblog/archive/2006/08/04/689026.aspx

CMapStringTo… HashKey Implementierung in VC-2003/5/8 ist auch fragwürdig

 Hash-Algorithmen haben es mir irgendwie angetan. 1984 hatte ich das erste mal mit einem miesen Hashverfahren zu tun, das einfach versagte wenn es nur um Ziffern ging. Das ganze betraf das Betriebssystem OASIS (später TheOS) und dessen Index Dateiorganisation. Ich entwickelte hierfür einen Patch in Assembler, der damals exakt in den x-Bytes der Kernels in Z80 Assembler passen musste.
Das Problem bei Strings die nur aus Ziffern bestehen ist das die Veränderung, die immer nur die unteren 4 Bits betrifft und die höheren 4 Bits immer konstant sind mit 3 belegt sind.

Als ich gelesen habe,  dass in VS-2010 die CMap Implementierung nun auch für Strings den selben Algorithmus aus der STL erhalten, habe ich mir auch den mal genauer angesehen. (siehe Beitrag Die MFC erhält mit VC-2010 jetzt eine neue HashKey Implementierung)
Der sieht so aus:

inline UINT CMapStringToString::HashKey(LPCTSTR key) const
{
  UINT nHash = 0;
  if (key == NULL)
  {
    AfxThrowInvalidArgException();
  }
 
  while (*key)
    nHash = (nHash<<5) + nHash + *key++;
  return nHash;
}

Und auch in diesem Fall muss ich sagen, dass der Algorithmus nur scheinbar intelligent ist. Wenn man sich aber die Abstände die hier erzeugt werden etwas genauer anschaut kommt man schnell auf eine Wertekombination, in der der Algorithmus versagt.
Wie sehr er versagt zeigt das folgende Beispiel, in dem ich einfach einen String verwende der aus 5 Ziffern besteht und immer den Abstand 11 verwendet.

CMapStringToPtr myMap;
for (int i=0; i<1000; i+=11)
{
  CString strKey;
  strKey.Format(_T("%05d"),i);
  myMap[strKey] = NULL;
}

Das erschreckende Ergebnis der Verteilung ist bei einem Unicode wie auch MBCS Projekt:

TMyMap<class CMapStringToPtr>::DumpMap
Bucket  0 =  0
Bucket  1 =  0
Bucket  2 =  0
Bucket  3 =  0
Bucket  4 =  0
Bucket  5 =  0
Bucket  6 =  0
Bucket  7 =  0
Bucket  8 = 36
Bucket  9 =  0
Bucket 10 =  0
Bucket 11 =  0
Bucket 12 =  0
Bucket 13 =  0
Bucket 14 = 55
Bucket 15 =  0
Bucket 16 =  0

Wie gut, dass auch die String Variante von HashKey überarbeitet wird.

BTW: Da die internen Strukturen protected sind muss man zu einem kleinen Trick greifen um die Verteilung ausgeben zu können. Ich habe dazu ein template verwendet, dass für alle MFC Maps funktioniert.

template<class TBase> class TMyMap : public TBase
{
public:
  void DumpMap()
  {
    TRACE(__FUNCTION__ "\n");
    if (m_pHashTable)
    {
      for (size_t i=0; i<m_nHashTableSize; ++i)
      {
        int iCount = 0;
        for (CAssoc *p = m_pHashTable[i]; p; p=p->pNext)
          ++iCount;
        TRACE("Bucket %2d = %4d\n", i, iCount);
      }
    }
  }
};

Merke: Wer Hashes verwendet sollte sich über sein Hashverfahren wirklich gedanken machen.

BTW: Sollte es den Leser meines Blogs langsam langweilen weil ich mich permanent mit Hash-Algorithmen aufhalte, der sei getröstet: Dies war vorläufig mein letzter Beitrag zu CMap… :mrgreen:

Die MFC erhält mit VC-2010 jetzt eine neue HashKey Implementierung

Ich hatte die schlechte Hashkey Implementierung ja bereits in VC-2005 als Bug gemeldet (siehe Die HashKey Implementierung in der MFC in VC-2005 und VC-2008). In VC-2008 geschah dies bzgl. wieder nichts. Aber was lange währt wird manchmal gut 😉

Die neue Implementierung wird aus der aktuellen STL übernommen. Diese Implementierung sorgt für Integer und Pointer für eine sehr gute zufällige Verteilung. Und weitere gute Nachricht dazu, auch die Implementierung für Strings wird aus der STL übernommen.

Zitat:

Hello Martin,

Thanks for the report. This issue has been fixed in MFC for Visual Studio 2010. MFC now uses the STL hash functions directly when possible, or uses a new algorithm copied from STL (in the case of strings).

Pat Brenner
Visual C++ Libraries Development
Von Microsoft am 20.07.2009 um 12:15 bereitgestellt

Siehe https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=468860

Die HashKey Implementierung in der MFC in VC-2005 und VC-2008

Die Maps in der MFC werden ja auch zum Teil gerne verwendet. Auch wenn viele Programmierer eher auf die std::map bzw. std::hash_map verwenden.

Zwei interne Dinge sind jedoch vielen Entwicklern nicht klar.

  1. Die Standard-Maps der MFC werden mit 17 Hash-Buckets erzeugt. Man sollte sich also über die Anzahl der Elemente klar werden, die gespeichert werden sollen.
    Bei großen Datenmengen sollte man evtl. darüber nachdenken, die Anzahl der Buckets zu erhöhen.
  2. Ist die Hash Funktion zu beachten, die hier verwendet wird. Denn deren Effektivität entscheidet ja, wie die Einträge auf die Buckets verteilt werden.

Zu diesem zweiten Punkt macht man eine erstaunliche Entdeckung, wenn man sich ansieht, was Microsoft für eine Funktion vorgesehen hat um den Hask-Key zu erzeugen. Diese Funktion ist in der MFC für primitive Werte vordefiniert, als primitive Werte sehe ich alle numerischen Werte, Zeiger und Handle an.
Man findet eine Implementierung als Template-Funktion in afxtempl.h:

template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
 // default identity hash - works for most primitive values
 return (DWORD)(((DWORD_PTR)key)>>4);
}

Das erstaunliche ist für mich, dass hier die untersten 4 Bits einfach abgeschnitten werden. Für mich hätte für Handles, Zeiger und Integer Werte einfach ein cast gelangt.

Nehmen wir jetzt mal an, wir haben eine einfache Datenmenge, die die Integer 1-100 auf eine Struktur abbilden. Man wird die erstaunliche Entdeckung machen, dass alle Werte nur in den Buckets 0-6 abgespeichert werden. Die Buckets 7 bis 16 werden nicht verwendet.

Der Nachteil ist offensichtlich. Man nutzt das Datenrauschen auf den untersten 4 Bits nicht.
Das macht sich sogar bei Fensterhandles bemerkbar. Bekanntlich sind das immer gerade Werte, aber auch auf den Bits 1-3 finden wir hier Informationen. Auch hier werden nützliche „zufällige“ Informationen nicht genutzt. Dadurch werden mehr Kollisionen in Kauf genommen als notwendig wären.

Ich möchte nicht unerwähnt lassen, dass die MFC Maps wirklich eine Berechtigung haben, weil sie grundsätzlich einen Pool-Allocator verwenden. Häufige Allokationen und Löschungen werden weitaus schneller behandelt, als durch die std::map, oder std::hash_map mit normalen Allocator.

Ich habe diesen Bug (oder miese Verhalten) bereits in der Beta für VC-2008 gemeldet. Es wurde aber nicht mehr geändert. Nun habe ich es an die Produktgruppe erneut  für VC-10 eingereicht.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100772
Nachtrag 22.06.2009: Da der Bug von Microsoft nicht neu geöffnet wird habe ich einen neuen für VS-2010 Beta 1 angelegt.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=468860
Wer Lust hat, der kann ja abstimmen.

BTW: Die HaskKey Funktion in afxtempl.h ist für andere Maps (z.B. CMapPtrToPtr) direkt in der Klasse definiert. Dieses Template wird nur vom CMap-Template verwendet.