Komfortabler Dateimanager mit vielen Funktionen

Visual Studio

CodeLens für C++ in TFVC

By Sven on 07.04.2017 - 09:00 in TFS, Visual Studio 2015 with 2 Kommentare

Eine große Neuerung in Visual Studio 2013 war CodeLens. Allerdings konnten sich nicht viele Entwickler darüber freuen, denn diese Funktion blieb den Käufern der sehr teuren Ultimate-Edition vorbehalten. Zudem war CodeLens anfangs auch auf .NET-Code beschränkt, C++-Entwickler hatten nichts davon.

Mit Visual Studio 2015 kamen auch die Professional-Anwender in den Genuss von CodeLens, zudem wurde die CodeLens-Funktion auf C++-Dateien ausgeweitet. Voraussetzung ist allerdings ein GIT-Repository. Ein Umstieg von TFVC auf GIT kommt für mich aber nicht in Frage, weil damit auch die ganze Versionsgeschichte verlorengeht. Alle TFS-Anwender mit TFVC (Team Foundation Version Control) – also die große Mehrheit – blieben somit außen vor. In den Kommentaren zum verlinkten Blogeintrag wurde gefragt, ob CodeLens auch einmal für TFVC zur Verfügung stehen würde. Der Antwort nach sollte dies innerhalb des VS 2015-Zeitrahmens möglich sein.

Seitdem habe ich keinen weiteren Hinweis dazu gefunden, nicht in den Updatehinweisen zu Visual Studio 2015, nicht in denen zu Team Foundation Server 2015 und auch nicht zur VS 2017-Produktreihe. Blieb also nur der Selbstversuch. Aber auch nach der Aktualisierung meines TFS 2013.5 auf TFS 2015.3 blieb es beim leeren CodeLens-Fenster:

Mit Hilfe des CodeIndex-Befehls und dem Parameter /reindexAll habe ich den Index dann noch einmal erzeugt. Und siehe da:

Die neuen CodeLens-Informationen muss man sich allerdings auch mit einer größeren Datenbank erkaufen. Vor der Indizierung war meine TFS-Datenbank 2 GiB groß, nach der Indizierung belegt sie 4 GiB.

Neue IDE mit altem Compiler

By Sven on 04.04.2017 - 11:00 in Visual Studio 2015 with 1 Kommentar

Bei mir läuft immer noch Visual Studio 2013. Ein Umstieg auf Visual Studio 2015 kam damals nicht in Frage. Mit dem ersten Update wurden zwar die Spaltenbreite im Quellcodeverwaltungs-Explorer bei HiDPI-Auflösungen angepasst, andere HiDPI-Probleme (z.B. die Größe Kleine der Aktionsschalter beim Zusammenführen) existieren allerdings immer noch. Der größte Nachteil war für mich aber die aus 40 Mini-Dlls bestehende neue Universal CRT, die mittlerweile auch als optionales Update für Windows 7 und 8 über Windows Update verteilt wird. Nach dem GWX-Trojaner kann ich aber jeden verstehen, der nur die wichtigen Updates installiert und alle optionalen Updates links liegen lässt. Irgendetwas in mir sträubt sich dagegen, diese 40 Dlls bei der Installation pauschal in das SpeedCommander-Programmverzeichnis zu kopieren.

Mit dem Release von Visual Studio 2017 vor vier Wochen habe ich mich einmal wieder etwas intensiver mit dem Thema IDE und Compiler beschäftigt. Microsoft wirbt ja damit, dass die Performance von IDE und Compiler/Linker bedeutend zugelegt hat. Beim Öffnen meines SpeedCommander-Arbeitsbereichs mit 40 Projekten konnte ich aber keinen großen Unterschied feststellen. Das Erstellen von SpeedCommander samt den abhängigen Projekten dauert mit dem Compiler/Linker von VS 2013 ca. 2:10 Minuten, mit dem VS 2017-Toolset dagegen 2:30 Minuten. Das hat mich dann doch etwas überrascht. Man kann zwar auch weiter das alte VS 2013-Toolset verwenden (wenn beide Versionen nebeneinander installiert werden), allerdings wird dann im Projektmappen-Explorer bei jedem Projekt der Zusatz (Visual Studio 2013) angefügt. Bei den ganzen Zusätzen gehen die Projektnamen völlig unter und sind nur noch schwer herauszulesen.

Das brachte mich auf die Idee, dem VS 2017 einfach mal das VS 2013-Toolset als sein eigenes VS 2017-Toolset unterzujubeln. Die Projekte werden also auf das neue Toolset umgestellt, was den Zusatz (Visual Studio 2013) im Projektmappen-Explorer entfernt. Zudem werden die VC-Verzeichnisse atlmfc, bin, crt, include und lib aus VS 2013 nach VS 2017 übertragen. Das neue Layout des VC-Ordners in VS 2017 erfordert zwar einige Anpassungen, am Ende kann man aber den alten Compiler für VS 2017-Projekte verwenden. Das einzige, was wirklich stört, ist eine öfters ausgegebene D9002-Warnmeldung des VC 2013-Compilers über eine nicht unterstützte Kommandozeilenoption. Das lässt sich auch nicht abstellen.

Also machte ich den gleichen Test noch einmal mit einem frisch installierten Visual Studio 2015. Die wichtigsten IDE-Neuerungen im Vergleich zu VS 2013 passierten größtenteils in VS 2015, in VS 2017 kam nicht mehr viel dazu. Die fünf Verzeichnisse aus VS 2013 konnte ich 1:1 nach VS 2015 übernehmen. Die Projekte wurden ohne Fehler und Warnhinweise kompiliert und anschließend gegen die alte VC 2013-Laufzeit gelinkt. Das Starten und Debuggen des kompilierten Programms verlief ebenfalls ohne Schwierigkeiten. Anschließend habe ich noch die verschiedenen alten vcvarsxxxx.bat-Dateien des VS 2013-Toolsets durch die Pendants von VS 2015 ersetzt, damit man die Projekte auch per Kommandozeile kompilieren kann.

Das ist für mich nun die perfekte Kombination. Das Entwicklerherz erfreut sich an den Neuerungen von Visual Studio 2015, während die kompilierten Programme weiter die alte Laufzeit mit zwei Dlls verwenden und nicht die Universal CRT mit 40 Mini-Dlls voraussetzen. Zudem hat Visual Studio 2015 vermutlich alle Feature-Updates hinter sich. Zusammen mit dem alten Compiler ist das eine gute Basis für die nächsten Jahre.

Noch kein Umstieg auf Visual Studio 2015

By Sven on 04.08.2015 - 11:35 in Visual Studio 2015 with 2 Kommentare

Gestern vor zwei Wochen wurde die finale Version von Visual Studio 2015 veröffentlicht. Seitdem war Zeit, um etwas damit herumzuspielen und einen möglichen Umstieg zu evaluieren.

Universal CRT

Zur neuen Universal CRT hatte ich schon einen längeren Beitrag geschrieben. Mit der finalen Version von Visual Studio 2015 kann die Universal CRT nun auch den Anwendungen beigelegt werden und muss nicht zwingend über Windows Update oder über das eigenständige Installationspaket vcredist.exe eingespielt werden. Gut, dass Microsoft hier so flexibel reagiert hat.

Nach einem Blick in das Verzeichnis C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86 war ich allerdings etwas erschrocken. Zur Universal CRT gehören 40 Dateien, die meisten davon nicht größer als 20 KiB:

Dateien der Universal CRT

Diese müsste man bei anwendungslokaler Verwendung alle in das SpeedCommander-Programmverzeichnis kopieren.

Codelens

Eine vielbeworbene Neuerung ist Codelens. Bisher war Codelens nur in der Ultimate-Ausgabe enthalten, mit Visual Studio 2015 gibt es diese Funktion bereits mit der Professional-Version. Codelens sorgt dafür, dass alle wichtigen Änderungsinformationen aus der Quellcodeverwaltung direkt im Kontext zu sehen sind. Bei C#/VB-Code werden die Infos direkt im Quellcode angezeigt, bei C++-Dateien erfolgt die Anzeige für die gesamte Datei:

Codelens in VS 2015 (1) Codelens in VS 2015 (2)

Prinzipiell eine schöne Sache. Leider ist Codelens für C++-Dateien auf Git-Repositories beschränkt und funktioniert im Gegensatz zu C#/VB-Dateien nicht mit der normalen TFVC-Versionskontrolle. Also eine Funktion, die ein Großteil der TFS-Anwender vorerst nicht nutzen kann (sofern man nicht auf Git umstellt und damit seine gesamte Änderungshistorie verliert).

HiDPI-Probleme beim Team Explorer

Öffnet man den Quellcodeverwaltungs-Explorer, dann wird man mit folgender Ansicht beglückt:

Team Explorer in VS 2015

Um die Dateinamen oder das Datum erkennen zu können, muss man jedesmal die Spalten manuell aufziehen. Der Grund für die schmalen Spalten ist der Umstand, dass die Spaltenbreiten fest vorgegeben sind und nicht entsprechend der aktuellen DPI-Vergrößerung umgerechnet werden. Das Aufziehen wäre auch kein Problem, wenn sich der Explorer die letzte Einstellung merken würde. So muss man bei jeder Anzeige die Spalten neu aufziehen, um etwas erkennen zu können.

Beim Zusammenführen von Änderungen sind die Schaltflächen für die einzelnen Aktionen arg klein:

Merge-Fenster in VS 2015

Man muss sich jedesmal Mühe geben, die Schaltfläche mit der Maus (bzw. dem Trackpad) zu treffen. Beide Anzeigeprobleme gab es schon in Visual Studio 2013. Anfang Januar habe ich Microsoft darüber informiert. Microsoft war allerdings der Meinung, dass diese Sachen nicht schwerwiegend genug seien, um sie für Visual Studio 2015 zu fixen. Aber was helfen neue hochauflösende Symbole für HiDPI-Umgebungen, wenn der Arbeitsfluss durch solche Unzulänglichkeiten extrem behindert wird?

So habe ich damals selbst Hand angelegt und die Werte in den entsprechenden Ressourcen-Dlls angepasst. Das gleiche wollte ich nun auch für Visual Studio 2015 machen. Dummerweise lädt die Team Explorer-Erweiterung jetzt nur noch von Microsoft signierte Ressourcendateien. So lassen sich die Fehler nicht mehr selbst beheben.

Fazit

Von meiner Vorfreude auf Visual Studio 2015 ist nicht viel übrig geblieben. Natürlich kann man sein Programmverzeichnis mit weiteren 40 Dateien füllen, ohne die Funktionalität zu behindern. Aber irgendetwas in mir stört sich daran. Codelens funktioniert nicht in meiner Umgebung und die in Visual Studio 2013 selbst behobenen HiDPI-Probleme kehren in Visual Studio 2015 wieder zurück. Bisher gibt es für mich also keinen zwingenden Grund für einen Umstieg.

Anwendungslokaler Einsatz der Universal CRT

By Sven on 24.06.2015 - 10:20 in Visual Studio 2015 with 1 Kommentar

Stephan T. Lavavej hat in einem Kommentar im Visual C++ Team Blog angekündigt, dass eine anwendungslokale Verwendung der Universal CRT mit der RTM-Version von Visual Studio 2015 möglich sein wird:

I’ve received confirmation that app-local deployment will be fully supported in 2015 RTM. This includes the Universal CRT, the STL, and everything else as usual. (Note that this applies to desktop apps only; store apps inherently use the framework packages.)

Damit steht einem Wechsel zum (hoffentlich) bald erscheinenden Visual Studio 2015 nicht mehr viel im Weg.

Zoom-Größe in Visual Studio permanent ändern

By Sven on 13.05.2015 - 11:00 in Visual Studio 2013 with Keine Kommentare

Die bevorzugte Schriftgröße für den Texteditor lässt sich bekanntermaßen im Einstellungsdialog ändern. Manchmal würde man aber gerne eine Zwischengröße verwenden, weil 8 Punkte zu klein und 9 Punkte zu groß sind. Allerdings werden nur Ganzzahlen akzeptiert und man muss sich für eine Größe entscheiden.

Hier könnte das Zoom-Eingabefeld am unteren linken Rand des Texteditors weiterhelfen, mit dem man die Schriftgröße viel feinstufiger anpassen kann. Könnte helfen, denn Visual Studio öffnet jedes neue Fenster mit 100%, ein Standardwert lässt sich nirgends vorgeben. Eine ständige Korrektur der Zoom-Größe bei jedem neuen Fenster ist natürlich auch keine praktikable Lösung.

Abhilfe schafft die TroutZoom-Erweiterung. Einmal installiert merkt sie sich den zuletzt eingestellten Wert und sorgt dafür, dass neue Fenster immer mit dieser Zoom-Größe geöffnet werden. Zudem werden bei einer Änderung der Größe automatisch auch alle anderen geöffneten Fenster angepasst. Der Quellcode für die Erweiterung ist auch verfügbar. Wenn man sich den Quellcode mal anschaut, dann fragt man sich, warum die 10 Zeilen nicht gleich Bestandteil von Visual Studio sind.

Visual Studio 2015 und die Universal CRT

By Sven on 12.05.2015 - 11:15 in Visual Studio 2015 with 2 Kommentare

Entwickler von portablen Programmen, die sich ohne Installation aufrufen lassen, sollten sich den Umstieg auf Visual Studio 2015 gut überlegen. Grund dafür ist die neue universelle Laufzeitbibliothek für C/C++ (Universal CRT). Bisher brauchte man nur die C/C++-Laufzeitbibliotheken msvcr120.dll und msvcp120.dll der Anwendung beilegen und die Anwendung konnte aus jedem Verzeichnis gestartet werden. Mit Visual Studio 2015 hat Microsoft die Laufzeitbibliothek in einen universellen und einen compilerabhängigen Teil aufgeteilt. Der universelle Teil ucrtbase.dll wird Bestandteil von Windows 10 und kann in Zukunft über Windows Update aktualisiert werden. Ältere Windows-Versionen können die Universal CRT ebenfalls über Windows Update einspielen, alternativ ist auch die Verwendung eines eigenständigen Installationspakets vcredist.exe möglich, das 14 MB groß ist und neben der Universal CRT auch alle anderen Laufzeitbibliotheken (inklusive MFC) enthält.

Problematisch an der ganzen Geschichte ist, dass der universelle Teil fest im Windows-Systemverzeichnis residieren soll und nicht mehr in das Anwendungsverzeichnis kopiert werden darf. Unter Windows 10 ist das nicht weiter tragisch. Der universelle Teil ist immer vorhanden, der compilerabhängige Teil kann mit der vcruntime140.dll weiter der Anwendung beigelegt werden. Auf den älteren Systemen muss der universelle Teil aber vor dem Starten der Anwendung installiert werden, entweder über Windows Update oder über das eigenständige Installationspaket. Auf dem eigenen Rechner ist das eine einmalige Sache und sollte nicht weiter stören. Der Zweck eines portablen Programms ist aber, dass man es schnell auf jedem Rechner starten kann und dafür in der Regel keine Administrator-Rechte benötigt. Mit dem Einzug der Universal CRT klappt das auf Windows XP/Vista/7 und 8 nur noch, wenn diese vom Administrator vorher installiert wurde. Ansonsten startet das Programm nicht. Man kann dies nur umgehen, indem man die C/C++- und MFC-Laufzeitbibliotheken statisch einbindet. Damit kann sich aber auch die Programmgröße wesentlich erhöhen, insbesondere wenn eine Anwendung aus mehreren Modulen besteht.

Wenn Microsoft für dieses Problem keine Lösung findet, dann werden Entwickler von portablen Programmen bei Visual Studio 2013 bleiben müssen. Man kann Visual Studio 2013 und 2015 zwar parallel installieren und in Visual Studio 2015 die Projekte auch mit den 2013-Tools erstellen. Dabei muss man aber auf die neuen Compilerfunktionen und -optimierungen verzichten.

Eine weitere Möglichkeit wäre die Verwendung der CRT/MFC aus Visual Studio 2013 in Visual Studio 2015. Dafür kopiert man die Verzeichnisse VC\atlmfc, VC\crt, VC\include und VC\lib aus 2013 nach 2015. Ein MFC-Beispielprojekt lässt sich so fehlerfrei kompilieren, beim Linken gibt es allerdings ein paar nicht aufgelöste Referenzen:

1>MainFrm.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__Init_thread_header" in Funktion ""protected: static struct AFX_MSGMAP const * __stdcall CMainFrame::GetThisMessageMap(void)" (?GetThisMessageMap@CMainFrame@@KGPBUAFX_MSGMAP@@XZ)".
1>stdafx.obj : error LNK2001: Nicht aufgelöstes externes Symbol "__Init_thread_header".
1>MainFrm.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__Init_thread_footer" in Funktion ""protected: static struct AFX_MSGMAP const * __stdcall CMainFrame::GetThisMessageMap(void)" (?GetThisMessageMap@CMainFrame@@KGPBUAFX_MSGMAP@@XZ)".
1>stdafx.obj : error LNK2001: Nicht aufgelöstes externes Symbol "__Init_thread_footer".
1>MainFrm.obj : error LNK2001: Nicht aufgelöstes externes Symbol "__Init_thread_epoch".
1>stdafx.obj : error LNK2001: Nicht aufgelöstes externes Symbol "__Init_thread_epoch".

1>MFCApplication1Doc.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl operator delete(void *,unsigned int)" (??3@YAXPAXI@Z)" in Funktion ""public: virtual void * __thiscall CDocument::CDocumentAdapter::`scalar deleting destructor'(unsigned int)" (??_GCDocumentAdapter@CDocument@@UAEPAXI@Z)".
1>stdafx.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""void __cdecl operator delete(void *,unsigned int)" (??3@YAXPAXI@Z)".

1>ChildFrm.obj : error LNK2001: Nicht aufgelöstes externes Symbol "___std_terminate".

Nach dem Setzen der zusätzlichen Compileroptionen (Projekteinstellungen – C/C++ – Befehlszeile)

/Zc:threadSafeInit-,sizedDealloc-,implicitNoexcept-

lässt sich das MFC-Beispielprojekt ohne Fehler mit dem Compiler von Visual Studio 2015 erstellen und aufrufen. Es verwendet die C-/C++/MFC-Laufzeitbibliotheken von Visual Studio 2013 und kann somit wie gewohnt verteilt werden.

Beim weiteren Test mit SpeedCommander wurden mir noch zwei weitere Referenzen nicht aufgelöst:

1>SpeedCommander.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __stdcall `eh vector constructor iterator'(void *,unsigned int,unsigned int,void (__thiscall*)(void *),void (__thiscall*)(void *))" (??_L@YGXPAXIIP6EX0@Z1@Z)" in Funktion ""public: virtual void __thiscall CSpeedCommanderApp::LoadState(void)" (?LoadState@CSpeedCommanderApp@@UAEXXZ)".
1>SpeedCommander.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __stdcall `eh vector destructor iterator'(void *,unsigned int,unsigned int,void (__thiscall*)(void *))" (??_M@YGXPAXIIP6EX0@Z@Z)" in Funktion ""public: void * __thiscall ATL::CStringT<wchar_t,class StrTraitMFC_DLL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >::`vector deleting destructor'(unsigned int)" (??_E?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QAEPAXI@Z)".

Die Ursache dafür ist, dass sich die Parameter für die vom Compiler generierten Funktionen __ehvec_ctor und __ehvec_dtor leicht geändert haben und so nicht mehr denen der VS 2013-Laufzeitbibliothek entsprechen. Zur Abhilfe fügt man die Zeilen

#define CALEETYPE __stdcall
#define __RELIABILITY_CONTRACT
#define SECURITYCRITICAL_ATTRIBUTE
#define ASSERT_UNMANAGED_CODE_ATTRIBUTE

#if defined _M_IX86
#define CALLTYPE __thiscall
#else
#define CALLTYPE __stdcall
#endif

__RELIABILITY_CONTRACT
void CALEETYPE __ArrayUnwind(
	void*       ptr,                // Pointer to array to destruct
	size_t      size,               // Size of each element (including padding)
	int         count,              // Number of elements in the array
	void(CALLTYPE *pDtor)(void*)    // The destructor to call
	);

__RELIABILITY_CONTRACT
inline void CALEETYPE __ehvec_ctor(
	void*       ptr,                // Pointer to array to destruct
	size_t      size,               // Size of each element (including padding)
	//  int         count,              // Number of elements in the array
	size_t      count,              // Number of elements in the array
	void(CALLTYPE *pCtor)(void*),   // Constructor to call
	void(CALLTYPE *pDtor)(void*)    // Destructor to call should exception be thrown
	) {
	size_t i = 0;      // Count of elements constructed
	int success = 0;

	__try
	{
		// Construct the elements of the array
		for (; i < count; i++)
		{
			(*pCtor)(ptr);
			ptr = (char*)ptr + size;
		}
		success = 1;
	}
	__finally
	{
		if (!success)
			__ArrayUnwind(ptr, size, (int)i, pDtor);
	}
}

__RELIABILITY_CONTRACT
SECURITYCRITICAL_ATTRIBUTE
inline void CALEETYPE __ehvec_dtor(
	void*       ptr,                // Pointer to array to destruct
	size_t      size,               // Size of each element (including padding)
	//  int         count,              // Number of elements in the array
	size_t      count,              // Number of elements in the array
	void(CALLTYPE *pDtor)(void*)    // The destructor to call
	) {
	_Analysis_assume_(count > 0);

	int success = 0;

	// Advance pointer past end of array
	ptr = (char*)ptr + size*count;

	__try
	{
		// Destruct elements
        while (count-- > 0)
		{
			ptr = (char*)ptr - size;
			(*pDtor)(ptr);
		}
		success = 1;
	}
	__finally
	{
		if (!success)
			__ArrayUnwind(ptr, size, (int)count, pDtor);
	}
}

am Ende der stdafx.h ein. Sie sorgen dafür, dass der Linker die vom Compiler generierten Funktionen korrekt auflösen kann. Der Unterschied zwischen der VS 2013- und VS 2015-Version liegt hauptsächlich im Typ des dritten Parameters, der von int auf size_t geändert wurde.

In einem halben Jahr wird sich wohl zeigen, wie die Verteilung der Universal CRT auf älteren Windows-Systemen vorangeschritten ist. Von den mit VS 2015 angekündigten Leistungsverbesserungen beim Erstellen von Projekten habe ich bisher noch nicht viel gemerkt, vermutlich sind meine Projekte dafür auch zu klein. Die neue CodeLens-Funktion für C++ arbeitet leider nur mit Git-Repositories und nicht mit der TFS-eigenen Versionsverwaltung. Mal schauen, ob Microsoft hier noch nachlegt. Bis dahin werde ich wohl erst einmal beim bewährten Visual Studio 2013 bleiben.

Pfadnamen bei Projekterstellung

By Sven on 27.04.2015 - 10:45 in Visual Studio 2013 with 2 Kommentare

Viele Entwickler bevorzugen für die Ausgabe von kompilierten Dateien ihre eigene Verzeichnisstruktur. Ich selbst habe jahrelang in jedem Projektordner ein Verzeichnis objs verwendet, welches noch einmal jeweils einen Unterordner für jede Konfiguration (Debug, Release, …) enthielt. Zum Löschen aller Ausgabedateien reichte in FileSearch eine Suche nach objs mit dem anschließendem Löschen aller gefundenen Ordner.

Mit dem Umstieg auf dem Mac musste ich mich aber von diesem System verabschieden. Der Grund war die stündliche automatische Sicherung mit TimeMachine. Die Ausgabedateien belegen pro Entwicklungszweig insgesamt bis zu 10 GB und ändern sich mit jedem Compilerlauf. Eine stündliche Sicherung würde auf dem Backupmedium schnell einen Engpass erzeugen. Man kann zwar Verzeichnisse von der Sicherung ausnehmen, muss diese aber genau benennen. Bei knapp 50 objs-Ordnern pro Entwicklungszweig ist das aber eher eine mühselige und fehlerträchtige Aufgabe.

Die Lösung war ein gemeinsamer Basisordner für die Ausgabedateien jedes Entwicklungszweigs auf dessen oberster Ebene. Die Ausgabe- und Zwischenverzeichnisse für jedes Projekt änderten sich so von

objs\Release_x64

auf

..\..\!IntDir\SpeedCommander\$(ProjectName)\Release_x64\

Anschließend mussten in der TimeMachine nur noch zwei !IntDir-Verzeichnisse für die Dev/Main-Entwicklungszweige als Ausnahme eingetragen werden.

Ein eher unschöner Nebeneffekt waren allerdings die relativen Bezüge in den Pfadnamen für die Ausgabedateien im Ausgabefenster. Statt

2>     Bibliothek "objs\Release_x64\CxLib72.lib" und Objekt "objs\Release_x64\CxLib72.exp" werden erstellt.
2>  CxLibrary.vcxproj -> D:\Visual C++\Dev\Libraries\CxLibrary\objs\Release_x64\CxLib72.dll
...
3>  sqc.vcxproj -> D:\Visual C++\Dev\SpeedCommander\sqc\objs\Release_x64\sqc.exe
3>  Done Adding Additional Store
3>  Successfully signed: D:\Visual C++\Dev\SpeedCommander\sqc\objs\Release_x64\sqc.exe

wurde im Ausgabefenster nun

2>     Bibliothek "..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.lib" und Objekt "..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.exp" werden erstellt.
2>  CxLibrary.vcxproj -> D:\Visual C++\Dev\Libraries\CxLibrary\..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.dll
...
3>  sqc.vcxproj -> D:\Visual C++\Dev\SpeedCommander\sqc\..\..\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe
3>  Done Adding Additional Store
3>  Successfully signed: D:\Visual C++\Dev\SpeedCommander\sqc\..\..\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe

angezeigt. Aber auch nach knapp sechs Monaten konnte ich mich an diese Darstellung nicht so recht gewöhnen.

Auf der Suche nach einer Lösung bin ich auf diese Seite gestoßen, auf der die Funktion $([System.IO.Path]::GetFullPath(”)) genannt wird. In den Tiefen der MSBuild-Umgebung habe ich dann die Datei Microsoft.cpp.targets gefunden, in der die Werte für Ausgabe- und Zwischenverzeichnis validiert werden. Gleich nach der Prüfung auf den abschließenden Backslash habe ich in Zeile 34 die folgenden Zeilen eingefügt:

  <PropertyGroup>
    <IntDir Condition="!$([System.IO.Path]::IsPathRooted('$(IntDir)'))">$([System.IO.Path]::GetFullPath('$(ProjectDir)$(IntDir)'))</IntDir>
    <OutDir Condition="!$([System.IO.Path]::IsPathRooted('$(OutDir)'))">$([System.IO.Path]::GetFullPath('$(ProjectDir)$(OutDir)'))</OutDir>
    <OutputPath>$(OutDir)</OutputPath>
  </PropertyGroup>

Diese sorgen dafür, dass die aus dem Projektverzeichnis und den dazu relativen Ausgabe- und Zwischenverzeichnissen zusammengesetzten Pfade keine überflüssigen Verweise mehr enthalten.

Beim nächsten Durchlauf war die Anzeige im Ausgabefenster nun bedeutend freundlicher:

2>     Bibliothek "D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.lib" und Objekt "D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.exp" werden erstellt.
2>  CxLibrary.vcxproj -> D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.dll
...
3>  sqc.vcxproj -> D:\Visual C++\Dev\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe
3>  Done Adding Additional Store
3>  Successfully signed: D:\Visual C++\Dev\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe

Erwähnenswert ist vielleicht noch, dass die Funktion $([System.IO.Path]::GetFullPath(”)) auch in den Befehlszeilen für Buildereignisse verwendet werden kann. Zudem sollte man damit rechnen, dass die Änderungen in Microsoft.cpp.targets beim nächsten VS-Update überschrieben werden können und dann neu durchgeführt werden müssen.

Nachtrag vom 11.05.2015

In der Zwischenzeit hat sich gezeigt, dass das Voranstellen des Projektpfades negative Auswirkungen auf das Neuladen von Projektdateien (z.B. nach dem Zurücknehmen von Änderungen) hat. Ich habe die beiden Zeilen nun so geändert, dass das Projektverzeichnis nur vorangestellt wird, wenn der Pfadname von In/OutDir relativ und nicht absolut ist.

Agile Prozessvorlage im TFS von 4.2 auf 2013 aktualisieren

By Sven on 10.12.2013 - 16:40 in TFS, Visual Studio 2013 with Keine Kommentare

Wenn man nach der Aktualisierung des Team Foundation Servers (TFS) auch die neuen Funktionen verwenden möchte, dann kommt man nicht umhin, die in den Teamprojekten verwendete Prozessvorlage zu aktualisieren. Ohne eigenes Zutun verbleibt diese nämlich in der Version, die bei der Projekterstellung aktuell war. Bei mir war das die Version 4.2 vom TFS 2008.

Von Microsoft gibt es dafür auch eine ausführliche Anleitung. Allerdings bezieht sich der erste Schritt zum Umbenennen der Systemfelder auf die englische Prozessvorlage. Die Anweisungen für die in der deutschen Version verwendeten Prozessvorlage lauten daher:

witadmin changefield /collection:CollectionURL /n:System.HyperLinkCount /name:"Anzahl von Hyperlinks"
witadmin changefield /collection:CollectionURL /n:System.ExternalLinkCount /name:"Anzahl externer Links"
witadmin changefield /collection:CollectionURL /n:System.RelatedLinkCount /name:"Anzahl zugehöriger Links"
witadmin changefield /collection:CollectionURL /n:System.AttachedFileCount /name:"Anzahl angefügter Dateien"

Die restliche Anleitung ab Schritt 2 kann dann wie beschrieben abgearbeitet werden. Nach der Aktualisierung sollte noch der Cache zurückgesetzt werden:

witadmin rebuildcache /collection:CollectionURL

Und nicht vergessen: Vor solchen Änderungen immer eine Sicherung der Datenbanken erstellen.

Umstieg 2: Visual Studio 2013

By Sven on 15.11.2013 - 15:55 in Visual Studio 2013 with 4 Kommentare

Seit mehr als sechs Jahren nutze ich nun Visual Studio 2008. Compiler- und bibliothekstechnisch war ich trotzdem auf dem aktuellen Stand, da sich die neuen Versionen relativ problemlos in die alte IDE einbinden lassen. Den Team Foundation Server (TFS) läuft schon in der 2010er-Version, aufgrund der Einbindung in die 2008er-IDE arbeitet man aber quasi auf dem 2008er-Niveau.

Die Entwicklung lief also quasi auf fest eingetrampelten Pfaden, was natürlich auch eine gewisse Stabilität verspricht. Trotzdem kam in den letzten Wochen der Wunsch nach etwas Veränderung auf. Also habe ich mir das nagelneue Visual Studio 2013 einmal etwas genauer angeschaut und getestet, ob ein Umstieg in Frage kommt.

Bei der wichtigsten Erweiterung Visual Assist waren keine Probleme zu erwarten. Auf meine EasyTabs muss ich natürlich verzichten, aber das Tabs Studio ist ein guter Ersatz. Ziemlich erstaunt war ich, als ich meine Makros übertragen wollte. Die Makrofunktionen waren nicht mehr zu finden und nach einer Netzsuche wusste ich, dass es seit Visual Studio 2012 keine Makros mehr gibt. Abhilfe schafft hier die Visual Commander-Erweiterung vom Tabs Studio-Autor. Meine VB-Makros konnte ich nahezu 1:1 übernehmen. Ab und zu fehlte nur ein DTE. für den Zugriff auf das Automationsmodell.

Der erste Kompilierungsversuch scheiterte allerdings an einer Exception in Microsoft.Build.Utilities.FileTracker. Die Ursache fand ich recht schnell im Netz. Mein Temp-Verzeichnis zeigt auf eine RamDisk, und zwar direkt auf das Hauptverzeichnis. Das mag MSBuild wohl gar nicht. Nach der Verlagerung des Temp-Verzeichnisses in einen Unterordner auf der RamDisk war das Problem behoben.

Die Fehlermeldungen im Zusammenhang mit den Zieldateinamen waren zu erwarten, schließlich habe ich die Erfahrung ja schon beim Test von Visual Studio 2010 gemacht. Die damalige Abneigung gegen die Vergabe von Projektnamen in den Projekteinstellungen hat sich nun in Befürwortung geändert. Bei konsequenter Verwendung des Projektnamens in den Compiler-/Linkereinstellungen braucht man bei Versionsänderungen (z.b. von MxFtp71 auf MxFtp72) diesen nämlich nur noch einer einzigen Stelle ändern. Früher musste man dagegen noch sämtliche Ausgabedateien anpassen.

Bei den gemeinsamen Bibliotheken verwende ich als Ausgabeordner der .dll-Dateien ein gemeinsames Verzeichnis. Hier unterscheidet sich der Zielpfadname mit Absicht vom Ausgabeverzeichnis des Projekts, was MSBuild jedesmal mit einer Warnung quittiert. Ein Löschen der entsprechenden Zeile 1186 aus Microsoft.CppBuild.targets schafft Abhilfe.

Als ordnungsliebender Mensch hat mich das neu angelegte ipch-Verzeichnis in jedem Arbeitsbereichsordner gestört, in dem die Datenbank für die IntelliSense-Daten abgelegt wird. Im Einstellungsdialog lässt sich unter Text-Editor | C/C++ | Erweitert im Bereich Ausweichpfad ein alternativer Pfad hinterlegen. Der Ausweichpfad zeigt bei mir nun auf ein Unterverzeichnis im lokalen AppData-Bereich und die Arbeitsbereichsordner sind ipch-frei.

Etwas verwirrend finde ich, dass im Projektmappen-Fenster vor den Quellcode-Dateien nun auch kleine Pfeile angezeigt werden und man die Quellcode-Dateien wie Ordner aufklappen kann. Aktiviert man auf der oben erwähnten Einstellungsseite im Bereich Durchsuchen/Navigation die Option Datenbank deaktivieren, dann verschwinden die Pfeile. Allerdings wird dann nur noch eine leere Ressourcen-Ansicht angezeigt. Eine Ressourcen-Datei kann dann nur per Rechtsklick mit Öffnen mit und dem Ressourcen-Editor geöffnet werden. Bei einem Gegentest mit Visual Studio 2010 zeigte sich das gleiche Problem. Entweder hat sich hier ein Fehler durch mehrere Versionen geschlichen oder das ganze ist ‘by Design’.

Beim Erstellen der konvertierten Projekte gab es nur wenige Probleme. Die MFC enthält nun Makros für die Nachrichtenfunktionen WM_COPY  und WM_PASTE, damit konnte ich meine eigenen Makros für diese Funktionen löschen. Zudem wurden die Implementierungen für CWnd::OnDisplayChange und CWnd::OnPrintClient geändert. Hier muss man die Funktionen in den eigenen Klassen entsprechend anpassen. Das gilt aber nur, wenn die Projekte bereits auf dem VS 2012-Stand sind. Beim Konvertieren von älteren MFC-Versionen könnten auch mehr Korrekturen nötig sein.

Die Codeanalyse-Prüfungen im neuen Compiler wurden weiter aufgebohrt und es werden Sachen angemeckert, die der VS 2012-Compiler noch ohne Warnungen durchgewunken hat. Hier empfiehlt es sich, die Codeanalyse erst einmal temporär zu deaktivieren und die genaue Untersuchung auf einen späteren Zeitpunkt zu verschieben. Neu ist, dass die Regelsätze für die Codeanalyse nun auch angepasst werden können. Ob das in VS 2012 auch schon war, kann ich leider nicht sagen.

Von optischer Seite her macht Visual Studio 2013 einen sehr guten Eindruck. Die verwendeten Symbole sind zwar farblich sehr zurückhaltend, konzentrieren sich dadurch aber auf das Wesentliche. Besonders gut gefallen mir die synchronisierten Einstellungen über mehrere Rechner hinweg. Hier werden die Einstellungen für Darstellung, Tastenkürzel und Texteditor auf einem Microsoft-Server gespeichert und immer aktuell gehalten. Das erleichtert das Arbeiten an mehreren Rechnern enorm.

Sehr gelungen finde ich auch die Team Explorer-Ansicht innerhalb der IDE. Arbeitsaufgaben und ausstehende Änderungen sind immer im Blickfeld. Auch das Verknüpfen von Arbeitsaufgaben beim Einchecken geht ohne modale Dialoge sehr viel leichter von der Hand. Zu weiteren Erkundungen innerhalb der IDE bin ich noch nicht gekommen, aber ich freue mich schon darauf.

Etwas schade ist, dass der Remote Debugger nicht mehr auf Windows XP und Windows Vista läuft. Zu älteren Versionen des Remote Debuggers kann VS 2013 keine Verbindung mehr aufnehmen. Man kann zwar noch Anwendungen erstellen, die unter Windows XP laufen, diese aber nicht mehr auf Windows XP debuggen. Windows XP nähert sich also unaufhaltsam seinem Ende.

Visual Studio 2012 und SSE2

By Sven on 18.10.2013 - 15:40 in Visual Studio 2012 with 2 Kommentare

Nach der Veröffentlichung von SpeedCommander 14.50 im Februar dieses Jahres berichteten mir einige Anwender, dass das Installationsprogramm kurz vor dem Ende abstürzte und die Installation nicht richtig abgeschlossen wurde. Die Dateien wurden zwar kopiert, allerdings fehlten die Startmenü-Einträge und die einzelnen Anwendungen stürzten beim Aufruf ebenfalls ab. Betroffen waren nur XP-Anwender. Ich konnte das Problem aber nicht nachstellen, weder in einer VM noch auf diversen XP-Rechnern.

Ein Zusammenhang mit der Umstellung des Compilers von Visual Studio  2010 auf 2012 war naheliegend. Der finalen Version von Visual Studio 2012 fehlte zuerst die Unterstützung für XP. Nach einem Aufschrei der Entwickler wurde diese allerdings mit dem Update 1 wieder reaktiviert. Vielleicht war im Compiler ja durch diesen Umstand noch ein Fehler enthalten, der nur auf ganz wenigen Rechnern auftrat.

Da ich das Problem nicht nachstellen konnte, habe ich das Installationsprogramm mit MessageBox-Aufrufen zugepflastert und einer der betroffenen Anwender teilte mir dann immer mit, wie der letzte angezeigte Text lautete. So konnte ich mich Stück für Stück zur Absturzstelle tasten. Nun wusste ich zwar, wo der Absturz erfolgte. Aber nicht, warum.

Am Montag erhielt ich eine E-Mail von einem anderen betroffenen Anwender. Dieser hatte einen AMD-K6 in die Hände bekommen und damit ein paar Versuche angestellt. SpeedCommander ließ sich auf einem frischen XP nicht installieren, auch nicht auf einem Windows 7. Das brachte mich auf die Idee, meinen alten und schon längst in den Ruhestand verabschiedeten Dual Pentium III zu reaktivieren. Und siehe da, die Installationsprobleme traten hier auch auf.

Eine Erklärung dafür fand ich dann auf dieser Seite. Visual Studio 2012 erstellt nun standardmäßig Programme, die den SSE2-Befehlssatz verwenden. Wenn dies nicht gezielt durch den Kommandozeilenparameter /arch:IA32  deaktiviert wird, dann läuft das erstellte Programm nur noch auf Prozessoren mit SSE2-Befehlssatz. Neben dem Pentium III gehören auch Athlon XP/Duron/Sempron für den Sockel A zu den damit ausgeschlossenen Prozessoren.

Die Entscheidung von Microsoft, mit Visual Studio 2012 den Schalter für die Erstellung von SSE2-Code standardmäßig zu aktivieren, kann ich nicht nachvollziehen. Das kann auch nichts mit der temporär entfernten Unterstützung für Windows XP zu tun haben, denn selbst Windows 7 lässt sich noch auch Prozessoren ohne SSE2 installieren und verwenden. Man kann als Entwickler in Zukunft wohl nicht mehr darauf vertrauen, dass mit den gleichen Optionen erstellte Programme auch weiterhin auf allen vorher unterstützten Systemen laufen, wenn man den Compiler aktualisiert.

Ähnliches gilt übrigens auch für mit Visual Studio 2012 erstellte 64-bit Anwendungen. Unter Windows 8 beziehen sich Speicheradressen nun auf den gesamten 64-bit Adressraum. Allerdings gilt das nicht nur für die Anwendung selbst, sondern auch gleich für alle geladenen Dlls. Bei SpeedCommander schließt das sämtliche geladene Shellerweiterungen mit ein. Einige davon sind aber nicht darauf vorbereitet, dass die Adresszeiger plötzlich etwas größer als 2 GB sein können und stürzen dann bei Zeigeroperationen ab. Die Verwendung des gesamten Adressraums lässt sich durch den Linkerparameter /HIGHENTROPYVA:NO deaktivieren.

Für SpeedCommander 14 wird es in nächster Zeit noch ein kleines Update geben, das die Installation auf Prozessoren ohne SSE2-Unterstützung wieder ermöglicht. Bei SpeedCommander 15 kommt dies mit dem nächsten Update.

Top