Kurztipp: HTTP-URLs in Windows Explorer öffnen

Manchmal ist es nützlich, zu wissen, dass Ihr in Windows Explorer (also nicht Internet Explorer) direkt HTTP-URLs eingeben könnt.

Also z.B. im Datei-Öffnen-Dialogfenster.

Anwendungszenario – Internet-Bild lokal bearbeiten

Wollt Ihr z.B. ein tolles Bild aus dem Internet lokal bearbeiten, so ist der übliche Weg:

  1. Webbrowser starten. (Also Google Chrome, was sonst)
  2. URL der Seite öffnen, auf der das Bild enthalten ist.
  3. Rechtsklick auf das Bild.
  4. „Speichern unter“ auswählen.
  5. Lokales Zeichenprogramm starten (Also Paint.NET).
  6. Datei-Öffnen-Dialogfenster anzeigen lassen.
  7. Das vorher heruntergeladene Bild suchen und öffnen.

Mit dem Wissen, dass das auch direkt in Windows Explorer geht (vermutlich über den eingebauten WebDAV-Client), könnt Ihr diese Prozedur abkürzen:

  1. Lokales Zeichenprogramm starten.
  2. Datei-Öffnen-Dialogfenster anzeigen lassen.
  3. URL des Bildes eingeben und direkt öffnen.

Hat mir schon oft geholfen, ggf. ist das auch für Euch mal nützlich. Funktioniert auch prima, wenn Ihr auf einer Seite ein Bild downloaden möchtet um es auf einer anderen Seite upzuloaden.

Geht natürlich mit beliebigen Dateien (z. B. PDF), nicht nur Bildern.

GDI+-Fehler 7 (Gdiplus::Win32Error) beim Speichern eines Bilds das aus der Zwischenablage gelesen wurde

Beschreibung

Gerade habe ich folgendes Phänomen erlebt:

Beim Speichern eines GDI+-Bilds (Image– bzw. Bitmap-Klasse) bekam ich einen Statuscode 7 zurückgeliefert, was die Fehlermeldung „Win32Error“ bedeutet.

Also wie bei den meisten GDI+-Fehlermeldungen völlig ungenau und völlig an der wahren Ursache vorbei.

Da ich das ganze im Debugger laufen ließ und dieser bei First-Chance-Exceptions anhält, sah ich die genaue Stelle wo zum ersten Mal ein Fehler auftritt. Nämlich eine Zugriffsverletzung („Access violation“, 0x00000005) innerhalb von GDI+ an der folgenden Stelle im Aufrufstapel:

Bzw. als Textversion:

GdiPlus.dll!GpJpegEncoder::PushPixelData() + 0xa5	
GdiPlus.dll!GpMemoryBitmap::PushIntoSink() + 0x14b	
GdiPlus.dll!GpMemoryBitmap::SaveToStream() + 0xa1	
GdiPlus.dll!GpMemoryBitmap::SaveToFile() + 0x39	
GdiPlus.dll!CopyOnWriteBitmap::DoSave() + 0x206	
GdiPlus.dll!CopyOnWriteBitmap::SaveToFile() + 0x15	
GdiPlus.dll!GpBitmap::SaveToFile() + 0x1f	
GdiPlus.dll!_GdipSaveImageToFile@16() + 0x5f	
zlzdiud.dll!Gdiplus::Image::Save() Zeile 140 + 0x18

Das Bild habe ich aus der Zwischenablage geholt (Zwischenablagenformat CF_DIB) und dann über die Funktion Bitmap::FromBITMAPINFO() ein Bitmap-Objekt daraus gemacht.

Ursache

Nach einigen Tests habe ich herausgefunden, woran es lag:

Sobald ich den Speicher freigegeben hatte, der die Daten aus der Zwischenablage gespeichert hat (ein Instanz der MFC-Klasse CByteArray), schlug der Aufruf von Image::Save() mit oben genannter Fehlermeldung fehl; habe ich den Speicher erst nach dem Aufruf von Image::Save() freigegeben, verlief das Speichern erfolgreich.

Die Ursache ist also (wiedermal) wie bei den meisten GDI+-Routinen: Ich muß selbst dafür sorgen, daß ich den Speicher, aus dem ein ein Bitmap-Objekt erstellt wurde, lange genug reserviere, weil GDI+ sich das nicht selbst in interne Puffer kopiert.

Ist für ehrlich gesagt teilweise ggf. verständlich (Performance, Flexibilität), aber sehr unintuitiv (Komfort)!

Lösung

Den Speicher für ein Bitmap-Objekt, das aus einem Aufruf via Bitmap::FromBITMAPINFO() (oder entsprechend anderer Funktionen) erstellt wurde, muß während der gesamten Lebensdauer des Bitmap-Objekts gültig sein und von der benutzenden Anwendung reserviert bleiben.