Schlagwort: .NET

Diagramme mit C# erstellen 👍 👎

Häufig möchte man Statistiken grafisch aufbereitet darstellen. Mit diesem Beitrag möchte ich gerne zeigen, wie sich mit Hilfe einiger unter System.Web.UI.DataVisualization.Charting befindlichen Klassen sehr einfach dynamisch Diagramme erzeugen lassen. Der korrespondierende Namespace für klassische Anwendungen lautet System.Windows.Forms.DataVisualization.Charting.

Für unser Beispiel verwenden wir eine einfache Windows-Anwendung und folgende Datensammlung:
Daten (einige BMW-Modelle)
010203040506
Dictionary<string, double> data = new Dictionary<string, double>() {    {"125i", 160},    {"335i", 225},    {"550i", 330},    {"760i", 400}};
Die Schlüssel bezeichnen das jeweilige Modell und der entsprechende Wert die Leistung (in kW). Daraus erzeugen wir nun ein einfaches Balkendiagramm und speichern das Ergebnis als dia.png:
Diagramm erstellen und speichern
01020304050607080910111213141516171819202122232425262728293031323334353637
using(Chart chart = new Chart() {    Height = 345,    Width = 543}) {      // Konfiguration    chart.Titles.Add("BMW-Leistungsvergleich");
chart.ChartAreas.Add(new ChartArea("statistic") { AxisX = new Axis() { MajorGrid = new Grid() { Enabled = false } }, AxisY = new Axis() { MajorGrid = new Grid() { LineColor = Color.LightGray, LineDashStyle = ChartDashStyle.Dot }, Title = "kW" } });
chart.Series.Add(new Series("data") { ChartType = SeriesChartType.Column });
// Daten foreach(KeyValuePair<string, double> entry in data) { chart.Series["data"].Points.Add(new DataPoint() { AxisLabel = entry.Key, YValues = new double[] { entry.Value } }); }
// Ausgabe chart.SaveImage("dia.png", ChartImageFormat.Png);}
Als grundlegende Konfiguration wurde in diesem Beispiel das Gitternetz im Hintergrund zur Orientierung auf horizontale Linien beschränkt und durch Farbänderung und Punktierung etwas subtiler gestaltet. Außerdem wurden ein paar Beschriftungen ergänzt und ansonsten die Standardkonfiguration belassen.

Wichtig zu verstehen ist das Konzept, welches zuerst eine ChartArea als Grundfläche und anschließend Series für die eigentlichen Daten erfordert. Es können jeweils mehrere davon in einem Diagramm untergebracht werden.

Selbstverständlich sind umfassende Optionen vorgesehen, die das Endergebnis praktisch völlig anders erscheinen lassen können – bis hin zum eigentlichen Diagrammtyp. Details zu den jeweiligen Klassen finden sich im MSDN.

XML-Dokument mit LINQ to XML verarbeiten 👍 👎

Obwohl andere Formate wie beispielsweise JSON immer mehr Verbreitung gewinnen, bleibt es natürlich nötig, XML verarbeiten zu können – mit diesem Beitrag möchte ich zeigen, wie XML-Dokumente mit LINQ to XML besonders einfach verarbeitet werden können. LINQ selbst werde ich separat noch ausführlich behandeln.

Als Ausgangslage für unser Beispiel soll folgendes XML-Dokument dienen:
Persons.xml
010203040506070809101112131415161718
<personList>    <person id="1">        <firstName>Anders</firstName>        <lastName>Hejlsberg</lastName>    </person>    <person id="2">        <firstName>Bjarne</firstName>        <lastName>Stroustrup</lastName>    </person>    <person id="3">        <firstName>James</firstName>        <lastName>Gosling</lastName>    </person>    <person id="4">        <firstName>Rasmus</firstName>        <lastName>Lerdorf</lastName>    </person></personList>
Wir möchten daraus eine (generische) Liste von Person-Objekten erzeugen. Die Klasse soll auch gleich die Methode zur XML-Verarbeitung erhalten, welche mit LINQ to XML nun besonders einfach umzusetzen ist:
Person.cs
010203040506070809101112131415161718192021222324252627
public class Person {    public int PersonID {        get;        set;    }
public string FirstName { get; set; }
public string LastName { get; set; }

public static List<Person> ParseXML(string xml) { return XElement.Parse(xml) .Descendants("person") .Select(p => new Person() { PersonID = Int32.Parse(p.Attribute("id").Value), FirstName = p.Element("firstName").Value, LastName = p.Element("lastName").Value }).ToList(); }}
Das Vorgehen dürfte eigentlich weitestgehend selbsterklärend sein. Obwohl selbstverständlich mehr Funktionalität zur Verfügung steht, dürften mit diesem kleinen Beispiel bereits die wichtigsten Fälle abgedeckt sein. Weitere Informationen finden sich ausgehend von XDocument im MSDN.

Laufwerksschacht mit C# öffnen und schließen 👍 👎

In ein paar vorherigen Artikeln haben wir bereits externe Funktionalität per DllImport verwendet, was wir nun nochmals benötigen werden. Diesmal soll es darum gehen, den Laufwerksschacht zu öffnen und zu schließen.

Wir implementieren dazu folgende (sehr einfache) Klasse:
DiskTray.cs
010203040506070809101112131415161718
public static class DiskTray {    public static void Close() {        mciSendString("set CDAudio door closed", null, 0, IntPtr.Zero);    }
public static void Open() { mciSendString("set CDAudio door open", null, 0, IntPtr.Zero); }

[DllImport("winmm")] private static extern int mciSendString( string lpstrCommand, string lpstrReturnString, int uReturnLength, IntPtr hwndCallback );}
Die Verwendung – beispielsweise im Rahmen einer Fernwartung – gestaltet sich nun äußerst einfach:
Erweiterungsmethoden verwenden
0102
DiskTray.Open();   // öffnenDiskTray.Close();  // schließen
Für interessierte Leser finden sich im MSDN weiterführende Informationen zu mciSendString.

Wake on LAN per C# 👍 👎

Wake on LAN ist ein Standard zum Starten eines deaktivierten Rechners über eine kompatible Netzwerkkarte. Dazu wird lediglich ein bestimmtes Paket im Netzwerk gesendet; mit C# lässt sich das beispielsweise so lösen:
Klasse implementieren
0102030405060708091011121314151617181920212223242526272829
public static class WakeOnLAN {    public static void SendMagicPacket(byte[] macAddress) {        using(UdpClient udpClient = new UdpClient()) {            udpClient.Connect(IPAddress.Broadcast, 9);
byte[] magicPacket = new byte[(6 + (16 * 6))];
for(int i = 0; i < 6; i++) { magicPacket[i] = 0xFF; }
for(int i = 1; i <= 16; i++) { for(int j = 0; j < 6; j++) { magicPacket[((i * 6) + j)] = macAddress[j]; } }
udpClient.Send(magicPacket, magicPacket.Length); } }
public static void SendMagicPacket(string macAddress) { SendMagicPacket(macAddress .Split(':', '-') .Select(m => Byte.Parse(m, NumberStyles.AllowHexSpecifier)) .ToArray() ); }}
Das Paket enthält sechs mal den Wert FF16, gefolgt von der 16-maligen Wiederholung der MAC-Adresse und wird per Broadcast im Netzwerk versendet. Durch die Methodenüberladung wird die Übergabe der MAC-Adresse sowohl per Zeichenkette als auch per Byte-Feld ermöglicht:
Klasse verwenden
01020304050607
WakeOnLAN.SendMagicPacket("11:22:33:44:55:66");
/* – oder – */
WakeOnLAN.SendMagicPacket(new byte[] { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66});

Papierkorb mit C# leeren 👍 👎

Passend zum letzten Beitrag (Datei mit C# in Papierkorb verschieben) soll es noch einmal um den Papierkorb gehen. Um den Papierkorb zu leeren gibt es leider ebenfalls keine in verwaltetem Code zur Verfügung stehende Funktionalität des .NET-Frameworks für C#. Es ist also – wieder einmal – an der Zeit für DllImport.

Wir werden dazu eine Klasse RecycleBin mit integrierten RecycleFlags erstellen:
RecycleBin.cs
010203040506070809101112131415161718
public static class RecycleBin {    public static void Clear(RecycleFlags recycleFlags = RecycleFlags.None) {        SHEmptyRecycleBin(IntPtr.Zero, null, recycleFlags);    }

[DllImport("shell32")] private static extern uint SHEmptyRecycleBin( IntPtr hwnd, string pszRootPath, RecycleFlags dwFlags );
public enum RecycleFlags : uint { None = 0x0, // Standardverhalten NoConfirmation = 0x1, // keine Rückfrage zur Bestätigung NoProgressUI = 0x2, // keine Fortschrittsanzeige NoSound = 0x4 // kein Abschlussgeräusch }}
Die Verwendung gestaltet sich nun wieder gewohnt einfach:
Papierkorb leeren
0102030405
  // Papierkorb leeren (Standard)RecycleBin.Clear();
// Papierkorb ohne Rückfrage leerenRecycleBin.Clear(RecycleBin.RecycleFlags.NoConfirmation);
Im MSDN gibt es wie üblich weitere Details zu SHEmptyRecycleBin.

Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche