Komfortabler Dateimanager mit vielen Funktionen

Visual Studio 2015

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.

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.

Top