Files via lokale HTML-Links öffnen

Visual Studio ist – unter vielem anderen – ein ganz passabler HTML-Editor, wenn man sich damit anfreunden kann, direkt in HTML zu arbeiten. Es muss ja nicht immer gleich eine Riesending wie Microsoft Expression Web oder Dreamweaver sein für Modifikationen an ein paar Seiten.

Eine Funktion habe ich allerdings so vermisst, dass ich sie per Makro nachgerüstet habe: eine Funktion, um einem lokalen HTML-Link zu folgen und das referenzierte File zu öffnen. Hat man z.B. im HTML-Text das folgende:

<a href=“sample.html“>

sollte es auf ganz einfache Weise möglich sein, dem Link zu folgen und das File sample.html in Visual Studio zu öffnen, auch wenn man kein Projekt hat, das dieses File enthält, weil man einfach mit einer Directory voller HTML-Files arbeitet.

Mit dem folgenden Makro braucht man nur den Cursor in den Filenamen zu positionieren und dann das Makro zur Ausführung zu bringen. (Am besten konfiguriert man natürlich eine Tastenkombination oder mindestens ein Icon in einer Toolbar hierzu.)

  Public Sub OpenFileAtCursor()
    Dim activeDoc As Document
    Dim sel As TextSelection
    Dim line As String
    Dim fileName As String
    Dim basePath As String
    Dim cursorColumn As Integer
    Dim startPos As Integer
    Dim endPos As Integer
    activeDoc = DTE.ActiveDocument
    sel = activeDoc.Selection
    cursorColumn = sel.AnchorPoint.LineCharOffset
    sel.SelectLine()
    line = sel.Text
    sel.Collapse()
    startPos = InStrRev(line, """", cursorColumn)
    endPos = InStr(cursorColumn, line, """")
    fileName = Mid(line, startPos + 1, endPos - startPos - 1)
    fileName = Replace(fileName, "/", "\")
    If Left(fileName, 1)  "\" Then
      basePath = Path.GetDirectoryName(activeDoc.FullName)
      fileName = basePath + "\" + fileName
    End If
    If File.Exists(fileName) Then
      DTE.ExecuteCommand("File.OpenFile", fileName)
    Else
      DTE.StatusBar.Text = "File """ + fileName + """ not found"
    End If
  End Sub
Advertisements
Veröffentlicht in Keine Kategorie. Schlagwörter: , , . Leave a Comment »

Forms in Visual Studio Macros

Kann man in Macros für Visual Studio Forms verwenden, oder sind diese damit überfordert? Wenn ein Macro eine Liste anzeigen will, kann es dazu eine System.Windows.Form mit einer ListBox oder sogar DataGridView verwenden, statt nur Zeilen von Text mit Hilfe einer MsgBox auszugeben oder das Output-Fenster zu verwenden?

Als ich mir kürzlich diese Frage stellte, brachte mich Google nicht weiter – ich konnte weder eine Bestätigung noch ein Dementi finden. Ich begann deshalb selbst zu experimentieren.

Erste Versuche waren nicht sehr hoffnungsvoll: Einen Designer für Forms konnte ich in der Macros IDE nicht finden. System.Windows.Forms zu importieren klappte, aber beim Aufruf der Methode Show für eine Form verhakte sich das System irgendwie. Zudem schienen alle Events in der Liste zu fehlen, die IntelliSense anzeigte für Form.

Bei einem zweiten Anlauf klärte sich allerdings einiges: ShowDialog anstelle von Show funktioniert problemlos, und betreffend Events wusste ich einfach zu wenig darüber, wie man diese genau in Visual Basic deklariert – irgendwie erstaunlich anders als in C#.

Einen Designer konnte ich auch im zweiten Anlauf nicht finden, aber das ist schliesslich kein grosses Hindernis, weil man die paar Controls, die man brauchen wird für eine Form in einem Macro, natürlich per Code produzieren kann.

Also kann ich bestätigen: Forms funktionieren in Macros für Visual Studio.

Veröffentlicht in Keine Kategorie. Schlagwörter: , , . Leave a Comment »

Von Fehler zu Fehler

Ich bin diesbezüglich vielleicht ein bisschen eigen, aber ich mag das Fenster Error List in Visual Studio nicht besonders: Die Art und Weise, wie da während dem Tippen von Code andauernd die Fehler auftauchen und wieder verschwinden, stört mich irgendwie und lenkt mich ab.

Ich habe mir deshalb das folgende Makro programmiert, mit dessen Hilfe ich den Cursor von Fehler zu Fehler navigieren kann, wobei der Fehlertext gleich im Statusbereich angezeigt wird. Das ist nicht nur bequemer, als einen Fehler um den anderen in der Error List anzuklicken, sondern ermöglicht mir eben auch, die Error List im Normalfall geschlossen zu halten, womit sich das Problem mit der Ablenkung erledigt hat.

Ich habe hierzu ein Icon in Visual Studio konfiguriert, welches das Makro GoToNextError aufruft.

Eine kleine Schwierigkeit, die sich beim Implementieren des Makros ergab und die noch auf eine elegantere Lösung wartet als jetzt programmiert: Das Makro muss irgendwie merken, dass neu kompiliert wurde, um mit dem Durchgehen der Fehler wieder von vorne beginnen zu können, gesteuert durch die Variable currentError. (Natürlich könnte man ein kleines zweites Makro mit einem zweiten Icon bauen, um von vorne zu beginnen, aber wenn es automatisch geht, ist das bequemer.)

Hierzu wird eine Art „Hashcode“ über die Liste aller Fehler gebildet, und wenn diese ändert, nimmt man an, dass neu compiliert wurde.

Ich war usprünglich skeptisch, ob sich die Einarbeitung in die Visual-Studio-Makro-Programmierung wirklich lohnt, und war auch ein bisschen abgeschreckt durch Visual Basic statt C# als Makro-Sprache und die seltsamen „DTE“-Objekte, aber diese Skepsis hat sich gelegt. Und schliesslich gibt es auch bei einem so ausgereiften Werkzeug wie der Visual-Studio-IDE immer mal wieder etwas zu verbessern, vor allem, wenn die eigene Arbeitsweise etwas ausserhalb des „Mainstream“ liegt…

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

Public Module BrMacros
  Private hashCode As Integer
  Private errList As ErrorList
  Private currentError As Integer

  Private Function ErrorListHashCode() As Integer
    ' Detektiere heuristischerweise eine NEUE Error-Liste nach Kompilation an Hand einer Art Hashcode
    Dim h As Integer
    Dim i As Long
    Dim errItem As ErrorItem
    For i = 1 To errList.ErrorItems.Count
      errItem = errList.ErrorItems.Item(i)
      If Not (errItem.FileName Is Nothing) Then
        h = h + errItem.Line + errItem.Column
      End If
    Next
    ErrorListHashCode = h
  End Function

  Private Function ErrorCount() As Integer
    Dim n As Integer
    Dim i As Long
    Dim errItem As ErrorItem
    n = 0
    For i = 1 To errList.ErrorItems.Count
      errItem = errList.ErrorItems.Item(i)
      If errItem.ErrorLevel = vsBuildErrorLevel.vsBuildErrorLevelHigh Then
        n = n + 1
      End If
    Next
    ErrorCount = n
  End Function

  Public Sub GoToNextError()
    errList = DTE.ToolWindows.ErrorList
    If ErrorCount() = 0 Then
      Exit Sub
    End If
    Dim h As Integer
    h = ErrorListHashCode()
    If h <> hashCode Then
      hashCode = h
      currentError = 1
    End If
    Dim numErrors = errList.ErrorItems.Count
    Dim errItem As ErrorItem
    Do
      If currentError > numErrors Then
        currentError = 1   ' Cycle
      End If
      errItem = errList.ErrorItems.Item(currentError)
      currentError = currentError + 1
      If errItem.ErrorLevel = vsBuildErrorLevel.vsBuildErrorLevelHigh Then
        errItem.Navigate()
        DTE.StatusBar.Text = errItem.Description
        Exit Sub
      End If
    Loop
  End Sub

End Module
Veröffentlicht in Keine Kategorie. Schlagwörter: , , , . Leave a Comment »