Donnerstag, 30. Oktober 2008

Toolbox-Item hinzufügen bei installierten Power Commands nicht möglich

Gerade eben wollte ich mir die Chart Controls für das .NET Framework 3.5 anschauen, die Microsoft vor kurzem veröffentlicht hat.
Leider war nach der Installation des Pakets nichts neues im Data-Tab der Toolbox zu finden. Laut Anleitung soll man für diesen Fall die Controls einfach händisch hinzufügen. Als ich das jedoch versuchte, fror mein Visual Studio 2008 einfach ein oder stürzte gar ab. Letzteres erfreulicherweise ohne jede Fehlermeldung.

Nach ein wenig Recherche habe ich tatsächlich herausgefunden, dass das Verhalten durch die installierten Power Commands für Visual Studio 2008 hervorgerufen wird.
Also habe ich diese schnell deinstalliert und siehe da, ich kann wieder Items zur Toolbox hinzufügen.

Sehr schade, dass die Power Commands einen derart negativen Einfluss auf VS2008 haben, denn eigentlich finde ich sie sehr nützlich. Deshalb werde ich sie auch wieder installieren und hoffen, dass ich mich das nächste mal, wenn ich etwas in die Toolbox schieben möchte, daran denke, sie zuvor zu deinstallieren.

Interessant ist im Übrigen auch, dass mein Kollege die Power Commands ebenfalls installiert hat, er jedoch problemlos neue Items in die Toolbox einfügen kann...

Nachtrag:
Ich habe die Power Commands jetzt wieder installiert und erneut versucht, ein Toolboxelement hinzuzufügen. Siehe da, es funktioniert einwandfrei.

Mittwoch, 29. Oktober 2008

Hexadezimaldarstellung eines Strings nach Int32 umrechnen - bbo-Style

Wie tropensturm Hex-Strings nach Int32 konvertiert, haben wir heute schon gelernt. Natürlich hat er gleich wieder Forderungen gestellt, also kommt hier meine Version.

Zunächst muss ich anmerken, dass ich wesentlich pragmatischer an die Sache herangegangen bin. Ich habe Dinge wie Encoding und Little- / Big-Endian vernachlässigt, denn ich brauchte schnell eine funktionierende Lösung für einen Test.

Folgender Code ist bei mir dabei heraus gekommen:

   1:  public static int ConvertHexStringToInt(string hexString)         
   2:  {
   3:      string hex = "0x";
   4:   
   5:      for (int i = 0; i < hexString.Length; i++)
   6:      {
   7:          hex += ((int)hexString[i]).ToString("X");
   8:      }
   9:   
  10:      return Convert.ToInt32(hex, 16);
  11:  }

Im Prinzip ist das, was ich hier tue, eigentlich recht einfach.
Zunächst lege ich mir eine String-Variable an, die die hexadezimale Darstellung des übergebenen Strings aufnehmen soll. In der for-Schleife sorge ich entsprechend dafür, dass dies auch so ist. In Zeile 7 wandle ich zunächst jeden Buchstaben des Übergabe-Strings in seine ASCII-Int32-Repräsentation, die anschließend nach Hexadezimal konvertiert und dem finalen String angehängt wird.
Ist die Schleife für alle Zeichen des Strings durchlaufen worden, haben wir einen String im Format 0xA9AE.
Diesen String konvertiere ich dann in Zeile 10 noch nach Int32, wobei ich eine Basis von 16 (also hexadezimal) angebe und gebe das Ergebnis zurück.

So weit, so einfach...
... leider aber auch so "beschränkt".
Durch das Konvertieren jedes Buchstabens in seine Int32-Repräsentation in Zeile 7 wird diese Lösung auf Zeichen beschränkt, die im ASCII-Zeichensatz vorhanden sind. Werden Zeichen verwendet, die in diesem nicht auftauchen, führt das zu falschen Ergebnissen.

FAZIT:
Für meine Zwecke ist diese Implementierung absolut ausreichend, da ich mir sicher sein kann, dass mein Übergabe-String nur Zeichen enthält, die auch im ASCII-Zeichensatz auftauchen. Für einen produktiven Einsatz ist aber auf jeden Fall tropensturms Lösung vorzuziehen, da diese eben auch mit nicht ASCII-konformen Zeichen umgehen kann.

bbo-Style: 0
tropensturm-Style: 1

Freie Cryptography API

Eine freie Cryptography API, inkl. OpenPGP, ohne jegliche Lizenzeinschränkungen mit der Ausnahme das License Informations File weiterzugeben. Hört sich zu gut an um wahr zu sein? :)

The Legion of the Bouncy Castle - Bouncy Castle Cryptography API

Features:
  • Generation and parsing of PKCS-12 files.
  • X.509: Generators and parsers for V1 and V3 certificates, V2 CRLs and attribute certificates.
  • PBE algorithms supported by PBEUtil: PBEwithMD2andDES-CBC, PBEwithMD2andRC2-CBC, PBEwithMD5andDES-CBC, PBEwithMD5andRC2-CBC, PBEwithSHA1andDES-CBC, PBEwithSHA1andRC2-CBC, PBEwithSHA-1and128bitRC4, PBEwithSHA-1and40bitRC4, PBEwithSHA-1and3-keyDESEDE-CBC, PBEwithSHA-1and2-keyDESEDE-CBC, PBEwithSHA-1and128bitRC2-CBC, PBEwithSHA-1and40bitRC2-CBC, PBEwithHmacSHA-1, PBEwithHmacSHA-224, PBEwithHmacSHA-256, PBEwithHmacRIPEMD128, PBEwithHmacRIPEMD160, and PBEwithHmacRIPEMD256.
  • Signature algorithms supported by SignerUtilities: MD2withRSA, MD4withRSA, MD5withRSA, RIPEMD128withRSA, RIPEMD160withECDSA, RIPEMD160withRSA, RIPEMD256withRSA, SHA-1withRSA, SHA-224withRSA, SHA-256withRSAandMGF1, SHA-384withRSAandMGF1, SHA-512withRSAandMGF1, SHA-1withDSA, and SHA-1withECDSA.
  • Symmetric key algorithms: AES, Blowfish, Camellia, CAST5, CAST6, DESede, DES, GOST28147, HC-128, HC-256, IDEA, ISAAC, NaccacheStern, Noekeon, RC2, RC4, RC5-32, RC5-64, RC6, Rijndael, Salsa20, SEED, Serpent, Skipjack, TEA/XTEA, Twofish and VMPC.
  • Symmetric key modes: CBC, CFB, CTS, GOFB, OFB, OpenPGPCFB, and SIC (or CTR).
  • Symmetric key paddings: ISO10126d2, ISO7816d4, PKCS-5/7, TBC, X.923, and Zero Byte.
  • Asymmetric key algorithms: RSA (with blinding), ElGamal, DSA, and ECDSA.
  • Asymmetric key paddings/encodings: ISO9796d1, OAEP, and PKCS-1.
  • AEAD block cipher modes: CCM, EAX, and GCM.
  • Digests: GOST3411, MD2, MD4, MD5, RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, Tiger, and Whirlpool.
  • Signer mechanisms: DSA, ECDSA, ECGOST3410, GOST3410, ISO9796d2, PSS, RSA.
  • Key Agreement: Diffie-Hellman and EC-DH.
  • Macs: CBCBlockCipher, CFBBlockCipher, GOST28147, HMac, ISO9797 Alg. 3, and VMPCMAC.
  • PBE generators: PKCS-12, and PKCS-5 - schemes 1 and 2.
  • OpenPGP (RFC 2440)
  • Cryptographic Message Syntax (CMS, RFC 3852), including streaming API.
  • Online Certificate Status Protocol (OCSP, RFC 2560).
  • Time Stamp Protocol (TSP, RFC 3161).
  • Elliptic Curve Cryptography (support for F2m and Fp curves).
  • Reading/writing of PEM files, including RSA and DSA keys, with a variety of encryptions. 
  • Hexadezimaldarstellung eines Strings nach Int32 umrechnen

    BBo hat mir eine Aufgabenstellung hingeworfen und wir haben diese dann unterschiedlich gelöst. Es ging darum die Hexadezimaldarstellung eines 2 Byte langen String nach Int32 zu konvertieren. Das war etwas schwieriger als wir dachten. Hier nun meine Lösungsvariante, vielleicht postet BBo ja noch seine ;)

    Das Erste was mir durch den Kopf ging ist, dass dies etwas gefährlich ist in Bezug auf das Stringencoding. Denn je nach dem wie der String decodiert wurde, hat man ja je nach Umgebung eine andere Hexadezimalwertdarstellung nach dem Encodieren. Darum habe ich einfach zur Absicherung das Encoding mit eingebaut in meine Lösung. Theoretisch kann man in einer homogenen Welt darauf verzichten, doch meine praktischen Erfahrungen in den letzten Monaten haben mir oft genug die Finger verkokelt. Man kann ja selber mal damit herumspielen und mit unterschiedlichen Encodings die unterschiedlichen Ergebnisse vergleichen...

       1:  // test
       2:  int erg = TwoByteStringHexValueToInt32("Aÿ", System.Text.Encoding.GetEncoding(1252));
       3:  ...
       4:   
       5:  public static int TwoByteStringHexValueToInt32(string input, Encoding encoding)
       6:  {
       7:     if (input.Length != 2)
       8:        throw new ArgumentException("TwoByteStringHexValueToInt32 - parameter input is allowed to be 2 byte long only!");
       9:              
      10:     if (encoding == null)
      11:        encoding = System.Text.Encoding.Default;
      12:   
      13:     int result = 0;
      14:     byte[] ba = encoding.GetBytes(input); // split to byte array of 2
      15:   
      16:     if (System.BitConverter.IsLittleEndian) // when little endian we need to do a workaround
      17:     {
      18:        result = (Convert.ToInt32(ba[0]) << 8) + Convert.ToInt32(ba[1]);
      19:     }
      20:     else
      21:     {
      22:        result = (int)System.BitConverter.ToInt16(ba, 0);
      23:     }
      24:   
      25:     return result;
      26:  }

    In Zeile 14 geht es richtig los, da zerleg ich den Input string in ein 2-Byte Array in Abhängigkeit (!) vom Encoding des Strings. 1252 ist das herkömmliche Encoding unter Windows für lateinische Schriftsysteme, u.a. Deutsch. Danach steht also in unserem Byte Array die Hexdarstellung unseres Strings.

    Danach mache ich einen kleinen Kunstgriff in Zeile 16, x86 Syteme sind LittleEndian kodiert, Motorola z.B. normalerweise BigEndian. Hier eine kleine Info wenn man damit nichts anfangen kann. Im Klartext, normalerweise rechnet man den Wert in unserem Bytearray wie in Zeile 22 gezeigt um. Mit dem Bitkonverter nach 16Bit Integer, werden 2 Bytes aus dem Bytearray ab der Position 0 gelesen und in Integer umgerechnet (Int32 bräuchte 4 Bytes, darum dieser Umweg).

    Und GENAU hier schlägt die Sache mit dem Little/Big Endian System zu! Denn wir haben zuvor oben unseren String eigentlich verkehrt herum abgelegt für unser x86 System!! Denn das rechnet von Hinten nach Vorne Bytedarstellungen nach Integer um!

    Daher das Byteshifting in Zeile 18, falls ein Little Endian System vorliegt. Ich greife mir das erste Byte konvertiere es nach Int32 und verschiebe es mal 8 Bits nach "links" (= 1 Byte, wir haben ja 2 Bytes und schieben das Erste sozusagen nach "vorne"), um dann einfach das Ergebnis aus der zweiten Byte Konvertierung dazu addieren.

    Nachtrag: Der Rückweg

       1:  public static byte[] Int16ToBigEndianByteArray(short input)
       2:  {
       3:     int higher = input >> 8;     // shift 1 byte -> get higher byte
       4:     int lower  = input & 0x00ff; // mask -> get lower byte
       5:   
       6:     byte[] ba = new byte[2];
       7:     ba[0] = Convert.ToByte(higher);
       8:     ba[1] = Convert.ToByte(lower);
       9:   
      10:     return ba;
      11:  }
      12:   
      13:   
      14:  ...
      15:  // test
      16:  byte[] ba = Int16ToBigEndianByteArray((short)31910);
      17:  string res = System.Text.Encoding.GetEncoding(1252).GetString(ba);

    Donnerstag, 16. Oktober 2008

    Embedded Ressources und ein bisschen mehr

    Dieser Blog entsteht aus einer Handvoll Diskussionen mit BBo über ein paar Tage hinweg. Irgendwie hab ich alle Punkte in ein Beispiel reingestopft bekommen :)

    Die Ursprungsfrage drehte sich darum, wie greift man auf eine eingebettete Ressource zur Laufzeit in meiner Assembly zu. Später kamen noch so Sinnesfragen hinzu wozu einen statischen Konstruktor, oder wie stell ich einfach fest ob die Konfiguration von log4net geklappt hat oder nicht,usw.

    Zur "embedded resource", als erstes hab ich eine XML angelegt, die einzig die Configurations Daten für Log4Net enthält. Ganz wichtig: unter Properties ist unter Build Action embedded resource auszuwählen, sonst finden wir das nachher nicht:

    Der Zugriff selber dann ist in Zeile 29 vom Code zu sehen. Beim auslesen der Ressource erhält man einen ganz normalen Stream, der kann dann wie gewohnt verarbeitet werden, log4net erlaubt uns eine Konfiguration direkt mit dem Stream. In Zeile 24 ist übrigens die Abfrage, ob Log4Net konfiguriert wurde, zu sehen.

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Text;
       4:  using System.Xml;
       5:  using System.IO;
       6:   
       7:  using Threading = System.Threading;
       8:  using Reflection = System.Reflection;
       9:  using L4N = log4net;
      10:   
      11:  namespace StaticLogWrapper
      12:  {
      13:      [Serializable]
      14:      public class Log
      15:      {
      16:          private static readonly L4N.ILog log = L4N.LogManager.GetLogger(typeof(Log));
      17:   
      18:          static Log()
      19:          {
      20:              // try configure the standard way
      21:              L4N.Config.XmlConfigurator.Configure();
      22:   
      23:              // is log4net configured? 
      24:              if (L4N.LogManager.GetRepository().Configured)
      25:                  return; // we are finished
      26:   
      27:              // when not set log4net config from internal setup
      28:              string name = "StaticLogWrapper.Log4NetConfig.xml";
      29:              Stream objStream = Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
      30:              L4N.Config.XmlConfigurator.Configure(objStream);
      31:              objStream.Close();
      32:          }
      33:          
      34:          ...

    Siebte Ausgabe des .NET BlogBook erschienen

    Nachdem der letzte Termin für eine neue Ausgabe des .NET BlogBook verstrichen ist, ohne dass der Community eine überarbeitete Version überlassen wurde, ist gestern am 15.10. die nunmehr siebte Ausgabe erschienen.
    Zugegeben, ganz korrekt ist die gerade getroffene Aussage nicht. Denn eine der angekündigten Veränderungen ist die Trennung von Themengebieten in eigene Dateien. Dadurch werden wird also im Prinzip drei BlogBooks bekommen, als da wären:

    • .NET Core
    • ASP.NET
    • Windows Presentation Foundation

    Bisher ist leider erst der WPF-Teil erschienen, die anderen beiden Teile sollen jedoch, laut Norbert Eder,  "im Laufe der kommenden Tage und der nächsten Woche nachgeliefert".

    Die Trennung ist nicht die einzige Änderung, die Einzug gehalten hat.
    Weiterhin wurde das Layout angepasst, um die Lesbarkeit sowie die Qualität von Druckerausgaben zu erhöhen. Auch neue Einträge wurden natürlich hinzugefügt.

    Die Idee der Aufteilung der Themengebiete halte ich für ausgesprochen gut. Die Bereiche WPF und ASP.NET sind zwar durchaus sehr interessante Bereiche von .NET, allerdings spielen diese in meinem täglichen Umgang mit dem Framework eine sehr geringe bis nicht vorhandene Rolle. Da kommt es mir natürlich gerade recht, ein eigenes Dokument für ".NET Core" zur Verfügung zu haben.

    Eine Verbesserung in Sachen Layout ist natürlich immer zu begrüßen, wenn es denn tatsächlich eine Verbesserung ist. Das ist im vorliegenden Fall meiner Meinung aber auf jeden Fall gegeben.

    Insgesamt begrüße ich die Änderungen, so weit ich sie jetzt bearbeitet hat. Also ein absolut positiver Schritt in der Evolution des .NET BlogBook.


    Update am 30.10.2008:
    Es steht jetzt auch der ASP.NET-Teil des Blogbooks zur Verfügung.

    Donnerstag, 9. Oktober 2008

    Strings verschlüsseln mit C# - Part 2

    Vor einiger Zeit hat chico beschrieben, wie man einen String mit C# verschlüsseln kann. Leider hatte der Beitrag den kleinen Schönheitsfehler, dass die Methode zur Verschlüsselung ein Byte-Array zurückgeliefert hat. Für manche Situationen mag das durchaus ausreichend sein, doch wenn man den verschlüsselten String beispielsweise in einer Datenbank ablegen möchte, wird man mit dem Byte-Array vermutlich nicht weit kommen. Daher möchte ich heute, aufbauend auf dem ersten Artikel zur Thematik, erläutern, wie man statt dem Byte-Array einen String zurückliefern kann.

    Auch hier müssen zuerst wieder ein Schlüssel sowie ein Initialisierungsvektor angelegt werden.

       1:  private readonly byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
       2:      13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
       3:  private readonly byte[] iv = new byte[] { 65, 110, 68, 26, 69, 178, 200, 219 };

    Die Methode zur Verschlüselung sieht sich ebenfalls noch ziemlich ähnlich. Es wurde lediglich eine Zeile geändert, eine neue kam hinzu.

       1:  /// <summary>
       2:  /// Verschlüsselt einen Eingabestring.
       3:  /// </summary>
       4:  /// <param name="input">Der zu verschlüsselnde String.</param>
       5:  /// <returns>Byte-Array mit dem verschlüsselten String.</returns>
       6:  public string StringVerschluesseln(string input)
       7:  {
       8:      try
       9:      {
      10:          // MemoryStream Objekt erzeugen
      11:          MemoryStream memoryStream = new MemoryStream();
      12:   
      13:          // CryptoStream Objekt erzeugen und den Initialisierungs-Vektor
      14:          // sowie den Schlüssel übergeben.
      15:          CryptoStream cryptoStream = new CryptoStream(
      16:          memoryStream, 
      17:          new TripleDESCryptoServiceProvider().CreateEncryptor(this.key, this.iv),
      18:          CryptoStreamMode.Write);
      19:   
      20:          // Eingabestring in ein Byte-Array konvertieren
      21:          byte[] toEncrypt = new ASCIIEncoding().GetBytes(input);
      22:   
      23:          // Byte-Array in den Stream schreiben und flushen.
      24:          cryptoStream.Write(toEncrypt, 0, toEncrypt.Length);
      25:          cryptoStream.FlushFinalBlock();
      26:   
      27:          // Ein Byte-Array aus dem Memory-Stream auslesen
      28:          byte[] encrypted = memoryStream.ToArray();
      29:   
      30:          // Stream schließen.
      31:          cryptoStream.Close();
      32:          memoryStream.Close();
      33:   
      34:          // Konvertierung in Base64-String
      35:          string encryptedString = Convert.ToBase64String(encrypted);
      36:   
      37:          // Rückgabewert.
      38:          return encryptedString;
      39:      }
      40:      catch (CryptographicException e)
      41:      {
      42:          Console.WriteLine(string.Format(
      43:              CultureInfo.CurrentCulture,
      44:              "Fehler beim Verschlüsseln: {0}", 
      45:              e.Message));
      46:   
      47:          return null;
      48:      }
      49:  }

    Die Änderung finden wir in Zeile 21, statt ASCIIEncoding wird jetzt Encoding.UTF8 verwendet. Hinzugekommen ist Zeile 35. Hier wird das ermittelte Byte-Array in einen Base64String umgewandelt, der dann auch zurückgegeben wird.
    Genau wie in der Verschlüsselungs-Methode ändert sich auch in ihrem Pendant wenig.

       1:  /// <summary>
       2:  /// Entschlüsselt einen String aus einem Byte-Array.
       3:  /// </summary>
       4:  /// <param name="data">Das verscghlüsselte Byte-Array.</param>
       5:  /// <returns>Entschlüsselter String.</returns>
       6:  public string StringEntschluesseln(string data)
       7:  {
       8:      try
       9:      {
      10:          // Verschluesselten Base64String in Byte-Array konvertieren
      11:          byte[] encrypted = Convert.FromBase64String(data);
      12:   
      13:          // Ein MemoryStream Objekt erzeugen und das Byte-Array
      14:          // mit den verschlüsselten Daten zuweisen.
      15:          MemoryStream memoryStream = new MemoryStream(encrypted);
      16:   
      17:          // Ein CryptoStream Objekt erzeugen und den MemoryStream hinzufügen.
      18:          // Den Schlüssel und Initialisierungsvektor zum entschlüsseln verwenden.
      19:          CryptoStream cryptoStream = new CryptoStream(
      20:          memoryStream,
      21:          new TripleDESCryptoServiceProvider().CreateDecryptor(this.key, this.iv), 
      22:          CryptoStreamMode.Read);
      23:   
      24:          // Buffer erstellen um die entschlüsselten Daten zuzuweisen.
      25:          byte[] fromEncrypt = new byte[data.Length];
      26:   
      27:          // Read the decrypted data out of the crypto stream
      28:          // and place it into the temporary buffer.
      29:          // Die entschlüsselten Daten aus dem CryptoStream lesen
      30:          // und im temporären Puffer ablegen.
      31:          cryptoStream.Read(fromEncrypt, 0, fromEncrypt.Length);
      32:   
      33:          // Den Puffer in einen String konvertieren und zurückgeben.
      34:          return Encoding.UTF8.GetString(fromEncrypt).Replace("\0", string.Empty);
      35:      }
      36:      catch (CryptographicException e)
      37:      {
      38:          Console.WriteLine(String.Format(
      39:              CultureInfo.CurrentCulture,
      40:              "Fehler beim Entschlüsseln: {0}",
      41:              e.Message));
      42:   
      43:          return null;
      44:      }
      45:  }

    Die erste Änderung findet sich - natürlich - direkt in der Signatur der Methode (Zeile 6). Entgegengenommen wird jetzt natürlich kein Byte-Array mehr, sondern ein String. Entsprechend haben wir in Zeile 11 dann die Umwandlung des Base64Strings in ein Byte-Array, das dann weiter verarbeitet wird.  Schlussendlich haben wir dann in Zeile 34 die finale Konvertierung in den Rückgabe-String. Auch hier wird statt ASCIIEncoding wieder UTF8 verwendet, schließlich ist das ja jetzt die Basis. Eine Besonerheit ist hierbei, dass am fertigen String einige "\0"s hängen. Diese müssen noch entfernt werden, was hier durch den Aufruf von Replace geschieht.

    Der jetzt zurückgegebene String entspricht wieder genau dem, der ursprünglich verschlüsselt wurde. Alles andere wäre natürlich auch inakzeptabel.

    Bleiben jetzt nur die Fragen, warum der Umstieg von ASCIIEncoding auf UTF8 sein musste und warum das Byte-Array nicht direkt in einen normalen String, sondern in einen Base64String konvertiert wird. Beides hängt damit zusammen, dass ein Aufruf von ToString() zu falschen Ergebnissen bzw. sogar zu einer Exception in Zeile 29 (beim Entschlüsseln) führt. Dies hängt offenbar damit zusammen, dass der String im Normalfall Steuerzeichen (Stichwort Backslash) enthält. Durch die gemachten Änderungen wird dies umgangen.

    Für die endgültige Lösung möchte ich chico danken, der maßgeblich an der Entwicklung beteiligt war.

    Online SourceCodeFormatter

    Da das SourceCode-Formatieren unter http://formatmysourcecode.blogspot.com/ zwar funktioniert, jedoch leider kein wirklich ansprechendes Ergebnis liefert, habe ich einmal mehr Google bemüht und tatsächlich einen Formatierer gefunden, der sehr schöne Ergebnisse liefert.

    Zu finden ist er unter http://www.manoli.net/csharpformat.

    Er formatiert C#, VB, HTML/XML/ASPX, T-SQL sowie msh und bietet die Möglichkeiten, Zeilennummern einzublenden und die Hintergründe alternieren zu lassen.

    Zur Verwendung des entstehenden HTML-Codes wird ein StyleSheet benötigt, dass von der Seite bezogen werden kann und dann in die Zielseite eingebunden werden muss. Möchte man das vermeiden, besteht aber auch die Möglichkeit, es in den HTML-Code mit einzubetten, so dass der beschriebene Schritt entfällt.

    Heraus kommt im Übrigen ein sehr übersichtlicher Quelltext, der - verglichen mit dem, was bisher hier an Code zu sehen war - sehr gut zu lesen ist. Was will man mehr?

    Mittwoch, 8. Oktober 2008

    BizTalk 2006 Error BEC2004: Validate Instance failed for schema

    warning BEC2004: Data at the root level is invalid. Line 1, position 1

    Da erstelle ich doch glatt ein XSD Schema mit dem Flatfile Schema Wizard von BizTalk2006/R2 für meinen Kollegen, schick es ihm rüber und es funktioniert nicht...

    Noch einmal getestet bei mir, geht immer noch, bei ihm... nicht...

    Also hingesetzt bei ihm, Schema nachkreiert -> Funktioniert...

    Zu mir rübergeschickt -> geht nicht...

    WinDiff -> Kein Unterschied...

    Unterschied Kollege hat 64Bit Betriebssystem ich 32Bit, also Files in einer anderen Text Codierung neu abgespeichert auf meinem 32Bitter.... Gleiches Verhalten...!

    Copy und Paste vom Inhalt des 64Bit Schemas in eine neue Datei... Gleiches Verhalten...!!!

    Nun bin ich etwas ratlos. Deutet vielleicht auf ein Problem mit Escape Zeichen hin... aber der Austausch von Escape Sequencen für Tab und CR/LF brachte auch keine Lösung.

    Äußerst kurios, zumal ich schon vorher mehrfach mit anderen Windows 2003 64Bit Systemen das gleiche tat und XSD Schemas aus einer 32Bit Entwicklungsumgebung migrierte in das dortige Projekt.


    Irgendjemand eine Idee?

    Donnerstag, 2. Oktober 2008

    SAP Adapter in Biztalk 64Bit oder "Retrieving the COM class factory for component with CLSID {XXX} failed..."

    Versucht man mit dem normalen vorgehen die SAP-Adapter für Biztalk unter einem 64Bit Windowssystem zu installieren, bekommt man so lustige Fehlermeldungen wie diese hier:Natürlich sagt diese treffend aus wo der Fehler liegt (Ha, HA!). Der Fehler liegt einfach darin das der SAP-Adapter seinen Dienst nur auf 32Bit Systemen nachgeht und auf 64Bit Systemen einfach seine DLLs nicht findet. Um das zu beheben muss man nach der Installation (SAP-Connector und SAP-Adapter) dem SAP Adapter expliziet eine 32Bit Umgebung zuweissen. Dazu legt manin der Biztalk Administration Console unter "Platform Settings/Hosts" einen neuen Host an und konfiguriert diesen auf 32Bit.

    Danach noch das ganze im SAP Adapter zuweissen (Send und Receive) und siehe da, es läuft.
    Jetzt nur nicht vergessen den Host zu restarten ;)

    Mittwoch, 1. Oktober 2008

    .NET Framework Client Profile

    Mit dem Service Pack 1 für das .NET Framework 3.5 und Visual Studio 2008 kam das Client Profile. Dieses ist dafür gedacht, dass bei der Verteilung einer Anwendung auf Basis von WinForms bzw. XAML auf einem System nicht das komplette .NET Framework 3.5 SP1 installiert werden muss. Es wird nur ein Bruchteil vom Framework installiert, der für Standardaufgaben ausreichend ist. Klingt nach einer sehr guten Idee, denn so ist es nicht mehr nötig,  die Installation mitzuliefern oder bei der Installation herunterzuladen. Daumen hoch für die Idee.

    Leider sieht die Praxis etwas weniger optimal aus, denn das Client Profile kommt ausschließlich unter Windows XP zum Zug und das auch nur dann, wenn bisher noch keine Version des Frameworks auf dem System installiert ist. Zudem kann es nicht verwendet werden, wenn der Rechner auf der x64- bzw. ia64-Plattform basiert. In all diesen Fällen wird das volle Framework 3.5 SP1 installiert!

    Der Prozentsatz von Systemen, die genau die Anforderungen erfüllen, die vom Client Profile gefordert werden, dürfte heutzutage reichlich gering sein, wenn man bedenkt, dass jeder Rechner, auf dem Vista läuft, schon mal außen vor bleibt, weil hier standardmäßig bereits eine Framework-Version installiert ist.

    Die an sich sehr gute Idee wird durch die Einschränkungen meiner Ansicht nach ad absurdum geführt. In dieser Art ist das Client Profile, jedenfalls für mich, von keinerlei Nutzen. Schade um den wirklich guten Ansatz. Bleibt zu hoffen, dass Microsoft hier in Zukunft (.NET Framework 4 regt sich ja bereits) nachbessern wird.