seeseekey.net - Invictus Deus Ex Machina

Die Ent­wick­lung von Con­trols unter .NET und Win­dows Form geht eigent­lich rela­tiv leicht von der Hand. Kom­pli­ziert wird das ganze immer dann wenn Feh­ler auf­tre­ten. So las­sen sich Con­trols wel­che im Desi­gn­mo­dus Excep­ti­ons wer­fen, nur schwer debug­gen. Aber wie immer gilt, wo ein Wille ist, da ist auch ein Weg.

Das Attach to Pro­cess Fenster

Um ein Con­trol zu debug­gen, sollte man das ent­spre­chende Pro­jekt bzw. die Solu­tion zwei mal öff­nen. In dem einen Visual Stu­dio öff­net man nun den Desi­gner. Im ande­ren Visual Stu­dio wählt man im Debug­menü den Punkt „Attach to Pro­cess…“ aus. Das sich öff­nende Fens­ter zeigt alle Pro­zesse an, an wel­che sich der Debug­ger anhän­gen kann. Hier wird das erste Visual Stu­dio (das mit dem Desi­gner) aus­ge­wählt. Nun kann man im Quell­text des Con­trols Bre­ak­points set­zen und somit die Aus­füh­rung über­wa­chen. Aller­dings sollte man sich dabei nicht wun­dern, das dass Con­trol im Debug­ger grö­ßer erscheint als es eigent­lich ist. Der Grund dafür liegt darin, das genau genom­men nicht das Con­trol son­dern das gesamte Visual Stu­dio debuggt wird.

Manch­mal ist es nötig je nach Kon­fi­gu­ra­tion ein ande­res Assem­bly in ein .NET/Mono Pro­jekt ein­zu­bauen. Direkt im Visual Stu­dio funk­tio­niert das lei­der nicht. Aller­dings kann man die Ein­stel­lung mit einem Text­edi­tor in der Pro­jekt­da­tei vornehmen:

<Reference Include="libInterval" Condition="'$(Configuration)'=='Debug'">
  <HintPath>libInterval\x32-debug\libInterval.dll</HintPath>
</Reference>
<Reference Include="libInterval" Condition="'$(Configuration)'=='Release'">
  <HintPath>libInterval\x32-release\libInterval.dll</HintPath>
</Reference>

Wich­tig ist dabei der „Condition“-Teil wel­cher fest­legt das die eine DLL nur bei der jewei­li­gen Kon­fi­gu­ra­tion genutzt wird. Durch die­sen lan­det das rich­tige Assem­bly spä­ter im ent­spre­chen­den Buildordner.

Mit der Instal­la­tion einer Ver­sion des Visual Stu­dios lan­den eine Menge Tools auf dem Rech­ner des Benut­zers. Eines der Tools wel­che dabei lei­der nicht auf der Platte lan­det, ist der CLR Pro­fi­ler, wel­cher auch aus dem Hause Micro­soft stammt.

Eine Aus­wer­tung des CLR Profilers

Mit die­sem Tool kann die Inne­reien sei­ner .NET Soft­ware, wie die Spei­cher­brauch im Heap, die Hand­le­an­for­de­run­gen und ähn­li­ches ana­ly­sie­ren und aus­wer­ten. Her­un­ter­ge­la­den wer­den kann der CLR Pro­fi­ler unter http://www.microsoft.com/en-us/download/details.aspx?id=16273.

Wenn man sein Visual Stu­dio hin­ter eine Pro­xy­ser­ver betreibt, so kann es pas­sie­ren das die „Online Gal­lery“ nicht funk­tio­niert. Möchte man dies ändern so muss man je nach Visual Stu­dio, eine der fol­gen­den Dateien ändern:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe.config (Visual Studio 2010)
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe.config (Visual Studio 2012)

Die „Online Gal­lery“ ist offline

Dort fin­det man einen Block der in etwa so aus­se­hen sollte:

<system.net>
  <settings>
    <ipv6 enabled="true"/>
  </settings>
</system.net>

Dort fügt man den Tag:

<servicePointManager expect100Continue="false" />

inner­halb des „set­tings“ Tag hinzu. Nach einem Neu­start des Visual Stu­dios, sollte auch die „Online Gal­lery“ wie­der funktionieren.

Wenn man das Visual Stu­dio 2010 oder 2008 gewöhnt ist, so kommt der erste Start der 2012 Ver­sion des Stu­dios einem klei­nen Schock gleich. Die Ober­flä­che sehr kon­trast­arm und unge­wohnt. Auch das Menü wirkt mit sei­nen groß geschrie­be­nen Ein­trä­gen sehr gewöhnungsbedürftig.

Das Visual Stu­dio 2012 nach eini­gen „Tuning“-Maßnahmen

Das Pro­blem mit den Far­ben bekommt man rela­tiv schnell mit der Erwei­te­rung Visual Stu­dio 2012 Color Theme Edi­tor in den Griff. Diese bie­tet beim Neu­start des Visual Stu­dios die Mög­lich­keit das Farb­schema sei­nen Bedürf­nis­sen anzupassen.

Dem Menü kommt man nur durch einen beherz­ten Ein­griff in die Regis­try bei. Hierzu wird im Regis­try­baum zur Stelle:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\General

navi­giert und dort ein „DWORD“ mit dem Namen „Sup­p­res­sUp­per­ca­se­Con­ver­sion“ und dem Wert „1“ ange­legt. Nach einem Neu­start des Stu­dios ist dann auch das Menü wie­der normal.

Bei der Ent­wick­lung wun­dert man sich ab und an, was für inter­es­sante Pro­jekte in den Wei­ten des Net­zes so umher­schwir­ren. So unter ande­rem das Pro­jekt Script#. Dabei han­delt es sich um eine Erwei­te­rung für das Visual Stu­dio 2012 mit wel­cher es mög­lich ist C# Quell­text (so er gewis­sen Kri­te­rien genügt) in Java­Script umzu­wan­deln, bzw. zu compilieren.

Die Erwei­te­rung wel­che im Quell­text unter https://github.com/nikhilk/scriptsharp zu fin­den ist, steht dabei unter der Apa­che Lizenz und ist somit freie Soft­ware. Nach der Instal­la­tion fügt sie dem Visual Stu­dio neue Pro­jekt­ty­pen hinzu, mit wel­chen man anschlie­ßend arbei­ten kann. Lei­der gibt es von Script# keine Mono­De­ve­lop Vari­ante, so das man im Moment zwin­gend an das Visual Stu­dio gebun­den ist. Aller­dings fin­det sich in der Road­map fol­gen­der Satz:

In terms of code con­tri­bu­tion, it would be espe­cially inte­res­ting to see the deve­lop­ment of import libra­ries for com­mon libra­ries, so they are easily usa­ble right out of the box. It would also be inte­res­ting to see the deve­lop­ment of com­ple­men­tary tools/addins, adding sup­port to other IDEs (esp. Mono­De­ve­lop) and other such com­ple­men­tary pro­jects. Or you might be inte­res­ted in the very core, i.e. the com­pi­ler itself.

Also wenn sich jemand bemü­ßigt fühlt, das ganze für Mono­De­ve­lop in Angriff zu neh­men, der muss nun nicht mehr auf die Ein­la­dung war­ten. Die offi­zi­elle Pro­jekt­seite von Script# ist unter http://scriptsharp.com/ zu finden.

Test­ba­sierte Ent­wick­lung ist schon eine schöne Sache, vor allem bei grö­ße­ren Pro­jek­ten. Mit Hilfe soge­nann­ter Unit-Tests kann man dabei auto­ma­ti­siert über­prü­fen ob der zu tes­tende Soft­ware­teil noch immer die Ergeb­nisse lie­fert, die erwar­tet wer­den. Meist ist es so, dass man in grö­ße­ren Soft­ware­pro­jek­ten etwas ändert und damit impli­zit an ande­ren Stel­len Feh­ler ein­baut, wel­che ohne Unit-Tests gar nicht bzw. erst spä­ter auffallen.

Für die Ent­wick­lung unter .NET/Mono mit Hilfe des Visual Stu­dios habe ich mich dabei für NUnit ent­schie­den, da man die­ses im Gegen­satz zu MsTest auch unter Linux und Mac OS X nut­zen kann. Damit sich das ganze bequem in das Visual Stu­dio inte­griert nutze ich TestDriven.NET wel­ches unter http://www.testdriven.net/ bezo­gen wer­den kann. Der per­sön­li­che Gebrauch ist dabei kostenlos.

Nach der Instal­la­tion von TestDriven.NET kann man sein Visual Stu­dio star­ten und mit der test­ba­sier­ten Ent­wick­lung begin­nen. Dabei hat man zwei Mög­lich­kei­ten dies zu lösen. Die erste Mög­lich­keit ist es die Tests in ein extra Pro­jekt zu ver­la­gern so das diese nicht in der zu tes­ten­den Soft­ware vor­kom­men. Bei der zwei­ten Mög­lich­keit wer­den die Tests direkt im zu tes­ten­den Pro­jekt geschrie­ben (z.B. in einen Name­space „Tests“).

Als Bei­spiel sei fol­gende Klasse gegeben:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Project
{
	public class FooBar
	{
		public int A { get; private set; }
		public int B { get; private set; }
		public int C { get; private set; }

		public FooBar(int a, int b, int c)
		{
			A=a;
			B=b;
			C=c;
		}
	}
}

Die Klasse „Foo­Bar“ nimmt dabei im Kon­struk­tor die drei Varia­blen a, b und c ent­ge­gen und weist sie den jewei­li­gen Eigen­schaf­ten der Klasse zu. Um nun zu tes­ten ob diese Zuwei­sung funk­tio­niert schrei­ben wir eine ent­spre­chende Test-Unit. Dazu erstel­len wir eine Klasse namens: „FooBarTest.cs“:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace Project
{
	[TestFixture]
	public class FooBarTests
	{
		[Test]
		public void TestNewFooBar()
		{
			FooBar fooBar=new FooBar(13, 24, 47);

			Assert.AreEqual(13, fooBar.A);
			Assert.AreEqual(24, fooBar.B);
			Assert.AreEqual(47, fooBar.C);
		}
	}
}

Diese Test­klasse tes­tet nun ob die Werte die im Kon­struk­tor ange­ge­ben wer­den auch wirk­lich in den ent­spre­chen­den Eigen­schaf­ten lan­den. Dazu wird zuerst das NUnit Frame­work mittels:

using NUnit.Framework;

ein­ge­bun­den. Mit­tels des Attri­bu­tes „[Test­Fix­ture]“ sagen wir dem NUnit Frame­work das sich in die­ser Klasse Unit-Tests befin­den. Bei die­sem Attri­but gibt es einige Ein­schrän­kun­gen, so darf die Klasse z.B. nicht abs­trakt sein, nähe­res dazu erfährt man auch in der Doku­men­ta­tion.

Das Attri­but „[Test]“ über der Funk­tion „Test­Ne­w­Foo­Bar“ teilt dem Frame­work mit das es sich bei die­ser Funk­tion um einen Unit-Test han­delt, wel­cher über­prüft wer­den soll. Dazu legen wir in der Funk­tion eine Instanz von „Foo­Bar“ an und über­ge­ben die ent­spre­chen­den Werte an den Konstruktor.

Mit­tels der „Assert.AreEqual“ Funk­tion (wei­tere „Assert“ Funk­tio­nen fin­det man in der Doku­men­ta­tion) über­prü­fen wir ob die Werte auch bei den Eigen­schaf­ten A, B und C ange­kom­men sind. Wäre dies nicht der Fall so würde der Tests fehlschlagen.

Nach­dem ein Test für die ent­spre­chende Klasse geschrie­ben wurde, klickt man im Visual Stu­dio mit der rech­ten Maus­taste auf die Test­klasse und wählt dort „Run Test(s)“ aus. Möchte man meh­rere Tests lau­fen las­sen so muss einen über­ge­ord­ne­ten Ord­ner aus­wäh­len. Wenn alles rich­tig gemacht wurde, sollte man fol­gende Aus­gabe sehen:

------ Test started: Assembly: Project.exe ------

1 passed, 0 failed, 0 skipped, took 3,07 seconds (NUnit 2.6.0).

Falls ein Feh­ler auf­ge­tre­ten ist so sieht das ganze so aus:

------ Test started: Assembly: Project.exe ------

Test 'Project.FooBarTests.TestNewFooBar' failed: 
  Expected: 47
  But was:  0
	FooBarTests.cs(19,0): bei Project.FooBarTests.TestNewFooBar()

0 passed, 1 failed, 0 skipped, took 1,66 seconds (NUnit 2.6.0).

Fin­det man einen Feh­ler bei einem Test sollte man schauen wodurch die­ser ver­ur­sacht wird und ihn behe­ben. Wenn man nun bei der spä­te­ren Ent­wick­lung Feh­ler fin­det (und besei­tigt), wel­che durch kei­nen Tests abge­deckt sind, so sollte man gleich einen ent­spre­chen­den Test dafür schrei­ben, damit die­ser Feh­ler nicht ein wei­te­res Mal auf­tre­ten kann.

Wei­tere Infor­ma­tio­nen gibt es unter:
http://de.wikipedia.org/wiki/NUnit
http://de.wikipedia.org/wiki/XUnit

Seit März gibt es den freien (wie Frei­bier) Obfu­sca­tor Eazfuscator.NET in neuer Ver­sion. Neu an die­ser Ver­sion ist das sie beim obfus­kie­ren des Quell­codes nun auch Opti­mie­run­gen durch­führt, so das die Anwen­dung im Opti­mal­fall schnel­ler läuft.

Das Eazfuscator.NET Fenster

Bezo­gen wer­den kann die neue Ver­sion unter http://www.foss.kharkov.ua/g1/projects/eazfuscator/dotnet/Default.aspx.

Wei­tere Infor­ma­tio­nen gibt es unter:
http://seeseekey.net/blog/4255
http://eazfuscator.blogspot.de/2012/03/high-level-optimization-for-net.html

Eine Auto­ma­tik ist nur dann gut wenn man sie abschal­ten kann. So ist es auch manch­mal beim Visual Stu­dio mit der auto­ma­ti­schen Code­for­ma­tie­rung. So nehme man fol­gende Klasse:

public class Trash: ContextBoundObject
{
    public Trash() : base()
    {
       throw new NotImplementedException();
    }
}

Die auto­ma­ti­sche Code­for­ma­tie­rung mach dar­aus folgendes:

public class Trash: ContextBoundObject
{
    public Trash()
        : base()
    {
       throw new NotImplementedException();
    }
}

Das „base“ wird dabei ein­fach umge­bro­chen. Das Pro­blem ist das es (augen­schein­lich) keine Ein­stel­lung gibt um das ganze zu verhindern.

Der Visual Stu­dio Opti­ons Dialog

Und so muss man mit einer Auto­ma­tik leben, die man nicht deak­ti­vie­ren kann. Da sollte Micro­soft mal etwas nach­bes­sern oder mir ver­ra­ten wie es geht ;)

Wei­tere Infor­ma­tio­nen gibt es unter:
http://seeseekey.net/blog/2434
http://stackoverflow.com/questions/1023014/how-to-stop-visual-studio-from-auto-formatting-certain-parts-of-code

Manch­mal möchte man im Visual Stu­dio Excep­ti­ons fan­gen obwohl sie z.B. in einem „try catch“ Block lie­gen. Dies ist rela­tiv ein­fach mög­lich sobald man weiß an wel­cher Stelle man suchen muss. Im Menü „Debug“ gibt es den pas­sen­den Menüpunkt:

Wenn man dort den Punkt „Excep­ti­ons…“ auf­ruft bekommt man fol­gen­des Dia­log­fens­ter zu sehen:

In die­sem kann man dann alle Excep­ti­ons ange­ben wel­che zwangs­weise gefan­gen wer­den sollen.

Wei­tere Infor­ma­tio­nen gibt es unter:
http://de.wikipedia.org/wiki/Visual_Studio