Home  |  Über den Autor  |  Impressum  |  .NET Developer Group Braunschweig  |  Hönigsberg & Düvel

RSS 2.0 | Atom 1.0 | CDF | Send mail to the author(s)  
 Wednesday, June 13, 2007

Am Montag, den 18.06.07, findet ab 19:00 Uhr das nächste Treffen der .NET Developer Group Braunschweig statt.

Als ASP.NET Entwickler freue ich mich besonders auf den Vortrag von Aleksander Seovic über "Distributed Caching: Essential Lessons". Aleksander ist Managing Director bei Solutions for Human Capital, Inc. und Co-Lead für Spring.NET. Außerdem ist er der erste Sprecher bei unserer Usergroup der seinen Vortrag auf englisch halten wird.

Nähere Infos unter http://www.dotnet-braunschweig.de

 

posted on 6/13/2007 9:24:15 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 Wednesday, June 06, 2007

Auch ich darf mich nun zum "Kreis der Erlauchten" zählen, die ein Zertifikat von Microsoft haben und darf mich fortan als

"Microsoft Certified Technology Specialist for Microsoft Team Foundation Server Configuration and Development"

bezeichnen.

Hmm, ein bisschen länger hätte der Titel schon sein können...je länger desto wichtiger, oder? ;-)


MCTS - Microsoft Team Foundation Server

posted on 6/6/2007 8:01:08 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [9]

 Thursday, May 24, 2007

Nach dem ich es nun nach Stunden endlich geschafft habe eine BCM 2007 Datenbank auf einem reinen Server zu installieren und vom Client darauf zuzugreifen muss ich mein Erfolgserlebnis doch glatt mit Euch teilen.

Nach dem Durchforsten des Internets bin nach vielen Forumseinträgen mit gleicher Problemstellung, aber ohne Lösung auf folgendes Dokument gestoßen:

Deploying Outlook 2007 with Business Contact Manager in a Remote Database Configuration

Super, dachte ich. Eine Anleitung von Microsoft, da kann ja fast nix mehr schief gehen. Denkste ich hab zwar sowohl eine neue, als auch eine bestehende Datenbank gehabt, aber der Client konnte die entsprechende Datenbank immer nicht finden.

Zum Glück habe ich nach einiger Zeit weitergoogeln folgendes Tool gefunden:

Outlook 2007 with Business Contact Manager: Database Admin Tool

Damit war das Ganze ein leichtes. Einfach installieren, neue DB erstellen und mit dem Client verbinden....MEEP!!! Oder auch nicht :(

Das Problem war aber schnell behoben. Einfach in der Tabelle OrgTable in der Spalte LocaleID den Wert von "en-US" auf "de-DE" ändern. Dann klappt's auch mit dem Client.

Mit einer bestehenden Datenbank funktioniert das auch wunderbar:

1) Datenbankdateien auf den Server kopieren

2) Im Management Studio die Datenbank anhängen

3) Ggf. in der Tabelle OrgTable den Wert LocaleID auf "en-US" setzen

4) In der Tabelle OrgTable den Wert SharedServer auf den Namen des Rechner mit der Datenbank setzen

5) Admin-Tool starten und "Share a database" auswählen

6) Ggf. in der Tabelle OrgTable den Wert LocaleID auf "de-DE" setzen


Weiterführende Links:

Business Contact Manager Team Blog

posted on 5/24/2007 2:00:58 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [15]

 Friday, May 11, 2007

Lange hat's gedauert, aber nun ist es soweit: Die Internet Explorer Developer Toolbar ist in der Version 1.0 erschienen. Neue Features gegenüber der Beta 3 scheint es allerdings nicht zu geben, sondern nur ein paar “fit-and-finish improvements" wie es das IE Team schreibt.

Download und Releaseinfos gibt's hier.

posted on 5/11/2007 8:42:46 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 Monday, April 23, 2007

Für alle die etwas mehr über den Microsoft Composite UI Application Block wissen möchten ist vielleicht folgender Webcast interessant:

Why CAB? A Business Manager's Perspective on Microsoft Composite UI Application Block

Inhalt:

  • Learn how CAB supports complex apps with rapidly changing requirements
  • See a working example demonstrating key capabilities
  • Understand the benefits and risks
  • Identify next steps to move forward with CAB

Info: 11:00 AM PST ist bei uns 20.00 Uhr.

 

posted on 4/23/2007 9:41:29 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 Monday, March 26, 2007

Da ich vor kurzem bei der .NET Developer Group Braunschweig einen Vortrag über Office Open XML gehalten habe, dachte ich mir, ich schreibe mal etwas zu diesem Thema. Ich werde kurz erläutern, wie das Format aufgebaut ist und werde an einem Beispiel zeigen, wie man die Bilder in einem Dokument manipulieren kann, indem ich einen Copyright-Hinweis darauf platzieren werde.

Das neue Dateiformat in Office 2007 ist wohl ohne zu übertreiben ein wahrer Segen für die .NET Entwicklergemeinde. Lange hat es gedauert, bis Microsoft ein Dateiformat geschaffen, das sowohl lizenzfrei, wie auch entwicklerfreundlich ist. Wie der Name schon sagt, ist das neue Office-Format kein Binärcode mehr, sondern basiert auf XML. Zwar gab es auch schon bei Office 2003 einen XML-Vorstoß von Microsoft, dieser war aber meiner Meinung nach nicht wirklich brauchbar. Folgend werde ich das Format anhand einer Word2007-Datei erläutern. Die verwendete Word-Datei ist in meinem Beispielprojekt enthalten.

Ein erster Blick

Das erste was auffällt, ist das die Dateiendung auf .docx geändert wurde. Für den Anwender besteht ein Word-Dokument also weiterhin aus einer einzigen Datei. Für Entwickler steckt aber weitaus mehr dahinter. Ändert man die Dateiendung auf .zip sieht man, dass die Datei eigentlich ein Zip-Container ist. Diesen Container bezeichnet Microsoft als Package. Ein Package besteht aus mehreren Teilen (Parts).

Abbildung 1: Docx-Container

Als erstes XML-Dokument fällt z.B. die Datei [Content_Types].xml auf. Darin wird definiert, welche Art von Inhalt in welchem Part vorhanden sein darf.

Das Word-Format ist natürlich sehr umfangreich und komplex. Wer es einmal erforschen  möchte, den kann ich die aufgeführten Links am Ende des Artikels empfehlen.

Bilder ausfindig machen
Da wir an die Bilder ran wollen, schauen wir uns doch mal ein wenig in der Ordnerstruktur um. Siehe da, unter word/media/ gibt es zwei Bilder image1.jpeg und image2.jpeg. Ein Doppelklick darauf verrät uns, dass es sich, wie vermutet, um die Bilder aus dem Dokument handelt.

Natürlich können wir die Bilder nun manuell extrahieren, manipulieren und wieder in den Ordner packen. Für Entwickler ist diese Vorgehensweise aber eher uncool ;-)

Cool dagegen ist übrigens, dass man die Bilder auch löschen kann. Das Word-Dokument lässt sich danach trotzdem noch öffnen. Das neue Format ist also durch seinen modularen Aufbau auch wesentlich robuster geworden.

Bevor wir zum spannenden Teil kommen möchte ich aber noch ein bisschen auf die Details eingehen. Zwar wissen wir nun wo die Bilder sind und könnten prinzipiell per Code auch direkt darauf zugreifen, aber ein bisschen die Zusammenhänge verstehen schadet ja nicht.

Die Datei word/document.xml beinhaltet das eigentliche Word-Dokument. Darin findet man folgenden  Knoten:

<w:drawing>

         

<wp:docPr id="4" name="Grafik 0" descr="Sunset.jpg"/>

<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">

<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">

                  <pic:nvPicPr>

                    <pic:cNvPr id="0" name="Sunset.jpg"/>

                    <pic:cNvPicPr/>

                  </pic:nvPicPr>

                  <pic:blipFill>

                    <a:blip r:embed="rId4"/>

                    <a:stretch>

                      <a:fillRect/>

                    </a:stretch>

                  </pic:blipFill>

    

        </w:drawing>

Wie man sich denken kann wird in diesem Abschnitt das Bild „Sunset.jpg“ in das Dokument eingebettet. Aber halt, im Ordner word/media/ gibt es nur die Bilder image1.jpeg und image2.jpeg?!

Wichtig ist folgende Zeile:
<a:blip r:embed="rId4"/>

Das Bild wird also nicht direkt in das Dokument eingebettet, sondern nur ein Verweis auf eine Relation namens rId4. Öffnen wir nun die Datei word/_rels/document.xml.rels finden wir dort folgende Zeile:

 

<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>


Damit wäre dieses Rätsel auch gelöst. Mit diesem Wissen im Hinterkopf kommen wir jetzt endlich zum spannenden Teil…

Bilder per Code auslesen

Wie gesagt, könnten wir mittels einer ZIP-Komponente wie SharpZipLib das Dokument öffnen und direkt auf die Bilder zugreifen. Das wäre aber zu einfach. Ich zeige nun, wie man generell an Bilder nicht nur in Word-Dokumenten, sondern auch in sonstigen Office-Dokumenten wie Excel oder PowerPoint rankommt, ohne dass man genau wissen muss wo genau sie sich innerhalb der Dokumentstruktur befinden bzw. um was genau für eine Datei es sich handelt.

Um Open XML Dateien zu verarbeiten hat Microsoft in .NET 3.0 Framework den Namensraum System.IO.Packaging eingeführt. Der Namensraum befindet sich in der Dll WindowsBase.dll. normalerweise kann man diese nach Installation von .NET 3.0 als normale .NET-Referenz hinzufügen. Bei wem (wie bei mir) die Dll fehlt, der muss sie manuell hinzufügen (C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll).

Als erstes müssen wir die Datei bzw. das Package erstmal öffnen:

Package pack = Package.Open(filePath);

Danach lesen wir den Document-Part ein:

PackagePart docPart = null;
Uri docUri = null;

foreach (PackageRelationship relDoc in pack.GetRelationshipsByType(documentRelationShipType))
{
    docUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relDoc.TargetUri);
    docPart = pack.GetPart(docUri);
    break; //es gibt nur ein Dokument in einer Word-Datei
}

In der foreach-Schleife durchlaufen wir alle Relationen im Package, die vom Typ Document sind. Den Namensraum, der in der Variablen documentRelationShipType(http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument) gespeichert ist findet man übrigens in der Datei /_rels/.rels.

Ich habe hier ein break eingefügt, da in einer Word-Datei nur ein Dokument enthalten ist. Bei Excel gibt es z.B. mehrere. In dem Fall könnte man die folgende foreach-Schleife in die erste verschachteln.

Wenn wir den Document-Part haben, können wir aus diesem die enthaltenen Relationen vom Typ Image auslesen. Vorher erstellen wir aber noch einen relativen URI, der uns den Pfad zum Document-Part angibt. In diesem Fall ist das "/word/".
Den imageRelationShipType findet man innerhalb des Package in der Datei /word/_rels/document.xml.rels. 

string baseUri = docUri.OriginalString.Remove(docUri.OriginalString.LastIndexOf('/') + 1);
PackagePart imagePart
= null
;
Uri imageUri
= null
;


foreach (PackageRelationship relImage in
docPart.GetRelationshipsByType(imageRelationShipType))
{
    imageUri
= new Uri(baseUri +
relImage.TargetUri, UriKind.Relative);
    imagePart
=
pack.GetPart(imageUri);

    System.Drawing.Image img
=
System.Drawing.Image.FromStream(imagePart.GetStream());
    Graphics g
=
Graphics.FromImage(img);
    g.DrawString(
"Copyright by netcreate", new Font("Arial", 54), Brushes.White, new
PointF(10, 10));
    img.Save(imagePart.GetStream(), System.Drawing.Imaging.ImageFormat.Jpeg);
}

 

Mithilfe eines ImageParts können wir das Bild als Stream einlesen, ein bisschen drauf rummalen, und das veränderte Bild wieder zurück in den Stream schreiben. Zum Schluß müssen wir das Package nur noch schließen.

pack.Close();

 

Da sieht man, wie man mit ein paar Zeilen Code schon eine ganze Menge erreichen kann. Das schöne am neuen Format ist übrigens auch, dass man keine installierte Version von Office mehr benötigt. Man kann also Word-Dokumente wie in meinem Beispeil-Webprojekt auch auf einem Webserver manipulieren oder gar dynamisch generieren. Wer nun etwas mehr Lust auf dieses Thema bekommen hat, den kann ich nur die bereits erwähnten Links empfehlen:

[1] Einführung in die Microsoft Office (2007) Open XML-Dateiformate
http://www.microsoft.com/germany/msdn/library/office/EinfuehrungInDieMicrosoftOffice2007OpenXMLDateiformate.mspx?mfr=true

[2] Walkthrough: Word 2007 XML Format
http://msdn2.microsoft.com/en-us/library/ms771890.aspx

[3] Beispiele und Tutorials
http://openxmldeveloper.org

[4] Microsoft Office Compatibility Pack für Dateiformate von Word, Excel und PowerPoint 2007
http://www.microsoft.com/downloads/details.aspx?FamilyID=941b3470-3ae9-4aee-8f43-c6bb74cd1466&DisplayLang=de

[5] Beispiel-Projekt
http://blogs.dotnet-braunschweig.de/karim/downloads/WordImages.zip

 

posted on 3/26/2007 10:21:25 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [1]

 Friday, March 02, 2007

Nachdem auch wir bei netcreate nach dem Update des Firefox auf Version 2.0.0.2 so unsere Probleme hatten, freue ich mich, dass schon kurze Zeit später das SP2 heute released wurde. Der Fehler wurde von den Jungs (und Mädels?) von Telerik wie zu erwarten schleunigst behoben.

Weiterhin wurden viele weitere Bugs behoben und weitere Features hinzugefügt. Eine komplette Zusammenfassung findet man hier.

Good Job! :)

 

 

 

posted on 3/2/2007 6:06:37 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 Thursday, March 01, 2007

Ich habe bei einem Projekt gerade ein "Problem", dass ich nicht wirklich nachvollziehen kann. Hier mal ein Codeschnipsel:

FileInfo fi = new FileInfo(licName);

if (fi.Exists == false)
{   
      throw new Exception("Die Lizenzdatei konnte nicht gefunden werden.");
}

fi.Exists liefert mir true zurück, trotzdem spring er in die Klammer und markiert die Exception!

Wenn ich anstatt des throw einfach eine Dummy-Zeile (z.B. string s="";) einsetze, dann geht er wie erwartet nicht in die Klammer. Scheint also tatsächlich was damit zu tun zu haben, das ich dort eine Exception feuere. Ich hab erst gedacht, das Visual Studio mal wieder aus dem Tritt gekommen ist, also Rechner neu starten! Der Fehler passiert aber auch nach einem Neustart immer noch.


Ich hab spaßeshalber die Bedingung mal auf true gesetzt und eine Dummy-Zeile eingebaut:

if (fi.Exists == true)
{   
      string s = "";
      throw new Exception("Die Lizenzdatei konnte nicht gefunden werden.");
}

In diesem Fall springt der Debugger richtigerweise auf die erste Zeile. Setze ich die Bedingung auf false, springt er direkt in die zweite Zeile zur Exception. Die Exception wird zwar nicht wirklich gefeuert, aber der Debugger markiert mir die Zeile.

Hat jemand dafür eine Erklärung?

NACHTRAG: Ich habe gerade mal eine weitere Dummy-Zeile vor der Exception eingefügt. Nun funktioniert es wie erwartet!?!

 

posted on 3/1/2007 9:24:18 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [2]