Visual Studio 2010 komplett entfernen bzw. die Unmöglichkeit es richtig zu tun

Immer wieder mal lese ich von Problemen bei der Installation oder mit Installationen von VS-2010. Ich hatte den Fall noch nie, aber es gibt scheinbar immer wieder Installationen in denen der Wurm drin ist.

VS-2010 installiert eine Unmenge an Komponenten und Programmteilen. Die meisten können einfach deinstalliert/gelöscht werden. Aber es bleiben immer noch ein Haufen DLLs/ActiveX Controls und Registry Einträge und Verweise auf Verzeichnisse. Und leider gibt es für die Visual Studio 2010 keinen richtigen Uninstaller, der auch alle Artefakte löscht und deshalb kann ich gleich zu Anfang sagen, dass man außer der Deinstallation wirklich wenig tun kann.
Eine Reparaturinstallation sollte man aber bei einer bestehenden Installation in jedem Fall einmal, bevor man zu härteren Maßnahmen greift. Die wirkt oft schon Wunder.

Im Netz gibt es das folgende Utility: Visual Studio 2010 Uninstall Utility:
http://archive.msdn.microsoft.com/vs2010uninstall
Das Tool hat drei Operationsweisen die man in dem obigen Link erklärt findet.
Das Tool funktioniert eigentlich ohne Probleme aber benutzt auch nur auf dem MSI Uninstall Prozess auf, und dabei berücksichtigt es nicht einmal Servicepacks. Sollte man also das SP1 von Visual Studio 2010 installiert haben, dann muss man dieses vorher selber entfernen.

Das dieses Tool macht aber auch nur die Arbeit halb. Das erkennt man mit einem schnellen Blick in Registry. Der Ast HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0 wird durch die Deinstallation nicht entfernt und man muß in diesem Fall manuell Hand anlegen.

Wenn man also persistente Probleme mit der VS-2010 Installation hat, die man nicht über die Setup-Logs oder mit Tipps aus den Foren lösen kann, dann bleibt nach meiner Meinung nur der harte Weg den Rechner neu aufzusetzen. Bisher bin ich davon verschont geblieben und meine Installation haben immer von Rechnerwechsel zu Rechnerwechsel gehalten.

VS-Tipps & Tricks: Debugger Pseudo Variablen

Die folgenden Variablen helfen mir immer wieder beim Debuggen und zeigen einem während des Debuggens in Watch-Window manch nützliche Information:

  • $TID
    Die Thread ID des aktuellen Threads. Nützlich wenn man mehrere Threads debuggt und bestimmte Threads bei einem Breakpoint identifizieren muss.
  • $HANDLES
    Die Anzahl der aktuell benutzen System-Handles des Prozesses. Handle Leaks lassen sich damit im Debugger leicht überwachen.
  • $ERR
    GetLastError
    leicht gemacht. Schlägt ein WinApi Befehl fehl, dann ist es schön das man sofort beim Debuggen im Watch-Window sehen kann was die Ursache war. Oft genug ist ja im Code selbst kein Aufruf von GetLastError vorhanden oder nötig.

Siehe auch MSDN:
http://msdn.microsoft.com/en-us/library/ms164891.aspx

BTW: WinDbg hat noch einige mehr nette Pseudovariablen:
http://blogs.msdn.com/b/debuggingtoolbox/archive/2008/06/16/special-command-using-variables-and-retrieving-information-through-pseudo-registers.aspx
Schmerzhaft vermisse ich immer wieder $PEB, $TEB, $TPID, $RA im Visual Studio, komisch, dass es die nur im WinDbg gibt.

VS-Tipps & Tricks: Wie man gezielt einen Breakpoint für einen Thread setzen kann

Wenn man eine Anwendung oder einen Dienst hat, der mit vielen Threads arbeitet, dann kann das Debuggen abenteuerlich werden. Besonders wenn viele Threads ein und die selbe Threadfunktion verwenden.
Was macht man nun wenn man einen Thread isoliert hat und dessen Verhalten weiter prüfen möchte? Single-Stepping ist nicht drin, denn der Breakpoint würde auch jeden anderen Thread anhalten, der diese Code-Position erreicht.

Die nachfolgende Methode ist relativ einfach um gezielt einen Breakpoint für einen Thread zu setzen.
Gehen wir mal davon aus, dass wir im Debugger einen Breakpoint haben und uns im Kontext des Threads befinden, den wir nun weiter verfolgen wollen.

  1. Zuallererst ermitteln wir die Thread-Id.
    Das geht elementar einfach über die Pseudo-Debugger-Variable $TID, die wir uns im Watch-Fenster, oder im Quick-View anzeigen lassen:
  2. Als nächstes modifizieren wir den Breakpoint so, dass er nur noch dann stoppt, wenn auch unser Thread diesen Breakpoint erreicht.
    Das erreichen wir über die Breakpoint-Eigenschaft Condition (rechter Mausklick, über das Kontextmenü):

    Hier geben wir einfach als Bedingung an, das $TID (also die Thread-ID) identisch sein muss, zu der ID des Threads, den wir beobachten wollen.
  3. Den Rest macht der Debugger für uns, wenn wir wieder den Go-Befehl (F5) geben:

Auf diese Weise kann man auch mehrere Threads einfach beobachten.

Hinweis:
Dieses Verfahren ändert das Laufzeitverhalten des Programmes, denn der Breakpoint wird immer intern ausgeführt, egal welcher Thread diese Codestelle passiert. Nur ermittelt der Debugger dann die Bedingung returniert und lässt das Programm, dann weiterlaufen, wenn die Id nicht passt. Wird diese Codestelle sehr oft passiert, dann kann ist der Einfluss eines solchen Breakpoints nicht  unerheblich.

Alternativ, kann man in solch einem Fall auch ein Stück Code einsetzen, der die aktuelle Thread-ID gegen eine statische Variable testet und einen DebugBreak ausführt. Die statische Variable setzt man dann während der Debugsession auf die gwünschte Thread-ID über das Watch-Window oder den Quick-View

Weiterführende Infos zu Debugger-Pseudo-Variablen von Visual-Studio findet man hier:
http://msdn.microsoft.com/en-us/library/ms164891.aspx

VS-Tipps & Tricks: MFC/ATL Tracing selektiv ein und ausschalten

In ATL und MFC steckt ein ziemlich ausgeklügelter Trace-Mechanismus. Wenn man sich das MFC – ATL Trace Tool ansieht kann man zu allen möglichen Kategorien Informationen in Debug Fenster ausgeben lassen.
Alleine die MFC hat 14 verschiedene Trace Kategorien. Darunter besonders interessante wie CommandRouting, AppMsg und WinMsg. Die ATL hat weitere 27 Kategorien.
Es lohnt sich mal einen Blick in dieses Tool und die entsprechenden Ausgaben zu machen. Es gehört zu den oft unbekannten netten Helferlein, die leider mangels Bekanntheit selten benutzt werden.

Um Fehler zu finden und einzugrenzen, sind mir jedoch oft eher zu viele Ausgaben vorhanden, als zu wenige. Zudem finde ich es manchmal unhandlich mit dem Trace-Tool die Nachrichten ab einem bestimmten Moment einzuschalten und wieder auszuschalten.
Ich habe eine kleine Hilfsklasse gebaut,mit der man in jedem Szenario, jederzeit zu einem bestimmten Moment das Tracing im Code ein- und automatisch wieder ausschalten kann.

class CDebugEnableTraceForCategory
{
public:
  CDebugEnableTraceForCategory(ATL::CTraceCategory &category,
           PCSTR pszPrompt=NULL,
           UINT uiLevel=4,
           ATL::ATLTRACESTATUS eStatus=ATL::ATLTRACESTATUS_ENABLED)
    : m_category(category)
    , m_uiSaveLevel(category.GetLevel())
    , m_eSaveStatus(category.GetStatus())
    , m_strPrompt(pszPrompt)
  {
    if (!m_strPrompt.IsEmpty())
      TRACE("%s - Tracelevel %d\n", m_strPrompt.GetString(),uiLevel);
    m_category.SetLevel(uiLevel);
    m_category.SetStatus(eStatus);
  }
  ~CDebugEnableTraceForCategory()
  {
    m_category.SetLevel(m_uiSaveLevel);
    m_category.SetStatus(m_eSaveStatus);
    if (!m_strPrompt.IsEmpty())
      TRACE("%s - Tracelevel %d\n", m_strPrompt.GetString(), m_uiSaveLevel);
  }
private:
  // Data fields
  ATL::CTraceCategory &m_category;
  ATL::ATLTRACESTATUS m_eSaveStatus;
  UINT m_uiSaveLevel;
  CStringA m_strPrompt;
  // no copy operator
  CDebugEnableTraceForCategory(const CDebugEnableTraceForCategory &);
  CDebugEnableTraceForCategory& operator=(const CDebugEnableTraceForCategory &);
};

Mit dieser Klasse kann ich zum Beispiel alle Windows-Nachrichten an MFC Fenster bei einer bestimmen Aktion ausgeben lassen. Und wenn die Aktion fertig ist stopp auch das Tracing wieder. 

Hier als Beispiel um alle Fensternachrichten in der Aktion LoadFrame zu Tracen: 

void CMyApp::InitInstance()
{
...
    CDebugEnableTraceForCategory trace(traceWinMsg,"messages in LoadFrame");
    pMainFrame->LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW);
...
}

Weitere Infos in der MSDN findet man unter ATL::CTraceCategory und ATLTRACE2 http://msdn.microsoft.com/en-us/library/dhxsse89(VS.100).aspx

VS-Tipps & Tricks: Kommentare intelligent und einfach umbrechen

 Wer programmiert, der dokumentiert auch. Denke ich zumindest 😀

Ich zumindest habe teilweise Kommentare, die sich über 10 bis zu 100 Zeilen erstrecken. Die sind nah am Code und erklären, oft was die Hintergründe für das gewählte Design und Vorgehen sind.

Leider ist aber der Editor vom Visual Studio kein Word. D.h. absatzweisen Umbruch kennt das Ding nicht und manuell solche Texte inkl. Einrückungen und Listen mit Bindestrichen oder 1., 2., 3. zu formatieren ist etwas was gar keinen Spaß macht. Zudem sind die Kommentar Zeichen // oder * eher lästig als hilfreich beim schreiben.
Und auch VAX muss hier mal passen. Aber! Netterweise gibt e auch andere Addins.

Ich habe vor langer Zeit schon den Comment Reflower  entdeckt. Mit dem ist das Ganze ein Klacks.
Aus dem nachfolgenden Text:

// Dies ist ein Kommentar, den man nicht wirklich hier schreiben
// müsste und der
// eigentlich nichts bedeutet außer
// die Funktionen von einem netten Addin zu zeigen.
// Das
//  1. wirklich Arbeit erspart
//  2. total simpel zu bedienen ist
//  3. für alle VS-Versionen von 2005 über 2008 bis 2010 verfügbar ist.
// Was bei der Formatierung heraus kommt lässt sich sehen.

Wird in Null-Komma-Nichts der folgende Text:

// Dies ist ein Kommentar, den man nicht wirklich hier
// schreiben müsste und der eigentlich nichts bedeutet
// außer die Funktionen von einem netten Addin zu
// zeigen. Das
//  1. wirklich Arbeit erspart
//  2. total simpel zu bedienen ist
//  3. für alle VS-Versionen von 2005 über 2008 bis
//     2010 verfügbar ist.
// Was bei der Formatierung heraus kommt lässt sich
// sehen.

Wer noch mehr Beispiele sehen will, was das Tool leistet findet hier auf der Sourceforge Seite ein Vorher Nacher Pärchen.

Das Addin existiert für alles Visual Studio Versionen ab 2005.
Es kann hier heruntergeladen werden:

PS: Es empfiehlt sich ein Blick auf die Blockdefnition in den Einstellungen. Dort ist oft ein Leerzeichen hinter dem * bzw. // eingetragen. Leider lässt sich in meiner Version hier RegEx nicht einschalten. Wer also ein <tab>-Zeichen hinter dem * oder // hat wird sich wundern wenn das Addin keinen Kommentar findet. Ich habe das Leerzeichen einfach entfernt…

PPS: Für alle nicht C++ Entwickler. Das Tool funktioniert auch für VB und C# ❗

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.

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

VS-Tipps & Tricks: Direkter Break in den Debugger bei einem ASSERT

ASSERTs in der MFC und in der CRT sind tolle Hilfsmittel, aber nicht selten verfälschen sie auch das Problem alleine dadurch, dass ein Fenster aufpoppt, wenn der ASSERT zuschlägt. Hat man nun einen Code, der in einem Tooltipp etwas Böses macht, dann wird der Tooltipp selbst aber schon wieder durch das erscheinen der ASSERT Meldung zerstört. Oder es wird ein neuer ASSERT ausgelöst. Der Callstack wird dadurch oft schwer zu lesen.
Besonders heikel kann dies auch noch werden wenn man mehrere Threads hat. Gleichfalls problematisch ist, dass in dem Moment in dem die ASSERT Box auftaucht nun auch wieder alle Timer weiterlaufen und sehr eigentümliche Seiteneffekte weiter auslösen können, dito. Probleme in WM_PAINT Handlern, denn auch die lösen evtl. schon wieder Aktionen aus, die Variablen verändern.

Nett ist am ASSERT-Dialog natürlich die Möglichkeit Ignorieren zu sagen und das Programm weiter laufen zu lassen. Ganz besonders wenn man Debug Versionen im Testfeld mit Anwendern testet.

Dennoch bin ich bei Debug-Versionen dazu übergegangen ASSERTs direkt  crashen zu lassen, bzw. direkt einen Debug-Break auszulösen. Das erleichtert das Lesen des Crashdumps bzw. hilft auch beim Debuggen, weil man direkt an der Stelle steht wo es hakt und alle Fenster und Variableninhalte exakt noch so sind, wie Sie es beim Auftreten des Problems waren (Tooltips, Popups, Menüs etc.).

Der Code um das zu erreichen ist relativ simpel. Man verwendet dazu _CrtSetReportHook2. In dem Hook sagt man einfach was man gerne hätte. Nämlich bei einem ASSERT oder ERROR keinen Dialog sondern einen Break (INT3).

#ifdef _DEBUG
int __cdecl DebugReportHook(int nReportType, char* , int* pnRet)
{
  // Stop if no debugger is loaded and do not assert, cause a crash
  // - returning TRUE indicates that we handled the problem, so no other hook
  //   needs to perform any action
  // - setting the target of *pnRet to TRUE indicates that the CRT should
  //   execute an INT3 and should crash or break into the debugger.
  return *pnRet = nReportType==_CRT_ASSERT ||
                  nReportType==_CRT_ERROR ?
                            TRUE : FALSE;
}
#endif

void SetBreakOnAssert(BOOL bBreakOnAssert/* =FALSE */)
{  
// Need to disable the ASSERT handler?
#ifdef _DEBUG  
  if (bBreakOnAssert)   
    _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, DebugReportHook); 
  else   
    _CrtSetReportHook2(_CRT_RPTHOOK_REMOVE, DebugReportHook);
#else
  UNUSED_ALWAYS(bBreakOnAssert);
#endif
}

Durch diese kleine Funktion SetBreakOnAssert kann man dieses Verhalten nun einfach ein- und ausschalten. Nähere Details stehen im Kommentar der Hook-Funktion.

VS-Tipps&Tricks: Einfache Debug-Ausgabe mit TRACE auch in der Release Version

Wer wollte nicht schon immer mal gerne TRACE (Debug)-Ausgaben in seinem Release Programm haben ohne dafür überall OutputDebugString reinschreiben zu müssen.

Die nachfolgene kleine Klasse macht es möglich, den gewohnten Syntax des MFC TRACE Makros zu verwenden und direkt auf die Debugausgabe umzuleiten:

//    CTraceToOutputDebugString
//        Is a nice replacment class for TRACE
//        Easy to use with:
//            #undef TRACE
//            #define TRACE    CTraceToOutputDebugString()

class CTraceToOutputDebugString
{
public:
    // Non Unicode output helper
    void operator()(PCSTR pszFormat, ...)
    {
        va_list ptr;
        va_start(ptr, pszFormat);
        TraceV(pszFormat,ptr);
        va_end(ptr);
    }

    // Unicode output helper
    void operator()(PCWSTR pszFormat, ...)
    {
        va_list ptr;
        va_start(ptr, pszFormat);
        TraceV(pszFormat,ptr);
        va_end(ptr);
    }

private:
    // Non Unicode output helper
    void TraceV(PCSTR pszFormat, va_list args)
    {
        // Format the output buffer
        char szBuffer[1024];
        _vsnprintf(szBuffer, _countof(szBuffer), pszFormat, args);
        OutputDebugStringA(szBuffer);
    }

    // Unicode output helper
    void TraceV(PCWSTR pszFormat, va_list args)
    {
        wchar_t szBuffer[1024];
        _vsnwprintf(szBuffer, _countof(szBuffer), pszFormat, args);
        OutputDebugStringW(szBuffer);
    }
};

Durch den obenstehenden Code kann man auch in einer Release Version Trace Ausgaben erzeugen und z.B. mit DebugView.exe (Sysinternals) sichtbar machen, ohne evtl. weitere Anpassungen vornehmen zu müssen:

// Activate my special tracer
#undef TRACE
#define TRACE    CTraceToOutputDebugString()

void Foo()
{
     // Sometime usefull to see the output in a release version too
     TRACE(__FUNCTION__ " called at %d\n", GetTickCount());
}

Tipps & Tricks: Warum nicht mal ein anderer Font, wie z.B. Consolas

Eigentlich bin ich sehr konservativ was meine Visual-Studio Einstellungen betrifft. Aber irgendwie hat mich heute mal die Experimentierlaune überkommen, weil ich durch Zufall über einige Color-Schemes gestolpert bin und im C++ Forum eine Diskussion lief ob „hell auf dunkel“ oder „dunkel auf hell“ besser ist.

Am Ende des Experimentierens, habe ich das Farbschema gelassen wie es ist. Ich habe ja auch VA-X, den untentbehrlichen Helfer des Programmieres,  und auch da ist bis auf das Highlighting alles Standard. Aber bei der Schriftart habe ich – für mich gefühlt – was besseres gefunden: „Consolas“.
Eindeutig für mich das schönere Schriftbild, klarer und etwas kompakter und kleiner als „Courier New“.

Beispiel „Courier New“
CourierNew

Beispiel „Consolas“
Consolas
Wer mag, der kann es gleich probieren. Auf meinen Vista Rechnern war diese Schriftart sofort vorhanden. Wer das Font-Paket nicht hat, der kann es herunterladen bei Microsoft Consolas Font Pack for Microsoft Visual Studio 2005 or 2008