Rash thoughts about .NET, C#, F# and Dynamics NAV.


"Every solution will only lead to new problems."

Category C#

In dieser Kategorie geht es um aktuelle Themen bzw. Code-Beispiele zur objektorientierten Programmiersprache C#.

Saturday, 4. November 2006


Eine überwachte Kopierfabrik (4)

Filed under: C#,Tools — Steffen Forkmann at 11:00 Uhr

Im vierten Teil meiner kleinen Serie zur überwachten Kopierfabrik, soll es nun darum gehen den Kopiervorgang in einen anderen Thread auszulagern. Das Problem ist nämlich, dass der lang anhaltende Kopiervorgang sonst das Erkennen weiterer Dateisystem-Ereignisse verhindert und der Dienst für die Zeit des Kopierens “eingefroren” ist. Um nun den Kopiervorgang “parallel” zu starten, kann man in C# 2.0 den sogenannten BackgroundWorker benutzen. Dieser bietet auf ganz einfache Weise die Möglichkeit ein lang andauernden Vorgang in einen Hintergrundthread zu verlagern und über Events sogar Fortschrittsmeldungen nach Außen zu geben. Im speziellen Fall des Kopierens könnte man also einfach von BackgroundWorker ableiten:

using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.IO; using System.Diagnostics; namespace DBCopyService { /// <summary> /// This BackgroundWorker copies the file async /// from source to target /// </summary> public class BackgroundCopyWorker : BackgroundWorker { private string sourceFile; private string targetFile; public BackgroundCopyWorker (string sourceFile, string targetFile) : base() { this.sourceFile = sourceFile; this.targetFile = targetFile; DoWork += new DoWorkEventHandler(bcw_DoWork); RunWorkerCompleted += new RunWorkerCompletedEventHandler (bcw_RunWorkerCompleted); RunWorkerAsync(); // Start new Thread } void bcw_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e) { Trace.WriteLine(string.Format("{0} copied to {1}", sourceFile, targetFileName)); } void bcw_DoWork(object sender, DoWorkEventArgs e) { try { Trace.WriteLine(string.Format("Copy {0} to {1}", sourceFile, targetFile)); FileInfo SourceFile = new FileInfo(sourceFile); FileInfo TargetFile = new FileInfo(targetFile); SourceFile.CopyTo(TargetFile.FullName, true); } catch (Exception ex) { Trace.TraceError(ex.Message); } } } }

Das Starten eines asyncronen Kopiervorgangs erfolgt dann ganz einfach über:

new BackgroundCopyWorker(originalFileName, targetFileName);

Friday, 27. October 2006


Eine überwachte Kopierfabrik (3)

Filed under: C#,Tools — Steffen Forkmann at 15:50 Uhr

Nachdem ich nun schon 2 kleinere Artikel zur überwachten Kopierfabrik geschrieben habe (Teil 1 und Teil 2), folgt nun der dritten Teil. Heute soll kurz gezeigt werden wie man mit C# ein Eingangsverzeichnis überwachen kann und dann bei Änderungen per Mail informiert wird.

using System.Net.Mail; ... fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Created); ... void fileSystemWatcher_Created(object sender, FileSystemEventArgs e) { MailMessage mailMessage = new MailMessage(from,to); mailMessage.Subject = string.Format("EntranceWatcher: {0}",e.FullPath); mailMessage.Body = string.Format( "Die Datei {0} wurde eben in ein Eingangsverzeichnis kopiert.", e.FullPath); SmtpClient smtpClient = new SmtpClient(smtpServer); smtpClient.Send(mailMessage); }

Saturday, 21. October 2006


Eine überwachte Kopierfabrik (2)

Filed under: C#,Tools — Steffen Forkmann at 17:36 Uhr

Gestern habe ich über ein kleines Tool berichtet, dass wiederkehrende langwierige Kopierfunktionen für den Nutzer versteckt in den Hintergrund verlagert und so einen ganz deutlichen Performancegewinn darstellt.

Um das Tool auf dem Server effektiv nutzen zu können wird es natürlich als Windows Dienst ausgeliefert. Wie man aus seinem Projekt einen solchen Dienst macht, wird ganz ausführlich in einer Exemplarischen Vorgehensweise auf MSDN demonstriert.

Mit folgendem Code-Schnipsel kann man sogar das Tracing des Dienstes gleich auf das EventLog umleiten:

using System.Diagnostics; ... EventLogTraceListener eventlogListener = new EventLogTraceListener("DBCopyService"); Trace.Listeners.Add(eventlogListener); Trace.WriteLine("Tracing auf EvenLog");

Tracing in die Ereignisanzeige

Friday, 20. October 2006


Eine überwachte Kopierfabrik

Filed under: C#,Tools — Steffen Forkmann at 20:20 Uhr

Bei uns in der Firma haben wir das Problem, dass wir für Entwicklungstests oft große Navision-Datenbanken aus einem Original-Verzeichnis in unsere Testverzeichnisse auf dem Testserver kopieren müssen. Dies hat bisher immer sehr viel Zeit (bis zu 30min pro DB) in Anspruch genommen – Zeit in der man nur unproduktiv auf das Ende des Kopiervorgangs warten konnte. Mit Hilfe eines kleinen Tricks kann man diese Zeit jedoch für den Nutzer fast komplett auf Null reduzieren.

Wir haben jetzt folgende Verzeichnisstruktur (alles auf dem selben Server)

  • Original (hier liegen die Ausgangsdatenbanken)
  • Lager (dies ist ein überwachtes Zwischenverzeichnis)
  • Nutzer
    • Steffen
    • Maik

Die Idee ist nun, dass die Nutzer sich eine Datenbank bei Bedarf einfach aus dem Lager in ihren Nutzer-Ordner schieben. Dabei passiert auf dem Dateisystem ja kein Kopiervorgang – sondern nur ein sehr schneller Verschiebevorgang. Der Lager-Ordner wird jedoch von einem Mini-Tool überwacht. Dies hat den Vorgang registriert und kopiert nun im Hintergrund die Datenbank aus dem Originalverzeichnis ins Lager. Sobald dieser Vorgang abgeschlossen ist, kann der nächste Nutzer wieder schnell auf die DB im Lager zu greifen.

Nun zur Implementierung des Überwachungs-Tools in C#:

// Consolenstart static void Main(string[] args) { FDBWatcher fdbWatcher = new FDBWatcher(); Console.ReadLine(); } class FDBWatcher { private string warehousePath = @"C:\\Test\\Lager\\"; private string originalPath = @"C:\\Test\\Original\\"; private string targetEndingFilter = "*.fdb"; public FDBWatcher() { FileSystemWatcher fdbWatcher = new FileSystemWatcher( warehousePath, targetEndingFilter); fdbWatcher.EnableRaisingEvents = true; fdbWatcher.IncludeSubdirectories = false; fdbWatcher.Deleted += new FileSystemEventHandler(fdbWatcher_Deleted); Console.Write("FileSystem Watcher started"); } private void fdbWatcher_Deleted(object sender, FileSystemEventArgs e) { Console.WriteLine("File {0} deleted", e.FullPath); FileInfo oldFile = new FileInfo(e.FullPath); FileInfo originalFile = new FileInfo(originalPath + oldFile.Name); originalFile.CopyTo(oldFile.FullName); Console.WriteLine( "Copy {0} to {1}", originalFile, oldFile); } }

Monday, 16. October 2006


Navision das "überfleißige" Bienchen

Filed under: C#,Navision — Steffen Forkmann at 9:37 Uhr

Navision scheint auf “Lazy Evaluation” komplett zu verzichten und ganz fleißig jeden logischen Ausdruck bis zum Ende durchzurechnen.

Mit folgendem Beispiel kann man das leicht nachprüfen:

IF A AND B THEN MESSAGE('A and B'); ... PROCEDURE A@1000000001() : Boolean; BEGIN MESSAGE('A'); EXIT(FALSE); END; PROCEDURE B@1000000002() : Boolean; BEGIN MESSAGE('B'); EXIT(TRUE); END;

Wenn man diesen Code ausführt werden beide Messages (‘A’ und ‘B’) angezeigt, obwohl eigentlich nach Funktion A der Term A AND B schon als falsch ausgewertet werden kann. Wenn man selbiges Beispiel in C# aufschreibt wird übrigens nur A() ausgeführt:

if (A() && B()) MessageBox.Show("A and B"; ... bool A() { MessageBox.Show("A"); return false; } bool B() { MessageBox.Show("B"); return true; }

Ähnlich verhält es sich auch mit allen anderen logischen Ausdrücken – Navision rechnet bis ganz zum Ende alles durch.

Friday, 6. October 2006


Lambda Operator C# 3.0

Filed under: .NET 3.0,C#,F# — Sebastian Wolf at 18:00 Uhr

Delegates gibt es schon in C#, aber mit dem Lambda Operator (=>) geht das nun kürzer.

Folgendes generisches Beispiel (bisher):

CSharp [Show Plain Code]:
  1. delegate T Func(T t);
  2. Func  funcDel = delegate(int x)
  3. {
  4. return x + x;
  5. }
  6. Console.WriteLine(funcDel(5));

Äquivalent mit Lampda Operator:

CSharp [Show Plain Code]:
  1. Func lambda = x =&gt; x + x;
  2. Console.WriteLine(lambda(5));

Monday, 18. September 2006


Navision: Report in bestimmten Druckerfach ausgeben

Filed under: C#,msu solutions GmbH,Navision — Steffen Forkmann at 14:28 Uhr

Oftmals steht man im Navision vor dem Problem einen Report in einem bestimmten Druckerfach auszugeben. Dafür muss man jedoch die RawKind-Property des Druckerfachs wissen und im Report als PaperSourceFirstPage bzw. PaperSourceOtherPages oder über CurrReport.PaperSource einstellen. Leider gibt es im Navision keine einfache Möglichkeit diese Property auszulesen. Mit dem folgenden Stück C#-Code kann man sich jedoch alle installierten Drucker samt unterstützten Druckerfächern anziegen lassen:  

using System.Drawing.Printing; .. PrinterSettings ps = new PrinterSettings(); foreach (string name in PrinterSettings.InstalledPrinters) { listBox1.Items.Add(name); ps.PrinterName = name; foreach (PaperSource paperSource in ps.PaperSources) listBox1.Items.Add(ps); }
Download: FindPrinter-Tool (benötigt: .NET Framework 2.0)
Tags: , ,

Thursday, 17. August 2006


Konfigurationsdateien schnell und flexibel

Filed under: C# — Sebastian Wolf at 17:03 Uhr

Nini ist eine .Net Library mit welcher man besonders schnell hoch flexible Anwendungen mit Konfigurationsdateien erstellen kann. Die Anwendung ist denkbar einfach wie man im folgenden Beispiel sieht:

; MyApp.ini [Logging] File Name = MyApp.log MessageColumns = 5 MaxFileSize = 40000000000000

Und der C# Code zum einlesen sieht folgendermasen aus:

using Nini.Config; IConfigSource source = new IniConfigSource("MyApp.ini"); string fileName = source.Configs["Logging"].Get("File Name"); int columns = source.Configs["Logging"].GetInt("MessageColumns"); long fileSize = source.Configs["Logging"].GetLong("MaxFileSize");

Das war aber noch längst nicht alles. Noch mehr gibt es hier.

Sunday, 26. March 2006


Visual SourceSafe (VSS) Integration in Microsoft Dynamics Nav

Filed under: C#,Navision,Tools — Steffen Forkmann at 19:09 Uhr

Da es keine native Möglichkeit gibt ein Quellcode-Versionsverwaltungsprogramm in Microsoft Navision einzubinden, haben wir bei der msu solutions GmbH eine eigene Lösung zum Zugriff auf Visual Source Safe oder Subversion (SVN) implementiert. Die entstandene Lösung ist ein Hybrid aus C# 2.0 COM-Objekten und nativen Navision-Objekten.

ObjectList

Der allgemeine Arbeitsablauf gestaltet sich nun folgendermaßen:

  1. Eine Aufgabe aus dem internen Bug & Task Tracker ziehen.
  2. Statt dem klassischen “Design” im Object Designer einfach im internen Object Designer auf “Auschecken” klicken. Dadurch wird das Objekt im VSS ausgecheckt und die aktuelle Version neu ins Navision importiert und im Designer geöffnet.
  3. Nun kann man im Navision Quelltext Editor Änderungen vornehmen und evtl. weitere Objekte auschecken.
  4. Vor dem Einchecken auf “Compare” klicken. Dadurch wird ein Diff zwischen der bearbeiteten Version und der Version im VSS angezeigt. (Das Diff-Programm kann frei gewählt werden. Standardmäßig ist WinMerge eingestellt.)
  5. Im internen Object Designer auf die ausgecheckten Objekte filtern und die Objekte durch Klick auf “Einchecken” mit dem aus dem Bug & Task Tracker vorgegebenen Checkin-Kommentar ins VSS einchecken.

Als weiteres besonderes Feature ist die Versionsgeschichte zu nennen. Im internen Object Designer kann man einfach auf ein Objekt gehen und durch Druck auf “History” die Versionsgeschichte des Objektes aus dem Visual SourceSafe abrufen. Dort kann man die Checkin-Kommentare ansehen, Version-Pins versetzen und sich Diffs zwischen den verschiedenen Versionen anzeigen lassen.

Versionsgeschichte

Interessant ist auch die interne Suchen nach Objekten (und deren Versionen bzw. Differenz dazwischen) die mit einer bestimmten Aufgabe geändert wurden. So fällt das Portieren von Features zwischen verschiedenen Entwicklungszweigen wesentlich leichter.

Suche in den Versionen

So macht das Programmieren in Navision gleich viel mehr Spaß und die Versionsverwaltung ist damit fast so einfach wie im Visual Studio – da bleiben dann ja nur noch die beiden größten Navision Schwächen: Editor und Debugger 🙂

Tags: , , , , , , , , , , ,

Wednesday, 25. January 2006


Ein neuer Compiler in einer Stunde [ein Nightcast]

Filed under: C#,Theoretische,WebCasts — Steffen Forkmann at 8:30 Uhr

In diesem Nightcast möchte Bernd Marquardt ein interessantes Thema aufgreifen. Er will in einer Stunde einen kleinen Sprach-Compiler entwickeln. Geplant sind ein kleine Einführung in Compilerbau und dann natürlich das Praktische also der Code, der notwendig ist, um einen eigenen Sprach-Compiler mit .NET zu entwickeln.