Sunday, 3. December 2006
Dec 03
Unter SEO’s gibt es ja schon geraume Zeit eine hitzige Diskussion über die Google SandBox. Gemeint ist damit eine Art Schutzsystem, das dafür sorgt, dass junge Seiten erstmal in einer Art “Sandkastenmodus” gelistet werden. Konkret bedeutet das, dass die Seiten im Google-Suchergebnis bei bestimmten Keywords schlecht gelistet werden. Google sammelt dann mit der Zeit Daten über die Seite und überprüft die tatsächliche Relevanz. Damit soll Spam und vor allem Rankingbetrug eingedämmt werden.
Das eine solcher Mechanismus wie die Sandbox im Google-Algorithmus existieren muss, habe ich nun auch erleben dürfen: Mein Artikel zum Xda orbit von O2 hatte erstaunlicherweise nach nur einem Tag so viele starke Backlinks gesammelt, dass Google den Artikel auf Platz 7 bei “xda orbit” gelistet hat. Da meine Seite ja eigentlich aber nichts mit PDA’s zu tun hat, war das in “Googles Augen” wohl ein zu starkes Wachstum in zu kurzer Zeit und demnach erstmal verdächtig. Also flog die Seite wieder raus aus den Suchergebnissen und ab in die Sandbox. Da aber die Backlinks nicht abrissen, wird die Seite nun wieder in den Google-Top10 gelistet.
Der ganze Vorgang hat nur ca. eine Woche gedauert – das liegt wahrscheinlich daran, dass den Backlinks von starken Seiten viel Vertrauen zugeprochen wird. Bei kleineren Seiten wird das Spiel höchstwahrscheinlich länger dauern.
Viele SEO’s empfehlen einen “langsamen Linkaufbau” (wie z.B. hier) – meine persönliche Erfahrung zeigt aber, dass Links von starken Seiten schnell dafür sorgen können, dass man auch wieder aus der Sandbox raus kommt. Mal ganz davon abgesehen, dass man einen “Linkaufbau” sowieso nur bedingt steuern kann 😉
Tags:
backlinks,
Diverses,
google-algorithmus,
orbit,
pda,
sandbox,
seo,
Tools
Saturday, 4. November 2006
Nov 04
Im fünften Teil meiner Serie möchte ich auf erweiterte Möglichkeiten der Konfiguration des Dienstes eingehen. Über die ApplicationSettings ist es in Visual Studio ganz einfach möglich Strings, Integer usw. als globale Anwendungseinstellungen (web.config bei ASP.NET – sonst app.config) abzuspeichern:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="...">
<section name="DBCopyService.Properties.Settings"
type="..."
allowExeDefinition="MachineToLocalUser"
requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<DBCopyService.Properties.Settings>
<setting name="ServerName" serializeAs="String">
<value>serverName</value>
</setting>
</DBCopyService.Properties.Settings>
</userSettings>
</configuration>
Der Zugriff auf die Einstellung “ServerName” erfolgt dann ganz einfach über Properties.Settings.Default.ServerName. Man kann sogar zur Laufzeit die Settings ändern und wieder abspeichern.
Wenn man jedoch komplexere Strukturen in den Einstellungen ablegen möchte, kommt man um etwas Code nicht mehr herum. Im folgenden Beispiel lege ich die neue Sektion “entrances” an, um dort dann beliebig viele Eingangsverzeichnisse überwachen zu lassen:
Eintrag in der app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="DBCopyService">
<section name="entrances"
type="DBCopyService.EntranceSection,DBCopyService" />
</sectionGroup>
</configSections>
<DBCopyService>
<entrances>
<entrance name="entrance1" path="C:\Eingang\"
mailAddress="mail@server.de" />
<entrance name="entrance2" path="C:\Eingang2\"
mailAddress="mail2@server.de" />
</entrances>
</DBCopyService>
</configuration>
Zugriff über Ableitung von ConfigurationElement, ConfigurationElementCollection und ConfigurationSection:
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace DBCopyService
{
public sealed class EntranceElement : ConfigurationElement
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[ConfigurationProperty("name", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
/// <summary>
/// Gets or sets the mail address.
/// </summary>
/// <value>The mail address.</value>
[ConfigurationProperty("mailAddress", IsRequired = true)]
public string MailAddress
{
get { return (string)base["mailAddress"]; }
set { base["mailAddress"] = value; }
}
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
[ConfigurationProperty("path", IsRequired = true)]
public string Path
{
get { return (string)base["path"]; }
set { base["path"] = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace DBCopyService
{
public sealed class EntranceCollection
: ConfigurationElementCollection
{
protected override ConfigurationElement
CreateNewElement()
{
return new EntranceElement();
}
protected override object GetElementKey(
ConfigurationElement element)
{
return ((EntranceElement)element).Name;
}
public override ConfigurationElementCollectionType
CollectionType
{
get
{
return
ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get{ return "entrance"; }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace DBCopyService
{
public sealed class EntranceSection : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
public EntranceCollection Entrances
{
get { return (EntranceCollection)base[""]; }
}
}
}
Mit Hilfe dieser Klassenstruktur (Element, Collection, Section) kann man nun bequem auf die Section zugreifen:
EntranceSection entranceSection =
ConfigurationManager.GetSection("DBCopyService/entrances")
as EntranceSection;
foreach (EntranceElement element in entranceSection.Entrances)
Console.WriteLine(
string.Format("Path {0}, Mail {1}",
element.Path,
element.MailAddress));
Nov 04
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);
Monday, 30. October 2006
Oct 30
Steven Jean beschreibt in einem umfangreichen Artikel die Versionsverwaltungsfeatures des Team Foundation Server aus der Sicht von VSS-Nutzern. Er zeigt u.a. die veränderten Arbeitsabläufe und die neuen Sicherheitsfeatures die sich mit dem TFS ergeben. Eines der größten Vorteile aus meiner Sicht ist übrigens, dass beim Check-In die definierten Policies überprüft werden und so nur Code eingecheckt werden kann, der bestimmten selbstdefinierbaren Richtlinien entspricht.
Interessant in diesem Zusammenhang ist auch ein Channel 9 Video in dem John Lawrence, seines Zeichens Development Manager des “Visual Studio 2005 Team Foundation’s Source Code Management Teams”, interessante Anwendungsmöglichkeiten des Team Foundation Servers zeigt – zum Beispiel auch automatisch generierte RSS-Feeds mit den Bugmeldungen.
Tags:
Team Foundation Server,
Tools,
Visual SourceSafe,
Visual Studio,
vss
Friday, 27. October 2006
Oct 27
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);
}
Thursday, 26. October 2006
Oct 26
Microsoft hat die Windows Desktop Search Version 3 released. Der Vorteil ist, dass diese Version schon von Hause aus Visio, C#, C++ Files usw. schön getrennt spidert. Mit Hilfe des “Add-in for UNC/FAT” können sogar Netzlaufwerke gespidert werden. Das ist vor allem für Firmen interessant, da man so endlich Volltextsuche für die eigenen Office-Dokumente im Netzwerk hat.
Man kann wie in den älteren Versionen auch eigene PlugIns schreiben, um die Indizierung von eigenen Dateitypen zu unterstützen.
Die Google Desktop Search fliegt jetzt also erstmal wieder runter.
Tuesday, 24. October 2006
Oct 24
Seit gestern ist nun auch die kostenlose Anti-SpyWare Windows Defender als offizielles Release zum kostenlosen Download verfügbar. Microsoft gibt sogar 2 kostenlose Support-Anfragen dazu.
Features:
- Spyware Erkennung und Entfernung
- Läuft im Hintergrund und bleibt automatisch auf dem neuesten Stand durch automatische Updates
- Sehr einfache Oberfläche
- Sehr gute Performance durch optimierte Scan Technologie
Weiteres und den Download gibt es hier.
Nachtrag: Laut Windows Defender bin ich clean – nur der RSSBandit “könnte potentiell ungewolltes Verhalten verursachen”. Â
Saturday, 21. October 2006
Oct 21
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");

Friday, 20. October 2006
Oct 20
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
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);
}
}
Sunday, 26. March 2006
Mar 26
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.

Der allgemeine Arbeitsablauf gestaltet sich nun folgendermaßen:
- Eine Aufgabe aus dem internen Bug & Task Tracker ziehen.
- 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.
- Nun kann man im Navision Quelltext Editor Änderungen vornehmen und evtl. weitere Objekte auschecken.
- 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.)
- 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.

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.

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:
C#,
com,
cvs,
Navision,
perforce,
quellcodeverwaltung,
source-safe,
subversion,
svn,
Tools,
visual-source-safe,
vss