Sonntag, 28. November 2010

Prüfen ob Netzwerkverbindung besteht

Wir benutzen die Klasse System.Net.NetworkInformation.NetworkInterface um zu prüfen, ob der Computer eine Verbindung zu einem Netzwerk hat.
Die hierzu benötigte Methode heißt GetIsNetworkAvailable(). Sie prüft nur, ob der Computer sich über einen beliebigen Adapter in ein Netzwerk eingewählt halt, nicht, ob dieses auch funktioniert oder eine Verbindung zum Internet besteht.
Folgendes Codebeispiel prüft die Konnektivität:

bool NetworkAvailable = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

Donnerstag, 25. November 2010

Assertions

Assertions sind eine Methode zur Kontrolle der Programmkorrektheit.
Sie stellen eine Bedindung dar, die bei Verletzung eine Fehlermeldung ausgibt.
Assertions stehen meistens vor Programmbereichen, die ohne Erfülltsein der Bedingung nicht funktionieren würden. Wird eine Assertion geworfen, weiß der Programmierer, dass er in diesem Bereich den Fehler abzufangen hat.
Der Ausdruck System.Diagnostics.Debug.Assert() kann in der Debug - Konfiguration verwendet werden, System.Diagnostics.Trace.Assert() in der Release - Version.
Als Beispiel eine Methode zur Division, die beim Versuch, durch 0 zu teilen, mittels Assert() dazwischengeht:

public double divide(double divident, double divisor)
{
    System.Diagnostics.Debug.Assert(divisor != 0);
    return (divident / divisor);
}

Dienstag, 23. November 2010

String - Repräsentation einer Klasse durch Überladen von ToString()

Alle Klassen und Strukturen in C# erben implizit von der Überklasse Object.
Diese stellt einige grundlegende Methoden wie Equals() (prüft auf Gleichheit) und ToString() (stellt die Klasse als Zeichenkette dar) zur Verfügung.
Alle Klassen und Strukturen implementieren somit standardmäßig diese Methoden.
Jedem wird die Schreibweise Console.WriteLine(x.ToString()); bekannt sein, wobei x beispielsweise eine Integer - Variable ist. Auch diese Klasse besitzt die Methode ToString(), sie gibt den Wert der Ganzzahl als String aus.
Vom Programmierer angelegte Klassen erben auch von Object, haben also somit auch die Methode ToString() vordefiniert, hier liefert diese aber wahrscheinlich nicht das gewünschte Ergebnis.
Der Compiler druckt einfach den Typnamen der Klasse als Zeichenkette aus, woher sollte er auch wissen, wie der Programmierer eine Instanz der Klasse als Zeichenkette darstellen möchte.
Deswegen bietet es sich an, bei eigenen Klassen die Methode ToString() zu überschreiben. Beim Überschreiben (engl. overriding) von Methoden wird in der Kindsklasse eine Methode mit der gleichen Signatur (d.h. Name und Parameterliste gleich) wie eine Methode aus der Vaterklasse angelegt.
Wird nun die Methode der Kindsklasse aufgerufen, wird der Aufruf nicht mehr auf die Methode der Basisklasse weitergeleitet, sondern direkt in der Kindsklasse verarbeitet.
Das folgende Konsolenprogramm implementiert eine kleine Klasse Employee, in welcher die Methode ToString() überladen wird.
In der modifizierten Version werden Name und Gehalt des Mitarbeiters ausgegeben:

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

class Program
{
    static void Main(string[] args)
    {
        Employee TestEmployee = new Employee("Hans Meier", 1000);
        Console.WriteLine(TestEmployee.ToString());
    }
}

class Employee
{
    public string Name;
    public int Salary;

    public Employee(string name, int salary)
    {
        Name = name;
        Salary = salary;
    }

    public override string ToString()
    {
        return "Name: " + Name + ", Gehalt: " + Salary + ".";
    }
}

Sonntag, 21. November 2010

Ein Quine mit C#

Ein Quine ist ein Programm, welches seinen kompletten eigenen Quellcode als Ausgabe ausgibt.
Lautet der Quellcode also beispielsweise

class Quine
{
    static void Main()
    {
        System.Console.WriteLine("Dies ist (noch) kein Quine.");
    }
}

müsste das Programm genau diesen Text ausgeben.
Je nachdem, wie erfahren man mit Problemen aus diesem Bereich ist, wird einem die Aufgabe, ein Quine zu schreiben, vielleicht als einfach, schwer oder sogar unmöglich vorkommen.
(Für theoretisch interessierte: In allen "höheren" Programmiersprachen, also C, C#, Java etc. ist sogar garantiert, dass Quines existieren müssen. Denn all diese Sprachen sind Turing - vollständig, und in Turing - vollständigen Sprachen lässt sich ein Quine realisieren.)
Geht man ganz naiv an die Sache ran, könnte man vielleicht vermuten, das Problem wäre ganz schnell gelöst.
Man druckt zuerst den Code bis zur Zeile mit WriteLine(), dann diese Zeile und schließlich den Rest bis zur abschließenden Klammer.
Aber Moment! Die Aufgabenstellung besagt, dass der komplette Quellcode gedruckt werden soll, es müssen also auch alle WriteLine() Anweisungen gedruckt werden.
Schreibt man beispielsweise
string test = "abc";
und gibt diese Zeile dann mittels WriteLine() aus
WriteLine("string test = \"abc\";");
, muss im nächsten Schritt dann auch diese Zeile ausgedruckt werden.
Damit so keine Endlosrekursion entsteht, besteht der Trick darin, den auszugebenden Code in einem String zu speichern und dann nur diesen String auszugeben.
Weiterhin wird noch ausgenutzt, dass in C# in der WriteLine() - Methode Platzhalter benutzt werden können, welche dann später ersetzt werden.
Ich zeige jetzt einfach den Code eines von mir geschriebenen funktionierenden Quines, die abstrakten Forderungen von oben werden so vielleicht am besten deutlich:

class Quine
{
    static void Main(string[] args)
    {
        string s = "class Quine {3} {0} {3} static void Main(string[] args) {3} {0} {3} string s = {2}{1}{2}; {3} System.Console.WriteLine(s, System.Convert.ToChar(123), s, System.Convert.ToChar(34), System.Environment.NewLine, System.Convert.ToChar(125)); {3} {4} {3} {4}";
        System.Console.WriteLine(s, System.Convert.ToChar(123), s, System.Convert.ToChar(34), System.Environment.NewLine, System.Convert.ToChar(125));
    }
}

Samstag, 13. November 2010

In das Windows Ereignisprotokoll schreiben

Im Windows Ereignisprotokoll zeichnet Windows viele systemrelevante Informationen (z.B. das Starten / Beenden von Diensten, um nur eins von unzähligen Anwendungsgebieten zu nennen) auf.
Mit C# können wir in dieses Protokoll ganz leicht eigene Einträge über die Klasse System.Diagnostics.EventLog schreiben, um beispielsweise den Programmfluss zu überwachen.
Zuerst müssen wir hierfür (sofern noch nicht vorhanden) eine neue Quelle im Ereignisprotokoll anlegen.
Die Quelle gibt an, durch welche Anwendung etc. der Eintrag geschrieben wurde.
Gibt es noch keine Einträge von der Anwendung, wird die Quelle also neu angelegt, müssen wir spezifizieren, zu welcher Kategorie das Programm zählt. Im Ereignisprotokoll gibt es beispielsweise die Kategorien "Anwendung", "Sicherheit", "Installation" etc.
Das letztendliche Schreiben des Ereignisses führt die Methode WriteEntry() durch. Diese erwartet als 1. Parameter die Quelle, als 2. die Kategorie und optional als 3. den Typ des Ereignisses (z.B. Warnung, Information, Fehler ...).
Zum Schreiben in das Ereignisprotokoll wird das Programm wahrscheinlich (unter Windows Vista und 7) Administratorrechte benötigen, wie man die eigene Anwendung damit ausstattet könnt ihr hier lesen.
Das folgende Codebeispiel schreibt einen kurzen Informationstext in die Windows Ereignisanzeige (using System.Diagnostics; wird vorrausgesetzt):

        private void Form1_Load(object sender, EventArgs e)
        {
            string Source;
            string LogType;
            string LogEvent;

            Source = "Ereignisprotokoll C# Demo";
            LogType = "Application";
            LogEvent = "Diesen C# Blog finde ich super.";

            if (!EventLog.SourceExists(Source))
                EventLog.CreateEventSource(Source, LogType);

            EventLog.WriteEntry(Source, LogEvent, EventLogEntryType.Information);
        }

Montag, 8. November 2010

Herunterfahren von Windows verhindern / verzögern

Im vorigen Post wurde gezeigt, wie man erkennen kann, ob der PC heruntergefahren wird.
In diesem Post geht es darum, wie man das Herunterfahren abbricht bzw. verzögert um z.B. vorher Daten zu sichern.
Im vorigen Post wurde die Methode FormClosing() benutzt, in welcher beim Schließen des Formulars der Beendigungsgrund abgefragt wurde.
In dieser Methode können wir nun ebenfalls über den Parameter e das Herunterfahren einfach unterbinden, in dem wir e.Cancel = true setzen.
Das Herunterfahren des Rechners wird damit nicht vollständig abgebrochen, sondern nur solange verzögert, wie das Programm läuft - nun hat die Anwendung beispielsweise Zeit, ungesicherte Daten zu speichern.
In Windows Vista und 7 erscheint dabei ein Wartungsfenster mit dem Hinweis: "Folgendes Programm verhindert das Herunterfahren des Computers."

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.WindowsShutDown)
        e.Cancel = true;
}


Eine andere Möglichkeit, das Herunterfahren von Windows zu verzögern, besteht in der Verwendung des Microsoft.Win32.SystemEvents.SessionEnding Ereignisses, welches bei Herunterfahren des Systems eintritt.
Diesem Ereignis kann man wie anderen Ereignissen (z.B. Klick auf einen Button) eine Methode zuweisen, die aufgerufen wird, wenn es eintritt.
Folgender Codeausschnitt zeigt ein Beispiel unter Verwendung des Systemereignisses:

        private void Form1_Load(object sender, EventArgs e)
        {
            Microsoft.Win32.SystemEvents.SessionEnding += new Microsoft.Win32.SessionEndingEventHandler(this.WinShutdown);
        }

        private void WinShutdown(object sender, Microsoft.Win32.SessionEndingEventArgs e)
        {
            e.Cancel = true;
        }

Samstag, 6. November 2010

C# erkennen ob System heruntergefahren wird

Eine häufig durchgeführte Suchanfrage, bei welcher Surfer auf diesem Blog landeten, war die Frage, wie man feststellen kann, ob der PC gerade heruntergefahren wird.
Deswegen gibt es die Lösung jetzt hier als Post (warum siehe hier).
Wird das System heruntergefahren, werden logischerweise alle laufenden Prorgamme beendet. Das können wir ausnutzen, in dem wir in der Methode FormClosing() des Hauptformulars, welche aufgerufen wird, wenn das Formular geschlossen wird, den Grund des Schließens abfragen.
Dieser kann über die Eigenschaft CloseReason des Parameters e ermittelt werden.
Im Falle des Herunterfahrens lautet dieser Grund CloseReason.WindowsShutDown.
Der folgende Codeausschnitt aus einer Windows Forms-Anwendung implementiert diese Möglichkeit und gibt eine Meldung aus, wenn der PC heruntergefahren wird:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.WindowsShutDown)
        MessageBox.Show("PC wird heruntergefahren.");
}

Die Verwendung des Ereignisses Microsoft.Win32.SystemEvents.SessionEnding, welches nur eintritt wenn der PC heruntergefahren wird, wird im nächsten Post kurz erwähnt.

Freitag, 5. November 2010

C# .txt Datei bereits vorhanden

In einem vorigen Post wurde allgemein beschrieben, wie man prüfen kann, ob eine Datei / ein Ordner bereits vorhanden ist.
Im Rahmen der "Posts für häufige Suchbegriffe" zeige ich in diesem Post explizit den Code zum Prüfen, ob eine Textdatei bereits vorhanden ist.
Wer den Code nicht versteht sei auf den allgemeineren Post verwiesen, ich poste hier nur kurz die Lösung:

        private void Form1_Load(object sender, EventArgs e)
        {
            bool test = TxtFileExisting(@"C:\Users\User\Desktop\c#");
        }

        private bool TxtFileExisting(string path)
        {
            bool TxtDateiExistiert = System.IO.File.Exists(path + ".txt");
            return TxtDateiExistiert;
        }

Aus der Methode Form_Load() wird die Methode TxtFileExisting() mit dem Pfad zur prüfenden Datei (ohne Endung) aufgerufen.
In dieser Methode wird an den Pfad ".txt" angehängt und mittels System.IO.File.Exists() geprüft, ob die entsprechende Textdatei existiert. Falls ja, wird true zurückgegeben, andernfalls false.

Dienstag, 2. November 2010

C# Textdatei zufällige Zeile auslesen

In diesem Post möchte ich zeigen, wie man mit C# eine zufällige Zeile aus einer Textdatei liest.
(Diesen Post schreibe ich im Rahmen der Posts für häufige Suchbegriffe.)
Leider gibt es in C# keine direkte Möglichkeit, auf eine bestimmte Zeile einer Textdatei zuzugreifen.
Denn die Inhalte von Dateien werden als Folgen von Bits gespeichert, verschiedene Zeilen sind erst in einer höheren Abstraktionsebene sichtbar.
Um nun eine zufällige Zeile aus einer Textdatei auszulesen, lesen wir zuerst alle Zeilen ein und geben dann eine zufällige Zeile aus.
Das Auslesen der Textdatei erfolgt über die Klasse StreamReader, die Methode ReadToEnd() liest den kompletten Inhalt der Textdatei aus und gibt diesen als String zurück.
Diesen String kann man mit der Methode Split() aufteilen, als Trennzeichen übergeben wir Environment.NewLine.
Diese Konstante gibt das auf dem aktuellen System verwendete Trennsymbol für Zeilenumbrüche zurück.
Unter Windows ist dieses Symbol "\r\n", da dieses quasi aus 2 verschiedenen Symbolen besteht wird der String zuoft gesplittet, jede 2. Zeile ist leer und wir setzen die Option StringSplitOptions.RemoveEmptyEntries
um diese leeren Zeilen zu löschen.

Zur Erzeugung von Zufallszahlen, was zur Rückgabe einer zufälligen Zeile benötigt wird, habe ich diesen Post geschrieben.

Und nun der Code für eine fertige Funktion, welche den Pfad zu der zu lesenden Textdatei als Parameter entgegen nimmt und als Ergebnis eine zufällige Zeile der Textdatei als String zurückgibt (oben im Projekt muss die Anweisung using System.IO; eingebunden sein):

private string ReadRandomTextLine(string path)
{
    StreamReader sr = new StreamReader(new FileStream(path, FileMode.Open)); // StreamReader zum Lesen der Datei im Pfad path
    string[] Lines = sr.ReadToEnd().Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); // kompletten Inhalt der Datei auslesen und nach Zeilen splitten
    Random rnd = new Random(); // den Zufallsgenerator initialisieren
    return Lines[rnd.Next(Lines.Length)]; // eine zufällige Zeile zurückgeben
}

Posts für häufige Suchbegriffe

Ich benutze Google Analytics zur Analyse des Besucherverhaltens dieses Blogs. Mit Analytics kann man u.a. sehen, wie oft die eigene Seite für welche Suchbegriffe in den Ergebnisseiten von Suchmaschinen auftaucht und wie oft sie angeklickt wird.
In diesen Statistiken finden sich einige interessante Begriffe betreffend C# Fragen, die häufig gesucht werden. In den nächsten Tagen werde ich Posts zu genau den gesuchten Themen veröffentlichen. Erfahrenen C# Nutzern werden sie vielleicht komisch oder überflüssig vorkommen, aber ich hoffe, einige Programmierer finden genau die Lösung ihres Problems und ich erhalte nebenbei noch den ein oder anderen Besucher ;-)

Liste der Posts aus dieser Reihe:
C# Textdatei zufällige Zeile auslesen
CSharp txt Datei bereits vorhanden