2010-03-10 3 views
6

Ich arbeite an der Neuentwicklung eines Access basierten Systems in C# .net, aber wenn MS von Office 2003 zu Office 2007 ging, entfernten sie den Bildeditor innerhalb des Zugriffs - welcher bedeutete, dass zuvor gespeicherte Bilder nicht mehr im System angezeigt werden. Die Leute bei der Firma haben einen Hack gemacht, der im Grunde die Bilder mit VBA mit Excel im Hintergrund gespeichert hat (ich kann mehr Informationen bekommen, wenn Sie es brauchen), aber im Grunde bedeutete das, dass die Zugriffsbildkontrollen immer noch benutzt werden konnten (Object bound frames).Konvertierung eines OLE Image Objekts aus MS Access für .NET

Allerdings habe ich jetzt das Problem zu versuchen, diese in .NET-Anwendungen anzuzeigen, und nach unzähligen Tagen des Ausprobierens verschiedener Möglichkeiten der Manipulation der Byte-Array bin ich kurz davor aufzugeben. Ich habe mindestens 8 verschiedene Lösungsvorschläge ausprobiert und jede endet mit einer 'Parameter nicht erkannt' Ausnahme, wenn ich Image.fromStream() mache. Unten ist der Code, der ich am nächsten so weit gekommen ist:

private void imageExtractTest() 
    { 
     LogOnDataSetTableAdapters.QueriesTableAdapter qa = 
      new LogOnDataSetTableAdapters.QueriesTableAdapter(); 

     object docO = qa.GetLogonImage(); 
     if (docO == null || !(docO is byte[])) 
     { 
      return; 
     } 
     byte[] doc = (byte[])docO; 

     MemoryStream ms = new MemoryStream(); 
     ms.Write(doc, 0, doc.Length); 
     int firstByte; 
     int secondByte; 
     ms.Seek(0, SeekOrigin.Begin); 
     firstByte = ms.ReadByte(); 
     secondByte = ms.ReadByte(); 

     if (firstByte != 0x15 && secondByte != 0x1C) 
     { 
      //ErrorResponse("Stored object is not an Access File."); 
      return; 
     } 

     int fileTypeLoc = 20; // begin of the file type 
     short offset; // end of the file type 

     byte[] buffer = new byte[2]; 
     ms.Read(buffer, 0, 2); 
     offset = BitConverter.ToInt16(buffer, 0); 

     long seekTotal = 0; 
     seekTotal += offset; 

     string docType = String.Empty; 
     for (int i = fileTypeLoc; i < offset; i++) 
     { 
      docType += (char)doc[i]; 
     } 

     //if I query docType now I get 'Picture\0\0' 

     // magic eight bytes 01 05 00 00 03 00 00 00 
     ms.Seek(seekTotal, SeekOrigin.Begin); 
     buffer = new byte[8]; 
     ms.Read(buffer, 0, 8); 
     seekTotal += 8; 

     // Second offset to move to 
     buffer = new byte[4]; 
     ms.Read(buffer, 0, 4); 
     seekTotal += 4; 
     long offset2 = BitConverter.ToInt32(buffer, 0); 
     seekTotal += offset2; 
     ms.Seek(seekTotal, SeekOrigin.Begin); 

     // eight empty bytes 
     buffer = new byte[8]; 
     ms.Read(buffer, 0, 8); 
     seekTotal += 8; 

     // next n bytes are the length of the file 
     buffer = new byte[4]; 
     ms.Read(buffer, 0, 4); 
     seekTotal += 4; 
     long fileByteLength = BitConverter.ToInt32(buffer, 0); 

     // next N bytes are the file 
     byte[] data = new byte[fileByteLength]; 

     // store file bytes in data buffer 
     ms.Read(data, 0, Convert.ToInt32(fileByteLength)); 

     MemoryStream imageStream = new MemoryStream(data); 
     Image test = Image.FromStream(imageStream); 
    } 

Dieser Code wurde von here angepasst, habe ich nicht die verschiedene doctypes Identifizierung benötigen, da ich nur mit Bildern zu tun habe, aber die Art Bild könnte sei eine beliebige Anzahl von Dingen - jpg, bmp, gif, png etc.

Ich habe auch versucht, die ausgegebene Byte-Array zu speichern, aber ich hatte kein Glück, das entweder zu sehen. Aber wenn ich auf die Datenbank zugreife und sie zur Ansicht bringe, ist alles in Ordnung. Auch der .NET Crystal Report Designer ist in der Lage, diese Bilder zu erhalten - so müssen sie irgendwo da sein ...

Hat jemand irgendwelche Ideen?

Marlon

Antwort

3

Der Versuch von .NET eine MS-Access-OLE Bildfeld abzurufen ist weit mehr Kopfschmerzen als es wert ist. Es gibt einige gute Diskussionen und Informationen zu diesem Thema in this post.

Letztendlich ist Ihre beste und einfachste Lösung, mit dieser Methode erfolgreich zu sein, Ihre Arbeitsansichtsmethode zu verwenden, um diese Bilder als separate Dateien zu speichern und diese Dateien dann als BLOB-Felder in die Datenbank zu importieren. Dann können Sie sie leicht in .NET lesen.

0

Versuchen Sie diese KB http://support.microsoft.com/kb/317701 Artikel von Microsoft. Es enthält Informationen darüber, wie auf das Image-Blob vom Zugriff aus zugegriffen werden kann und das in winforms-Anwendung angezeigt wird.

+0

danke für die Info, aber ich denke, Sie missverstehen das Problem. In diesem Artikel wird nur erläutert, wie eine Bilddatei in einer Datenbank gespeichert wird. Nicht, wie ein bereits gespeichertes OLE-Objekt in ein Bild konvertiert wird. Anscheinend ist OLE einfach magisch ... – Marlon

0

Es ist nicht C# -Code, aber hier ist ein Delphi example von einer Möglichkeit, dieses Problem zu lösen.

Es verwendet die IOLEObject, um zu zeichnen, was gespeichert ist, anstatt zu versuchen, die Rohdaten auszulesen. Schritte:

  1. Lesen Sie die Access-Header vor dem OLE-Objekt
  2. den OLE1 Strom
  3. den OLE1 Strom
  4. Verwenden OLELoad auf ein OLE2 IStorage Objekt konvertieren Vorlesen auf "run" der OLE Ojekte.
  5. Rufen Sie OLEDraw an, um das Bild auf eine Leinwand Ihrer Wahl zu ziehen.
1

In meinem Fall funktionierte die folgende Funktion. Die Daten werden von einer VB6-Anwendung gespeichert.

public static byte[] ConvertOleBytesToRawBytes(byte[] oleBytes) 
{ 
    // The default encoding is in my case - Western European (Windows), Code Page 1252 
    return Encoding.Convert(Encoding.Unicode, Encoding.Default, (byte[])oleBytes); 
}