Autor Beitrag
Icarus666
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mi 18.01.06 21:32 
Hallo erstmal.

Ich habe folgendes Problem:
Ich habe eine Klasse, die ein kleines Bildchen und eine Beschreibung speichert. Mehrere dieser Objekte sollen u.a. in einer XML-Datei gespeichert werden und daraus wieder gelesen werden.

Also so:

Klasse HistoryType
Member:
string Description
Image Icon

Hier erstmal der Code:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
public ArrayList Types

public void LoadXML(string FileName)
{
  XmlDocument XmlDoc = new XmlDocument();
  try {
    XmlDoc.Load(FileName);
  }
  catch (Exception ex) {
    MessageBox.Show("Fehler beim Öffnen der XML-Datei (" + FileName + "): " + 
      ex.Message, Application.ProductName, MessageBoxButtons.OK, 
      MessageBoxIcon.Error);
    return;
  }
  XmlNode DocNode = XmlDoc.DocumentElement;
  foreach (XmlNode ProgramNode in DocNode.ChildNodes) {
    if (ProgramNode.Name == "Name"
      this.Name = ProgramNode.InnerText;
    if (ProgramNode.Name == "Description"
      this.Description = ProgramNode.InnerText;
    if (ProgramNode.Name == "Types") {
      foreach (XmlNode TypeNode in ProgramNode.ChildNodes) {
        HistoryType HT = new HistoryType();
        HT.Description = TypeNode.Attributes["Description"].InnerText;
        byte[] Buffer = Convert.FromBase64String(TypeNode.Attributes["Icon"].InnerText);
        MemoryStream ImageStream = new MemoryStream(Buffer);
        Bitmap img = new Bitmap(ImageStream);
        HT.Icon = img;
        ImageStream.Close();
        this.Types.Add(HT);
      }
    }
  }
}
    
public void SaveXML(string FileName)
{
  XmlTextWriter w;
  try {
    w = new XmlTextWriter(FileName, Encoding.UTF8);  
  }
  catch (Exception ex) {
    MessageBox.Show("Fehler beim Öffnen der XML-Datei (" + FileName + "): " + 
      ex.Message, Application.ProductName, MessageBoxButtons.OK, 
      MessageBoxIcon.Error);
    return;
  }
  w.Formatting = Formatting.Indented;
  w.Indentation = 2;
  w.IndentChar = ' ';
  w.WriteStartDocument(true);
  w.WriteStartElement("Program");
  w.WriteElementString("Name"this.Name);
  w.WriteElementString("Description"this.Description);
  w.WriteStartElement("Types");
  
// TEST:
// HistoryType H = new HistoryType();
// H.Icon = Image.FromFile("BugFix.bmp");
// this.Types.Add(H); 

  w.WriteAttributeString("Count", Convert.ToString(this.Types.Count));
  for (int i = 0; i < this.Types.Count; i++) {
    w.WriteStartElement("Type");
    w.WriteAttributeString("Description"this.Types[i].Description);
    MemoryStream ImageStream = new MemoryStream();
    this.Types[i].Icon.Save(ImageStream, this.Types[i].Icon.RawFormat);  // <====
    byte[] Buffer = new byte[ImageStream.Length];
    Buffer = ImageStream.ToArray();
    w.WriteAttributeString("Icon", Convert.ToBase64String(Buffer));
    w.WriteEndElement();
  }
  w.WriteEndElement();
  w.WriteEndDocument();
  w.Close();
}


Wenn ich in SaveXML die Kommentarstriche bei TEST wegmache wird das Bitmap einwandfrei geladen und in die XML-Datei wie geplant abgespeichert.

Ich kann dann mit LoadXML die Objekte auch wieder korrekt einlesen, jedoch lässt sich dann die Datei nicht mehr mit SaveXML abspeichern.
Das Programm stoppt dort wo der Pfeil ist, mit der Fehlermeldung "Exception System.Runtime.InteropServices.ExternalException was thrown in debugee:
A generic error occurred in GDI+."

So langsam gehen mir die Ideen aus.
Icarus666 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Do 19.01.06 21:05 
Titel: Lösung
Hallo nochmal.
Wen's interessiert: Ich denke ich habe die Lösung des Problems gefunden. Und zwar auf der M'soft Support-Seite:

SYMTOMS
When either a Bitmap object or an Image object is constructed from a file, the file
remains locked for the lifetime of the object. As a result, you cannot change an image and
save it back to the same file where it originated.
Additionally, if the stream was destroyed during the life of the Bitmap object, you cannot successfully access an image that
was based on a stream. For example, the Graphics.DrawImage() function may not succeed after the stream has been
destroyed.

CAUSE
GDI+, and therefore the System.Drawing namespace, may defer the decoding of raw image bits until the bits are required
by the image. Additionally, even after the image has been decoded, GDI+ may determine that it is more efficient to discard
the memory for a large Bitmap and to re-decode later. Therefore, GDI+ must have access to the source bits for the image for
the life of the Bitmap or the Image object.
To retain access to the source bits, GDI+ locks any source file, and forces the application to maintain the life of any source
stream, for the life of the Bitmap or the Image object.

SOLUTION

Hier mal meine Lösung:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
public void LoadXML(string FileName)
{
  XmlDocument XmlDoc = new XmlDocument();
  try {
    XmlDoc.Load(FileName);
  }
  catch (Exception ex) {
    MessageBox.Show("Fehler beim Öffnen der XML-Datei (" + FileName + "): " + 
      ex.Message, Application.ProductName, MessageBoxButtons.OK, 
      MessageBoxIcon.Error);
    return;
  }
  XmlNode DocNode = XmlDoc.DocumentElement;
  foreach (XmlNode ProgramNode in DocNode.ChildNodes) {
    if (ProgramNode.Name == "Name"
      this.Name = ProgramNode.InnerText;
    if (ProgramNode.Name == "Description"
      this.Description = ProgramNode.InnerText;
    if (ProgramNode.Name == "Types") {
      foreach (XmlNode TypeNode in ProgramNode.ChildNodes) {
        HistoryType HT = new HistoryType();
        HT.Description = TypeNode.Attributes["Description"].InnerText;
        byte[] Buffer = Convert.FromBase64String(TypeNode.Attributes["Icon"].InnerText);
        MemoryStream ImageStream = new MemoryStream(Buffer);
        Bitmap img = Image.FromStream(ImageStream);
        // Start Workaround
        Image img2 = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppRgb);
        Graphics g = Graphics.FromImage(img2);
        g.DrawImage(img, new Rectangle(00, img2.Width, img2.Height));
        g.Dispose();
        img.Dispose();
        // End Workaround
        HT.Icon = img2;
        ImageStream.Close();
        this.Types.Add(HT);
      }
    }
  }
}
    
public void SaveXML(string FileName)
{
  XmlTextWriter w;
  try {
    w = new XmlTextWriter(FileName, Encoding.UTF8);  
  }
  catch (Exception ex) {
    MessageBox.Show("Fehler beim Öffnen der XML-Datei (" + FileName + "): " + 
      ex.Message, Application.ProductName, MessageBoxButtons.OK, 
      MessageBoxIcon.Error);
    return;
  }
  w.Formatting = Formatting.Indented;
  w.Indentation = 2;
  w.IndentChar = ' ';
  w.WriteStartDocument(true);
  w.WriteStartElement("Program");
  w.WriteElementString("Name"this.Name);
  w.WriteElementString("Description"this.Description);
  w.WriteStartElement("Types");
  w.WriteAttributeString("Count", Convert.ToString(this.Types.Count));
  for (int i = 0; i < this.Types.Count; i++) {
    w.WriteStartElement("Type");
    w.WriteAttributeString("Description"this.Types[i].Description);
    MemoryStream ImageStream = new MemoryStream();
    this.Types[i].Icon.Save(ImageStream, ImageFormat.Bmp);  <==== geändert
    byte[] Buffer = new byte[ImageStream.Length];
    Buffer = ImageStream.ToArray();
    w.WriteAttributeString("Icon", Convert.ToBase64String(Buffer));
    w.WriteEndElement();
  }
  w.WriteEndElement();
  w.WriteEndDocument();
  w.Close();
}
McSteel
ontopic starontopic starofftopic starofftopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 54

Win XP
VS 6.0, VS2005
BeitragVerfasst: Fr 17.02.06 11:49 
Hi Icarus666,

wir sind immer an allen Lösungen interessiert.

Vielen Dank.

SteelWarrior