Suche: AD

Syslog-Nachrichten mit C# versenden 👍 👎

Syslog beschreibt einen Protokollierungsstandard. Dieser Beitrag soll die beispielhafte Implementierung eines C#-Clients aufzeigen. Dazu werden UDP-basierte Nachrichten im (älteren) BSD-Format nach RFC 3164 erzeugt.

In einem früheren Beitrag hatte ich bereits mein NAS von Synology erwähnt. Sofern ihr ebenfalls ein solches besitzt, könnt ihr dieses sehr einfach als Server einrichten und somit direkt für die Beispiele (und mehr) nutzen.
Syslog-Klasse implementieren
010203040506070809101112131415161718192021222324252627282930313233343536
public class Syslog : IDisposable {    private const int Facility = 1;  // user-level messages    private const int FacilityFactor = 8;
private readonly UdpClient udpClient;

public Syslog(string hostname = "localhost", int port = 514) { this.udpClient = new UdpClient(hostname, port); }
public void Send(Severity severity, string message, [CallerMemberName] string caller = null) { byte[] data = Encoding.UTF8.GetBytes(String.Format("<{0}>{1} {2} {3}", ((Syslog.Facility * Syslog.FacilityFactor) + (int) severity), DateTime.Now.ToString("MMM dd HH:mm:ss"), Dns.GetHostName(), ((!String.IsNullOrWhiteSpace(caller)) ? (caller + " ") : (String.Empty)) + message ));
this.udpClient.Send(data, data.Length); }
public void Dispose() => this.udpClient?.Dispose();

public enum Severity { Emergency, // [0] system is unusable Alert, // [1] action must be taken immediately Critical, // [2] critical conditions Error, // [3] error conditions Warning, // [4] warning conditions Notice, // [5] normal but significant condition Informational, // [6] informational messages Debug, // [7] debug-level messages } // https://tools.ietf.org/html/rfc3164}
Es handelt sich hierbei – wie üblich – um eine minimale Implementierung ohne Fehlerbehandlung, welche außerdem keine Konfiguration des Facility-Wertes ermöglicht. Die Verwendung gestaltet sich nun jedoch sehr einfach:
Syslog-Klasse verwenden
01020304
using(Syslog syslog = new Syslog("syslog.example.net")) {    syslog.Send(Severity.Notice, "Dies ist eine weniger interessante Meldung.");    syslog.Send(Severity.Warning, "Dies ist eine sehr interessante Meldung.", "MyApp");}

Quartal mit C# ermitteln 👍 👎

Leider bietet die DateTime-Struktur standardmäßig keine eingebaute Funktionalität zur Ermittlung des Quartals einer Instanz. Wir werden diese daher als praktische Erweiterungsmethode ergänzen:
Erweiterungsmethode implementieren
0102030405
public static class DateTimeExtensions {    public static int GetQuarter(this DateTime dateTime) {        return ((dateTime.Month + 2) / 3);    }}
Durch die vorherige Addition von 2 wird die (ganzzahlige) Teilbarkeit bei richtigem Ergebnis sichergestellt. Indem die Teilung variabel gestaltet wird, beispielsweise mit Hilfe eines zu übergebenden Aufzählungswertes mit passenden ganzzahligen Werten, können auch andere Jahresteile (z. B. Halbjahre) sehr einfach ermittelt werden:
Erweiterungsmethode implementieren (erweitert)
010203040506070809101112
public static class DateTimeExtensions {    public static int GetYearDivisionPart(this DateTime dateTime, YearDivision yearDivision) {        int monthsPerDivision = (int) yearDivision;
return ((dateTime.Month + (monthsPerDivision – 1)) / monthsPerDivision); }
public enum YearDivision { Half = 6, Quarter = (Half / 2) }}
Die Verwendung gestaltet sich in beiden Fällen naheliegend einfach:
Erweiterungsmethode verwenden
0102030405
DateTime birthday = new DateTime(1988, 1, 29);
int quarter = birthday.GetQuarter(); // 1 /* bzw. */quarter = birthday.GetYearDivisionPart(YearDivision.Quarter); // 1

CSV- zu XML-Dateien konvertieren 👍 👎

Ein bestehendes Projekt von mir beinhaltet eine erweiterbare Dateiverwaltung. Die Anforderung war es nun, CSV-Dateien zu XML-Dateien zu konvertieren. Die Ausgangsdateien haben folgenden einheitlichen Aufbau:
CSV-Dateiformat (→ test.csv)
010203
spalte1,spalte2,spalte3inhaltA,inhaltB,inhaltCinhaltD,inhaltE,inhaltF
Zwar ist dieser konkrete Kontext sicherlich etwas speziell, jedoch möchte ich die allgemein verwendbare Kernfunktionalität kurz vorstellen. Ihr könnt euch im Folgenden also auf die Methode ConvertFiles konzentrieren:
Konvertierung implementieren
010203040506070809101112131415161718192021222324252627282930313233
public static class CsvToXml {    public static void ConvertDirectory(string path, SearchOption searchOption) {        CsvToXml.ConvertFiles(Directory.EnumerateFiles(path, "*.csv", searchOption));    }
public static void ConvertFiles(params string[] pathList) { foreach(string path in pathList) { using(StreamReader fileStream = File.OpenText(path)) { string currentLine = fileStream.ReadLine(); string[] fieldList = currentLine.Split(',');
XElement root = new XElement("entries"); XDocument document = new XDocument(root);
while((currentLine = fileStream.ReadLine()) != null) { string[] dataList = currentLine.Split(',');
XElement entry = new XElement("entry"); root.Add(entry);
for(int i = 0; i < dataList.Length; i++) { entry.Add(new XElement(fieldList[i], dataList[i])); } }
document.Save(Path.Combine( Path.GetDirectoryName(path), String.Concat(Path.GetFileNameWithoutExtension(path), ".xml") )); } } }}
Ich habe die beispielhafte Implementierung bereits etwas vereinfacht und wie üblich um Fehlerbehandlungen etc. reduziert, um den Fokus auf die eigentliche Funktionalität zu legen. Die Verwendung gestaltet sich nun sehr einfach:
Konvertierung anwenden
01
CsvToXml.ConvertDirectory(@"X:\data", SearchOption.TopDirectoryOnly);
Die zu Beginn beschriebene Beispiel-Datei würde nun zu folgender Datei konvertiert:
XML-Dateiformat (→ test.xml)
01020304050607080910111213
<?xml version="1.0" encoding="utf-8"?><entries>  <entry>    <spalte1>inhaltA</spalte1>    <spalte2>inhaltB</spalte2>    <spalte3>inhaltC</spalte3>  </entry>  <entry>    <spalte1>inhaltD</spalte1>    <spalte2>inhaltE</spalte2>    <spalte3>inhaltF</spalte3>  </entry></entries>
Natürlich kann diese grundlegende Funktionalität beliebig erweitert werden, beispielsweise für weitere Dateiendungen oder um die Bezeichner der äußeren Elemente (entries und entry) individuell angeben zu können. Je nach gewünschtem Einsatzzweck kann insbesondere auch die SearchOption-Aufzählung interessant sein.

Melodien mit Systemtönen in C# 👍 👎

Im letzten Beitrag hatte ich Systemtöne mit C# vorgestellt. Der Übersicht wegen – und nicht ganz ernstzunehmen – möchte ich mit diesem separaten Beitrag noch ein paar Beispiele zur Umsetzung einfacher Melodien zeigen.

Dazu implementieren wir zuerst eine kleine Hilfsklasse mit einigen vordefinierten Werten:
Klasse zur Arbeit mit der Tonart C-Dur
01020304050607080910111213141516171819
public static class BeepMusic {    private static readonly Dictionary<char, int> frequencyCollection = new Dictionary<char, int>() {        ['C'] = 264, ['D'] = 297, ['E'] = 330, ['F'] = 352,        ['G'] = 396, ['A'] = 440, ['H'] = 495, ['c'] = 528    };
public static void PlayNotes(Duration duration, string noteList) { foreach(char note in noteList) { Console.Beep(frequencyCollection[note], (int) duration); } }
public enum Duration { Whole = 1600, Half = (Whole / 2), Quarter = (Half / 2), Quaver = (Quarter / 2) }}
Nun können wir diese Klasse statisch importieren und (sehr) einfache Melodien erzeugen:
Melodien
01020304050607080910111213141516171819202122232425262728293031323334353637383940
using static BeepMusic;
// TonleiterPlayNotes(Duration.Quarter, "CDEFGAHc");
// Alle meine EntchenPlayNotes(Duration.Quaver, "CDEF");PlayNotes(Duration.Quarter, "GG");PlayNotes(Duration.Quaver, "AAAA");PlayNotes(Duration.Half, "G");PlayNotes(Duration.Quaver, "AAAA");PlayNotes(Duration.Half, "G");PlayNotes(Duration.Quaver, "FFFF");PlayNotes(Duration.Quarter, "EE");PlayNotes(Duration.Quaver, "GGGG");PlayNotes(Duration.Half, "C");
// Hänschen KleinPlayNotes(Duration.Quarter, "GE");PlayNotes(Duration.Half, "E");PlayNotes(Duration.Quarter, "FD");PlayNotes(Duration.Half, "D");PlayNotes(Duration.Quarter, "CDEFGG");PlayNotes(Duration.Half, "G");PlayNotes(Duration.Quarter, "GE");PlayNotes(Duration.Half, "E");PlayNotes(Duration.Quarter, "FD");PlayNotes(Duration.Half, "D");PlayNotes(Duration.Quarter, "CEGG");PlayNotes(Duration.Whole, "C");PlayNotes(Duration.Quarter, "DDDDDE");PlayNotes(Duration.Half, "F");PlayNotes(Duration.Quarter, "EEEEEF");PlayNotes(Duration.Half, "G");PlayNotes(Duration.Quarter, "GE");PlayNotes(Duration.Half, "E");PlayNotes(Duration.Quarter, "FD");PlayNotes(Duration.Half, "D");PlayNotes(Duration.Quarter, "CEGG");PlayNotes(Duration.Whole, "C");
Interessante Effekte ergeben sich darüber hinaus bei (pseudo-)zufälligen Tonfolgen. In einem späteren Beitrag möchte ich gerne aufzeigen, wie man auch etwas ernsthafter mit diesem Thema in C# umgehen kann.

Systemtöne mit C# ausgeben 👍 👎

Eine häufige Frage ist das Ausgeben von Systemtönen mit C#. Da sich dieses Blog explizit nicht nur an Experten richten soll, möchte ich natürlich gerne auch dazu erst einmal ein paar Beispiele auflisten:
Systemtöne ausgeben
01020304050607080910
// Systemton per Steuerzeichen/KonsoleConsole.Write('\a');Console.Beep();
// Systemtöne per MethodenaufrufSystemSounds.Asterisk.Play();SystemSounds.Beep.Play();SystemSounds.Exclamation.Play();SystemSounds.Hand.Play();SystemSounds.Question.Play();
Etwas interessanter ist die Überladung von Console.Beep(…), welche nicht nur in der Lage ist, den Standardton (800 Hz, 200 ms) auszugeben, sondern darüber hinaus dessen Konfiguration in Tonhöhe und -länge ermöglicht:
Benutzerdefinierten Ton ausgeben
0102
// 2350 Hz-Ton für 650 ms abspielenConsole.Beep(2350, 650);

Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche