code it

Martins Tech Blog

MSBuild-Messages im Output-Window anzeigen lassen

Das Output-Window von Visual Studio kann mittels einer Option dazu gebracht werden, detaillierter anzuzeigen, was bei der Ausführung der internen aber auch von angepassten MSBuild-Skripten eigentlich gemacht wird. Die Einstellung dafür findet man unter Tools -> Options -> Projects and Solutions -> Build and Run.

Die "MSBuild project build output verbosity" bestimmt, wie geschwätzig sich MSBuild verhalten soll.

Kontextmenü von Smart Tags im Visual Studio anzeigen

Meiner Meinung nach sind die Smart Tags in Visual Studio ein sehr schönes Feature, die ich besonders häufig für das Umbenennen von Variablen oder für das Erzeugen von Methodenrümpfen beim Implementieren von Interfaces verwende.

In der täglichen Arbeit finde ich es allerdings etwas nervig, den doch etwas klein geratenen Smart Tag mit der Maus zu treffen.

Wie für so vieles gibt es auch hier eine Tastenkombination: Laut Tooltip kann das Smart Tag Menü mit Alt+Shift+F10 geöffnet werden. Was der Tooltip nicht sagt: Mit der viel einfacheren Tastenkombination Strg+. öffnet sich das Menü ebenfalls.

Gib Laut!

Besonders wenn man einen sehr zeitintensiven Build hat, bekommt man manchmal nicht mit, wenn das Build durchgelaufen ist. In diesen Fällen wäre es doch schön, wenn Visual Studio noch einen akustischen Hinweis liefern würde. 

Eine Einstellung in Options hab ich dafür nicht gefunden... aber es gibt ja noch Makros :)

Wenn man mag, legt man sich im Makro-Explorer(Alt+F8) ein neues Makro-Projekt an. Alternativ kann man die Einstellungen auch im MyMacros-Projekt hinzufügen.

Im Anschluss daran öffnet man die Macro-IDE(Alt+F11). Im eben erstellen Makro existiert bereits das Modul EnvironmentEvents. Falls nicht, kann man es sich aus dem Projekt Samples kopieren. Es sollte ungefähr so aussehen:

Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module EnvironmentEvents

#Region "Automatically generated code, do not modify"
    'Automatically generated code, do not modify
    'Event Sources Begin
    <System.ContextStaticAttribute()> 
    Public WithEvents DTEEvents As EnvDTE.DTEEvents
    <System.ContextStaticAttribute()> 
    Public WithEvents DocumentEvents As EnvDTE.DocumentEvents
    <System.ContextStaticAttribute()> 
    Public WithEvents WindowEvents As EnvDTE.WindowEvents
    <System.ContextStaticAttribute()> 
    Public WithEvents TaskListEvents As EnvDTE.TaskListEvents
    <System.ContextStaticAttribute()>
    Public WithEvents FindEvents As EnvDTE.FindEvents
    <System.ContextStaticAttribute()>
    Public WithEvents OutputWindowEvents As EnvDTE.OutputWindowEvents
    <System.ContextStaticAttribute()>
    Public WithEvents SelectionEvents As EnvDTE.SelectionEvents
    <System.ContextStaticAttribute()>
    Public WithEvents BuildEvents As EnvDTE.BuildEvents
    <System.ContextStaticAttribute()>
    Public WithEvents SolutionEvents As EnvDTE.SolutionEvents
    <System.ContextStaticAttribute()>
    Public WithEvents SolutionItemsEvents As EnvDTE.ProjectItemsEvents
    <System.ContextStaticAttribute()>
    Public WithEvents MiscFilesEvents As EnvDTE.ProjectItemsEvents
    <System.ContextStaticAttribute()>
    Public WithEvents DebuggerEvents As EnvDTE.DebuggerEvents
    <System.ContextStaticAttribute()>
    Public WithEvents ProjectsEvents As EnvDTE.ProjectsEvents
    <System.ContextStaticAttribute()>
    Public WithEvents TextDocumentKeyPressEvents As EnvDTE80.TextDocumentKeyPressEvents
    <System.ContextStaticAttribute()>
    Public WithEvents CodeModelEvents As EnvDTE80.CodeModelEvents
    <System.ContextStaticAttribute()>
    Public WithEvents DebuggerProcessEvents As EnvDTE80.DebuggerProcessEvents
    <System.ContextStaticAttribute()>
    Public WithEvents DebuggerExpressionEvaluationEvents As EnvDTE80.DebuggerExpressionEvaluationEvents
    'Event Sources End
    'End of automatically generated code
#End Region

End Module

Nun wählt man noch im Dropdown "Class name" den Eintrag "BuildEvents" und im Dropdown "Method name" den Entrag "OnBuildDone" und schon ist der Eventhandler für den Build-Done-Event vorhanden. In diesen können nun die gewünschten Aktionen programmiert werden - im Beispiel wird die Methode Beep aufgerufen:

Private Sub BuildEvents_OnBuildDone(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildDone
    Beep()
End Sub

Das war's auch schon! So lange das Makro geladen ist, wird sich Visual Studio nun am Ende jeden Builds akustisch melden.

Go Offline?

Eine sehr praktische Möglichkeit bei der Arbeit mit Visual Studio in Verbindung mit dem Team Foundation Server ist es, dass man auch Offline arbeiten kann und dann später im Online-Modus die Änderungen zusammengesucht werden und man einchecken kann.

Ist keine Verbindung zum TFS möglich, wenn ein entsprechendes Projekt geöffnet wird, geht Visual Studio automatisch in den Offline-Modus und man kann mittels des “Go Online”-Buttons in den Online-Modus wechseln.

Leider funktioniert der umgekehrte Weg nicht. Ist man Online und möchte in den Offline-Modus wechseln, sucht man den “Go Offline”-Button vergeblich.

Doch wo ein Wille ist, ist auch ein Weg – der Zauberbefehl lautet tfpt tweakui:

  • Visual Studio schließen
  • die aktuellsten Team Foundation Power Tools herunterladen und installieren
  • Visual Studio Command Prompt öffnen
  • tfpt tweakui eingeben
  • den Server markieren und auf Edit klicken
  • Server ist offline anhaken
  • Visual Studio neu öffnen

Visual Studio öffnet das Projekt nun im Offline-Modus.

Attach-to-Webserver-Makro für Visual Studio

In letzter Zeit mache ich wieder sehr viel Webentwicklung und –debugging. Dabei fand ich es etwas nervig für das Debugging immer die Menüstruktur mit den Punkten Debug -> Attach to Process zu bedienen und dann aus der Liste alle w3wp-Prozesse auszusuchen.

Glücklicherweise gibt es dafür ja die Makro-Funktion. also schnell ein Makro geschrieben:

Imports System
Imports EnvDTE80
Imports System.Windows.Forms

Public Module AttachToWebServer

    Public Sub AttachToWebServer()
        Dim W3WPProcName As String = "w3wp.exe"

        If Not AttachToProcess(W3WPProcName) Then
            MessageBox.Show(String.Format("Process {0} cannot be found", W3WPProcName), "Attach to webserver macro")
        End If

    End Sub

    Public Function AttachToProcess(ByVal ProcessName As String) As Boolean

        Dim Processes As EnvDTE.Processes = DTE.Debugger.LocalProcesses
        Dim Process As EnvDTE.Process
        Dim ProcessFound As Boolean = False

        For Each Process In Processes
            If (Process.Name.Substring(Process.Name.LastIndexOf("\") + 1) = ProcessName) Then
                Process.Attach()
                ProcessFound = True
            End If
        Next

        AttachToProcess = ProcessFound

    End Function
End Module

Damit nun das Makro nicht immer händisch über den Makro-Explorer aufgerufen werden muss, noch schnell ein ein Shortcut dafür vergeben und: Voilà!

Visual Studio Tipp: Shortcut für ein Makro vergeben

Makros erleichtern die Arbeit mit Visual Studio. Doch nicht immer möchte man über den Makro-Explorer erst sein Makro auswählen. Besonders bei häufig benutzten Makros ist es sinnvoll, einen Shortcut zu vergeben. Dazu geht man wie folgt vor:

  1. Unter dem Menüpunkt Tools den Eintrag Options auswählen.
  2. Unter Environment auf Keyboard klicken.
  3. Im Auswahlfeld Show commands containing gibt man nun “macros.” ein. Damit erscheinen hier alle Makros.
  4. Hier markiert man nun das gewünschte Makro.
  5. Im Feld Press shortcut key(s) drückt man nun einmal die Tastenkombination, mit der man das Makro künftig aufrufen möchte – z.B. Strg + Shift + Alt + A
  6. Nachdem man auf Assign und OK geklickt hat, ist der neue Shortcut aktiv.

Die detaillierte Beschreibung gibt es auch nochmal in der MSDN.

Visual Studio Tipp: Unterbrechen, wenn eine Exception auftritt

Im Standard hält Visual Studio im Debugging-Modus dann an, wenn eine Exception im Code nicht behandelt wurde. Das ist allerdings meist sehr weit von dem eigentlichen Punkt entfernt, an dem die Exception aufgetreten ist, da mehrere try…catch-Blöcke durchlaufen sein können, bevor die Exception unbehandelt ist.

Eine einfache Möglichkeit, das Verhalten zu ändern, findet sich im Visual Studio: Im Debug-Menü findet sich der Punkt “Exceptions” (Strg+Alt+E), der folgenden Dialog öffnet:

 

Setzt man hier den Haken unter “Thrown” für “Common Language Runtime Exceptions”, hält der Debugger an der Stelle an, an der der Fehler aufgetreten ist. Nachteil dieser Methode ist, dass diese Einstellung Auswirkungen auf den kompletten Code hat und eben nicht nur auf eine spezielle Methode. Man sollte diese Änderung also sehr dosiert vornehmen.

Kleiner Tipp noch am Rande: Die Spalte “User-unhandled” ist ausgeblendet, wenn unter Tools –> Options –> Debugging –> General der Punkt “Enable Just My Code” deaktiviert ist.

Eigene Wörterbücher für die Rechtschreibkontrolle in der Codeanalyse definieren

Nachdem ich für mein Projekt CodeAnalysis aktiviert hatte und dabei auch die Rechtschreibkontrolle angehakt hatte, bekam eine ganze Menge an Rechtschreibfehlern angezeigt, die sich hauptsächlich darauf bezogen, dass z.B. der Firmenname in Namespace-Namen enthalten waren und dieser angeblich falsch geschrieben war. Die im ersten Moment einfachste Lösung dafür ist: Rechtsklick -> Suppress in project suppression file. Dumm an dieser Lösung ist nur, dass mit jedem neuen Namespace das Problem wieder auftritt. Aus diesem Grund hab ich mich heute mit der etwas intelligenteren Lösung befasst und ein Custom Dictionary in das Projekt eingebunden. Ein guter Blogeintrag in dem steht wie man dazu vorgeht findet sich im Visual Studio Code Analysis Team Blog.

Wo sind meine Code Coverage-Ergebnisse?

Unittests find ich ja auch eine sehr sinnvolle Möglichkeit, die Qualität des eigenen Codes sicherzustellen und Probleme schon recht frühzeitig zu merken. Nun wollte ich heute mal schauen, wie hoch eigentlich meine Code Coverage ist und was muss ich da sehen? Code Coverage ist nicht verfügbar - oder wie es Visual Studio ausdrückt: "Code coverage is not enabled for this test run."....

Ein wenig Suche in der Konfiguration bringen die Ursache zu Tage: Unter "Tests" -> "Edit Test Run Configurations" -> "Local Test Run" ist einfach nichts angehakt gewesen. Offenbar ist die Code Coverage-Berechnung im Standard deaktiviert und muss erst explizit aktiviert werden.

Kleiner Haken - große Wirkung:

Direkt im Anschluss daran stolperte ich auch gleich über das nächste Problem: "Empty results generated: none of the instrumented binary was used. Look at the test run details for any instrumentation problems."

Wie vorgeschlagen, werf ich einen Blick in die Details. Dort steht aber nicht wirklich etwas, das mir weiterhelfen würde. Aber dann fällt es mir ein: In meinen PostBuild-Events installiere ich meine DLL gleich in den GAC. Vermutlich wird versucht, die DLL von dort zu laden und zu prüfen. Und siehe da: Nachdem ich meine Komponente aus dem GAC deinstalliert hab, bekomm ich wieder Ergebnisse angezeigt.

Erweiterungen für STSADM debuggen

Bei der Entwicklung von Erweiterungen für STSADM kommt man auch irgendwann an die Stelle an der man seine Entwicklung testen möchte. STSADM selbst läuft aber viel zu schnell durch als dass man "Attach to process" auswählen könnte.

Die Lösung ist recht trivial: Im Debug-Reiter des Projektes gibt man unter "Start external program" den Pfad zur stsadm.exe (c:\program files\common files\microsoft shared\web server extensions\12\bin\stsadm.exe) an und in "Command line arguments" die gewünschten Parameter.