Licht und Schatten

Vor einer Woche hat Microsoft den Veröffentlichungskandidaten von Visual Studio 2010 zum Download freigegeben. Ursprünglich war ja für Mitte Februar schon die finale Version angekündigt. Aufgrund der doch recht schwachen Performance der Beta 2 hat man sich aber für eine kurze Verschiebung entschieden und möchte mit einer RC-Version sicherstellen, dass alle Probleme behoben sind.

IDE und Editor

Alle bisherigen Visual Studio-Entwicklungsumgebungen waren weitgehend in nativem Code geschrieben. Mit Visual Studio 2010 ändert sich das jetzt grundlegend, die neue IDE setzt größtenteils auf Windows Presentation Foundation (auch bekannt unter WPF) auf. Das schließt auch den Texteditor ein.

Beim ersten Bearbeiten einer Quellcodedatei kam mir die Schrift etwas blass vor. Die Farbeinstellungen von Visual Studio 2008 wurden beim ersten Start übernommen, so dass es eigentlich keine Unterschiede geben sollte. Auch ein Vergleich der Farbeinstellung im Einstellungsdialog zeigte, dass die Werte für die Textfarbe gleich sind (schwarz). Hier mal ein Screenshot mit beiden Darstellungen, die obere Hälfte zeigt VS 2010 und die untere VS 2008:

Editor in VS 2010/2008

Ich weiß nicht, wie das andere empfinden – mir geht es auf die Augen.

Durch die Umstellung auf WPF ändert sich auch die gesamte Fensterstruktur in der IDE, da eine WPF-Anwendung weitgehend fensterlos daherkommt. Das werden einige AddIn-Entwickler zu spüren bekommen. Einer davon bin ich, mein geliebtes EasyTabs funktioniert nicht mehr und müsste neu geschrieben werden.

Class Wizard

Mit der neuen Version feiert ein Urgestein der VC-IDEs seine Auferstehung – der Class Wizard ist zurück. Die Umsetzung des Assistenten ist auf den ersten Blick gut gelungen, sie kommt für mich aber um einige Jahre zu spät. Mittlerweile habe ich mich nämlich daran gewöhnt, Überschreibungen und Bearbeitungsfunktionen für Nachrichten selbst im Editor einzugeben. So kann man die Funktionen gleich an der richtigen Stelle eintragen, wenn man eine gewisse Übersicht bevorzugt. Der Class Wizard hängt dagegen alles nacheinander als öffentliche Funktionen am Ende der Klassendefinition an. Hut ab, wer da am Ende noch den Überblick über die Klasse hat.

Sprache und Bibliotheken

An der C++-Sprachfront hat sich einiges getan. Der neue Compiler kann mit Lambda Expressions umgehen und  kennt Rvalue-Referenzen. Mit dem auto-Schlüsselwort erspart man sich die eine oder andere Typendeklaration. Im Moment habe ich noch keine Ahnung, was sich damit alles anstellen lässt. Bisher habe ich mich bei der Verwendung der C++-Standardbibliothek (STL) immer sehr zurückgehalten.

Auch bei der C/C++-Laufzeit und der ATL/MFC gibt es eine Menge Neuerungen. Die wohl wichtigste in der C++-Laufzeit ist die Concurrency Runtime, eine Klassenbibliothek, die das Erstellen von Multicore-Anwendungen erleichtern soll. Die neue MFC bietet direkte Unterstützung der Taskbar von Windows 7, inklusive Taskbar-Miniaturansichten für MDI-Anwendungen. Der schon in Windows Vista eingeführte Restart-Manager zieht endlich in die MFC ein. Eingebaut ist auch eine Unterstützung für Windows 7 Multitouch.

Verteilung der Dlls

Eine wesentliche Änderung betrifft die Verteilung der C/C++-Laufzeit und der MFC. Bis einschließlich Visual Studio 2003 wurden die Dlls immer nur in das Systemverzeichnis kopiert. Ab und zu sorgte das für Ärger, weil einige Softwareanbieter nicht mit Versionsinformationen umgehen konnten und bei der Installation auch mal eine neuere Version einer Dll mit ihren alten Version überschrieben. Das alles ist auch unter dem Namen Dll-Hölle bekannt.

Windows XP versprach Abhilfe und führte die Side-by-Side Manifeste ein. Jede Dll-Version wurde nun mit einem Manifest versehen und im WinSxS-Verzeichnis abgelegt. Der Anwendung wurde bei der Erstellung die benötigten Dlls eingeimpft. Ab Visual Studio 2005 wurden nun auch die C/C++-Laufzeit und die MFC nach diesem Schema verteilt. Doch die Praxis war nicht so gut wie die Theorie. Die Dlls mussten zwingend in das WinSxS-Verzeichnis installiert werden, portable Anwendungen waren nur unter erschwerten Bedingungen möglich. Besonders kritisch war es auch, wenn man versehentlich ein im DEBUG-Modus kompiliertes Modul in eine Release-Anwendung aufgenommen hatte. Der Windows-Programmlader beschwerte sich dann über eine fehlerhafte Anwendungskonfiguration und meinte damit eigentlich die fehlende C/C++-Laufzeit in der Debug-Version.

Diese Probleme sind anscheinend auch bei Microsoft nicht spurlos vorbeigegangen. Mit Visual Studio 2010 lässt man die Side-by-Side Manifeste wieder links liegen und kehrt in die Dll-Hölle zurück. Vermutlich ist dies das kleinere Übel, mir kann es nur recht sein.

Erstellung der MFC

Seit Visual C++ 1.5 waren die Makefiles für die MFC im Lieferumfang enthalten und man konnte sich die MFC so selbst kompilieren. Das war insbesondere bei Visual C++ 6 eine große Hilfe, weil die damalige MFC gerade mal Windows 98 unterstützte und mit den neuen Datei öffnen/speichern-Dialogen von Windows 2000 und Dateigrößen von mehr als 4 GiB ein wenig überfordert war. Als Visual Studio 2005 aktuell war und ich Visual C++ 6 immer noch bevorzugte, habe ich die MFC8 so angepasst, dass sie auch mit Visual C++ 6 verwendet werden konnten. Nicht zu vergessen auch die WinSxS-Hölle, der man durch eine Neukompilierung entrinnen konnte und die Möglichkeit, die für mich überflüssigen Erweiterungen der BCGControlbar loszuwerden.

Abgesehen davon habe ich die MFC intern auch etwas erweitert, um dem Anwender eine gezielte Sprachauswahl zu ermöglichen. Dazu kommt noch der eine oder andere Fix, z.B. um die Datei öffnen/speichern-Dialoge generell größenveränderbar zu machen. Dies alles ist Geschichte, wenn es nach Microsoft geht. Die MFC ist bei Visual Studio 2010 zwar weiter im Quellcode dabei, aber es fehlen die wichtigen Makefiles für die Erstellung und die .DEF-Dateien für die Exporte. Möglicherweise werden die MSBuild-Optionen später im Visual C++ Team-Blog veröffentlicht. Das gleiche gilt auch für die C/C++-Laufzeit, wobei hier neben den Makefiles noch viele Dateien fehlen, die früher nur als .obj-Dateien ausgeliefert wurden.

Fazit

Es fällt nicht leicht, ein Fazit zu ziehen. Die blasse Schrift und das in Zukunft fehlende EasyTabs machen es mir ziemlich schwer, mich in Visual Studio 2010 wohlzufühlen. Die neuen Möglichkeiten der C/C++-Laufzeit und der MFC locken natürlich, obwohl die fehlenden Makefiles der MFC schon ein ziemlicher Showstopper sind. Aber mal schauen, vielleicht kann man ja die Makefiles von Visual Studio 2008 recyclen.

VA X für VS 2010 ist auf dem Weg

Visual Studio ohne Visual Assist ist wie Windows ohne SpeedCommander. Im Blog von Whole Tomato ist nun zu lesen, dass mit einer Version für Visual Studio 2010 in den nächsten ein bis zwei Wochen gerechnet werden kann.

Visual Studio 2010 Beta 2

Zugegeben, ich bin diesmal etwas später dran. Seit Dienstag können sich MSDN-Abonennten die Beta 2 von Visual Studio 2010 herunterladen. Am Mittwoch wurde der öffentliche Download bereitgestellt. Martin hat in seinem Blog die wichtigsten Neuerungen zusammengefasst.

Visual Studio 2010 (Beta 1) in VMWare

Wer sich die Beta 1 von Visual Studio 2010 in VMWare installiert, der sollte unbedingt die DirectX-Grafikoption für die VM deaktivieren. Ansonsten gibt es ein paar unschöne Effekte, für die Visual Studio 2010 wohl nichts kann.

Unsichtbare Hauptsymbolleiste:

Unsichtbare Symbolleiste

Probleme bei der Menübedienung:

Unsichtbare Menüs

Fehlende Menüeinträge:

Leeres Menü

Fensterchaos nach Layoutänderungen:

Fensterchaos

Effizienter Programmieren mit Visual Studio

Der eine oder andere kennt vielleicht die vielen kleinen (insgesamt 382) Tips zu Visual Studio, die Sara Ford täglich in ihrem Weblog veröffentlicht hat. Im letzten Herbst hat sie 250 davon in einem Buch zusammengestellt, die deutsche Ausgabe ist mittlerweile auch erhältlich. Ich habe mir das Buch gerade bestellt. Auf der Couch macht das Lesen halt mehr Spaß als vor dem Rechner.

Erwähnenswert ist vielleicht noch, dass Sara Ford alle ihre Einkünfte aus dem Buchverkauf einem Stipendienfond zur Verfügung stellt, um Betroffene vom Wirbelsturm Katrina den Collegebesuch zu ermöglichen.

Symboldateien einzeln laden

Beim Debuggen von Memory-Dumps hat man meistens das Problem, dass die entsprechenden Windows-Symboldateien zum Snapshot des Anwenders nicht vorhanden sind. Letztlich muss eine Symboldatei immer genau zur jeweiligen Dll passen, damit der Debugger den Aufrufstack vernünftig anzeigen kann. Dank dem Microsoft-Symbolserver ist das aber kein großes Problem, der Debugger kann sich die passenden Symboldateien automatisch herunterladen.

Nachteilig ist, dass man keine Möglichkeit hat, die gewünschten Symboldateien auszuwählen. Startet man einen Dump mit aktiviertem Symbolserver, dann werden automatisch alle Symboldateien heruntergeladen, die zum jeweiligen Snapshot passen. Zudem lädt der Debugger auch noch die entsprechenden System-Dlls herunter, was natürlich entsprechend dauert.

Mit VS 2008 SP1 scheint Microsoft das Laden von Symboldateien erheblich vereinfacht zu haben. Gestern habe ich ein Kontextmenü entdeckt, das ich bisher noch nie gesehen hatte. Ich bin mir sicher, dass dieses Menü in der RTM-Version noch nicht enthalten war:

Symboldateien herunterladen

Nach Auswahl des Befehls wurde die passende Symboldatei für “kernel32.dll” heruntergeladen und der Aufrufliste aktualisiert. Genial!

TFS: Warehouse-Aktualisierung

Die TfsWarehouse-Datenbank enthält alle wichtigen Daten, die für die Generierung und Anzeige von Berichten nötig sind. Die Informationen stammen aus den operationalen Datenbanken (z.B. Arbeitsaufgaben, Versionskontrolle), sie werden durch den Warehouse-Webservice in die TfsWarehouse-Datenbank übertragen. Der TFSServerScheduler-Dienst sorgt dafür, dass dies stündlich geschieht. Allerdings läuft der Dienst wie berichtet nur auf einem an eine Domäne angeschlossenen Server.

Als Abhilfe habe ich mir ein kleines Programm geschrieben, welches die Aktualisierung der TfsWarehouse-Datenbank durch den Webservice anstößt. In Verbindung mit der Windows-Aufgabenplanung kann dies je nach Bedarf stündlich, täglich oder in anderen gewünschten Abständen geschehen. Optimaler wäre natürlich ein eigener Dienst, aber so schwer wollte ich es mir dann auch nicht machen.

  1. // ****************************************************************************
  2. // ****** Implementation zu wWinMain ******
  3. // ****************************************************************************
  4. int APIENTRY wWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPWSTR /*lpCmdLine*/, int /*nCmdShow*/)
  5. {
  6. // Internet-Session oeffnen
  7. HINTERNET hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
  8. if (NULL != hSession)
  9. {
  10. // Verbindung herstellen
  11. HINTERNET hConnect = WinHttpConnect(hSession, L"localhost", 8080, 0);
  12. if (NULL != hConnect)
  13. {
  14. // Anforderung erstellen
  15. HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/Warehouse/v1.0/warehousecontroller.asmx/Run", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
  16. if (NULL != hRequest)
  17. {
  18. // Anforderung senden
  19. BOOL fResult = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
  20.  
  21. // Anforderung wurde gesendet
  22. if (fResult && WinHttpReceiveResponse(hRequest, NULL))
  23. {
  24. // Antwort abfragen
  25. char szResponse[2048] = { 0 }; DWORD dwBytesRead = 0;
  26. WinHttpReadData(hRequest, szResponse, 2048, &dwBytesRead);
  27. }
  28.  
  29. // Anforderung schliessen
  30. WinHttpCloseHandle(hRequest);
  31. }
  32.  
  33. // Verbindung schliessen
  34. WinHttpCloseHandle(hConnect);
  35. }
  36.  
  37. // Session freigeben
  38. WinHttpCloseHandle(hSession);
  39. }
  40.  
  41. // Ans kloar
  42. return 0;
  43. }

Es wird einfach nur eine Url aufgerufen und die Antwort abgefragt, auf eine Fehlerausgabe habe ich verzichtet. Das kompilierte Programm könnt ihr hier herunterladen.

MFC abgespeckt

Letzte Woche Montag ist das Service Pack 1 für Visual Studio 2008 erschienen. Wichtige Neuerungen für den C++-Entwickler sind sicherlich die Unterstützung von TR1 und das UI-Update für die MFC. Nach den Installationsproblemen mit dem im April veröffentlichten Feature Pack wollte ich eigentlich erst einmal die Erfahrungen anderer abwarten.

Daraus wurde dann doch nichts. Zu Testzwecken hatte ich mir ein VS 2008 in einer VM installiert und anschließend das SP1 eingespielt. Probleme gab es keine, die Microsoft-Entwickler haben aus dem Feature Pack-Dilemma gelernt und diesmal wieder ausreichend getestet.

Erfreulicherweise hat Microsoft auch das Konzept beibehalten, die bisherige MFC sowie die neuen UI-Klassen nicht zu verzahnen. Somit kann man die Einbindung der neuen Klassen durch Entfernen der entsprechenden Sektion im Makefile sehr einfach entfernen und die MFC weiter im bisherigen Umfang verwenden. Nach dem Löschen der nicht mehr benötigten Dateien hat man wieder ein schlankes und übersichtliches MFC-Verzeichnis.

Neben den neuen UI-Klassen gab es in der Standard-MFC nur kleinere Korrekturen. Die in afximpl.h definierten Konstanten CX_BORDER und CY_BORDER wurden nach AFX_CX_BORDER und AFX_CY_BORDER umbenannt. Bei einigen Zeigern fehlte bisher die Prüfung gegen NULL, das wurde mit dem SP1 auch behoben.

Nach den positiven Erfahrungen bei der VM-Installation habe ich das SP1 dann auch auf meinem Entwicklungsrechner eingespielt sowie C/C++-Laufzeit und MFC kompiliert. Die Anleitungen für die C/C++-Laufzeit sowie für die MFC sind weiter gültig, zusätzlich müssen für einen manifestlosen Einsatz die Linkerkommentare in appmodul.cpp

#pragma comment(linker, “/include:__forceMFCManifestRTM”)

und crtdll.c

#pragma comment(linker, “/include:__forceCRTManifestRTM”)

auskommentiert werden. Ansonsten beschwert sich der Linker beim Erstellen der CRT sowie beim Erstellen einer MFC-Anwendung über einen fehlenden Import. Bisher habe ich leider noch nicht herausgefunden, was diese beiden Linkerkommentare bewirken sollen. Die RTM-Version kam noch ohne diese aus.

Fehler 1603 bei der Installation von TFS 2008 SP1

Die Aktualisierung auf TFS 2008 SP1 wurde kurz vor Fertigstellung mit dem Fehler 1603 beendet. Beim Durchstöbern der Log-Dateien entdeckte ich folgende Zeilen:

Using workflow file from location exe.
Executing workflow ‘Unquiesce AT’…
Stopping Windows Service ‘W3SVC’…
Starting Windows Service ‘W3SVC’…
Starting Windows Service ‘TFSServerScheduler’…
Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden.
Retrying…
Starting Windows Service ‘TFSServerScheduler’…
Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden.
Retrying…
Starting Windows Service ‘TFSServerScheduler’…
Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden.
Retrying…
Starting Windows Service ‘TFSServerScheduler’…
Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden.
Retrying…
Starting Windows Service ‘TFSServerScheduler’…
Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden.
Retrying…
Starting Windows Service ‘TFSServerScheduler’…
System.InvalidOperationException: Der Dienst TFSServerScheduler kann nicht auf dem Computer . gestartet werden. —> System.ComponentModel.Win32Exception: Der angegebene Dienst kann nicht gestartet werden. Er ist deaktiviert oder nicht mit aktivierten Ger„ten verbunden
   — Ende der internen Ausnahmestapelberwachung —

Nach diesen Zeilen startete dann das Rollback. 

Die Startprobleme mit TFSServerScheduler kenne ich schon seit der Installation des TFS. Dieser Dienst ist dafür verantwortlich, die Warehouse-Datenbanken zu aktualisieren, auf denen die verschiedenen generierten Reporte aufbauen. TFSServerScheduler ist abhängig vom Windows-Anmeldedienst (Netlogon), der sich nach dem Start auf normalen Servern und Arbeitsplatzrechnern aber gleich wieder beendet. Er ist der Meinung, dass seine Dienste nur beim Arbeiten in einer Domäne nötig sind. Um auf die Berichte nicht verzichten zu müssen, habe ich mir ein kleines Hilfsprogramm geschrieben. Dazu demnächst mehr.

Dummerweise lässt sich der TFS aber nicht direkt auf einem Domänencontroller (DC) installieren. Bis kurz vor der finalen Version von TFS 2005 war das wohl noch möglich, laut Berichten in diversen Foren soll das mit der nächsten Version (Rosario) auch wieder möglich sein. Allerdings habe ich keine Lust, mir bis dahin noch einen zweiten Server als DC einzurichten.

Das halb eingespielte Update hatte den TFS 2008 aber in einen undefinierten Status gebracht, Verbindungsversuche wurden mit folgendem Fehler abgelehnt:

TF31001: Team Foundation kann die Liste von Teamprojekten aus Team Foundation Server nicht abrufen. Team Foundation Server gab folgenden Fehler zurück: Fehler bei der Anforderung mit HTTP-Status 503: TF30059: Schwerwiegender Fehler beim Initialisieren des Webdiensts.

Was tun? Die Lösung bestand darin, auf meinem Entwicklungsrechner in einer VM einen Windows Server 2003 zu installieren und diesen als DC einzurichten. Nach dem Beitritt des Server zu dieser Domäne ließ sich auch der Windows-Anmeldedienst samt TFSServerScheduler starten und das Update lief fehlerfrei durch. Anschließend hat der Server die Domäne wieder verlassen und läuft nun wieder eigenständig.

Bin ich denn etwa der Einzige, der den TFS 2008 ohne Domäne betreibt?

TFS: Dateidatum beim Verzweigen erhalten

Beim Verzweigen von Projekten im TFS und anschließenden Abruf des neuen Projekts bekommen die Dateien immer das aktuelle Systemdatum als Datum der letzten Änderung verpasst. In SourceSafe war es noch möglich, beim Abruf zwischen dem Systemdatum, dem Datum des Eincheckens und dem Datum der letzten Änderung zu wählen. Im TFS habe ich diese Einstellung leider noch nicht gefunden, ich würde aber das Datum der letzten Änderung bevorzugen.

Als Workaround habe ich mir ein kleines Programm geschrieben, welches das Änderungsdatum eines Verzeichnisbaums auf einen anderen überträgt. Der Aufruf erfolgt über die Kommandozeile mit dem Befehl

SyncModified.exe <SourceDir> <TargetDir>

Das Quellverzeichnis wird inklusive den Unterverzeichnissen durchlaufen und das Datum der letzten Änderung einer jeden Datei in das Zielverzeichnis übernommen (sofern die Datei dort existiert). Ein eventuell gesetztes Schreibschutzattribut bleibt erhalten.

Das kleine Tool (76 KiB) könnt ihr hier herunterladen.