VisualBasic Ressourcen Dateien verwenden

Karkand_medic

Cadet 4th Year
Registriert
Mai 2011
Beiträge
66
Hallo CBler,

ich bin gerade dabei ein Hilfsprogramm in VB zu erstellen und verwende dabei zum ersten mal Ressourcen. Sollte ich vielleicht generell in eine falsche Richtung unterwegs sein und es gibt bessere Ansätze, bitte immer her damit ;-)

Aufgabe:
Ich erstelle mit Visual Studio 2019 eine Windows Form Anwendung in VB. Diese soll einen Foliensatz mit mit einer Powerpointvorlagendatei (.potx) öffnen, diese dann modifizieren (u.a. selektiv Bilder einfügen) und als neue Datei abspeichern.

In einer ersten Version habe ich neben der .exe einfach eine Ordnerstruktur gehabt mit /content/images und /content/sampleslides auf die ich dann über einen Pfad zugegriffen habe. Funktioniert an sich gut, es bietet aber leider immer die Möglichkeit, dass Kollegen die das Tool verwenden diese Dateien modifizieren/verschieben und es dann deswegen natürlich nicht mehr läuft.

Jetzt bin ich auf Ressourcendateien gestoßen mit denen es meiner Auffassung nach möglich sein soll die Dateien mit in die .exe zu packen und damit eine kompaktere/weniger fehleranfällige Lösung zu erhalten.

Einen Teil habe ich schon gelöst indem ich die .potx Datei als Ressource aufgenommen habe, diese dann im Code auf die HDD schreibe (siehe Codezeile), per Link dann verwende und anschließend wieder lösche.

Code:
IO.File.WriteAllBytes(path + "\Beispielfolien.potx", My.Resources.Resource1.Beispielfolien)

Klappt auch gut.
Problematisch wird es jetzt bei den Bildern. Ich habe 17 Bilddateien, sowohl .bmp als auch .png die ich auch "mitverpacken" möchte.
Da funktioniert nur leider das schreiben auf die HDD nicht und ich kann sie auch nicht anders aufrufen.

Mein Code für den Fall dass das Bild auf der HDD liegt und ich es verwende sieht beispielsweise so aus:

Code:
oSlide.Shapes.AddPicture(path + "\content\images\Hintergrundbeleuchtung.bmp", False, True, 325, 260, 250, 240)

Kann mir jemand eine Möglichkeit nennen, wie ich die Bilder als Ressourcen einbinden und dann auf diese Art verwenden kann?

Vielen Dank gleich mal und falls ich wichtige Infos vergessen habe bitte fragen :)
 
Karkand_medic schrieb:
Da funktioniert nur leider das schreiben auf die HDD nicht und ich kann sie auch nicht anders aufrufen.

Das müsstest du genauer erläutern. Was genau Funktioniert nicht. Wie versuchst du sie zu speichern. Gibts ne Exception?
 
Wenn ich die folgende Zeile eintippe (analog zum Schreiben der .potx):

Code:
IO.File.WriteAllBytes(path + "\Hintergrundbeleuchtung.bmp", My.Resources.Resource1.Hintergrundbeleuchtung)

wird sofort der letzte Ausdruck rot unterwellt und wenn ich mit der Maus darüber fahre kommt die Anmerkung:
Der Wert vom Typ "Bitmap" kann nicht in "Byte()" konvertiert werden.

Beim Kompilieren kommt dann ein Error mit Code BC30311
Fehler BC30311 Der Wert vom Typ "Bitmap" kann nicht in "Byte()" konvertiert werden.

Bei .png Dateien kommt exakt die selbe Meldung. Bilder haben da anscheinend eine Sonderstellung. Was ich nicht ganz verstehe, im Endeffekt sind es ja auch nur Dateien aus Bits und Bytes.
 
Zuletzt bearbeitet: (Fehlermeldung und Code hinzugefügt)
Code:
Hintergrundbeleuchtung.bmp

Als Objekt bzw fso instanziert?
Ergänzung ()

Karkand_medic schrieb:
Bei .png Dateien kommt exakt die selbe Meldung. Bilder haben da anscheinend eine Sonderstellung. Was ich nicht ganz verstehe, im Endeffekt sind es ja auch nur Dateien aus Bits und Bytes.

Jein. Viele Dateiformate sind dem Complier bekannt und er weiß, dass er diese in seiner Prozedur nur als Object behandeln kann. Dann instanziert er diese automatisch als object bzw fso. Bilder wiederum könnten im Prozeduraufruf auch anderweitig verwendet werden (als Hintergrund geladen etc). Daher musst Du ihm explizit in der Funktion mitteilen, dass du das Bild gerade als Object bzw FSO in die Exe integrieren möchtest.

Gerade da du eben dieses Object (Hintergrund.bmp) ja auch später wirklich verwendest, kann der Compiler unmöglich das Bild global als FSO (=Datei) oder als Bild (bekanntes Format für Verwendung innerhalb VB) instanzieren. Soweit ist das eigentlich logisch. Wenn Du verschiedene Verwendungen für ein Object / String whatever, innerhalb eines Programms hast, musst Du die zwangsläufig per Funktion deklarieren / instantiieren, so wie Du es an der Stelle brauchst.

So zumindest mein Ansatz.
 
Zuletzt bearbeitet:
Das habe ich gerade nachgezogen:

Code:
 Dim Image1 As Object
Image1 = My.Resources.Resource1.Auflicht
IO.File.WriteAllBytes(path + "\Bauteil2.png", Image1)

Beim Kompilieren lief alles gut, aber wenn ich es dann ausführe kommt eine Exception:
System.InvalidCastException: "Das Objekt des Typs "System.Drawing.Bitmap" kann nicht in Typ "System.Byte[]" umgewandelt werden."

Ich muss sagen dieses "Datei erstmal auf die HDD schreiben" ist ja auch nur ein Workaround, am liebsten wäre es mir ich könnte es direkt aus den Ressourcen in den Befehl füttern. Die Dateien brauchen aus keinem anderen Grund gespeichert zu werden.

Code:
oSlide.Shapes.AddPicture(path + "\content\images\Hintergrundbeleuchtung.bmp", False, True, 325, 260, 250, 240)

So etwas in der Art wäre natürlich ideal:

Code:
path = "My.Resources.Resource1.smartcam.png"
oSlide.Shapes.AddPicture(path, False, True, 375, 185, 100, 75)

Aber das liefert leider:
System.ArgumentException: "Die angegebene Datei wurde nicht gefunden."

Aber da wird es auch keinen Weg geben oder?
 
Zuletzt bearbeitet:
Karkand_medic schrieb:
Die Dateien brauchen aus keinem anderen Grund gespeichert zu werden.

Ne, das nicht. Aber schau:

Du hast Hintergrund.bmp einmal als Datei (Object / FSO), da du es ja als Datei in der Exe ablegen möchtest.
Weiter im Code wirst Du ja irgendwann eben dieses Bild effektiv laden (=als Bild vearbeiten) dort würde der Compiler also Hintergrund.bmp in der Picture-Klasse verorten. Daher musst du es jeweils manuell deklarieren. Der Compiler sieht verschiedene Aufrufarten und kann daher keine globale Instanzierung setzen.

System.Drawing.Bitmap
könnte ein Hinweis darauf sein, dass er es an der Stelle trotzdem wieder als Picture, nicht als FSO behandelt. Soweit ich das in Erinnerung habe, musst Du FSO nutzen damit er das Bild wirklich als Datei und nicht als Bild behandelt. Dann kann er das auch umwandeln.

Aber ohne Gewähr. Ansonsten schau doch mal bei stackoverflow.

Ich hätte allerdings ne Idee für nen quick & dirty workaround.

Benenn die Datei in irgendwas um. ".abcd". Der Compiler identifiziert die Datei als Bild aufgrund ihrer Endung. Das ist Start des Problems, da er das BIld ab dort offensichtlich als Bild und nicht als Datei behandelt.

Lösung Quick & Dirty:
Dateiendung umbenennen (.abcd) / in der Exe speichern (.abcd) / aus der Exe laden (.abcd) / wieder in .bmp umbenennen / verwenden.
 
Ich habe jetzt nochmal auf stackoverflow geschaut und tatsächlich etwas passendes gefunden:

Code:
My.Resources.Resource1.Auflicht.Save("Auflicht.bmp")

Macht genau was man erwartet (speichert die Bilddatei in das Verzeichnis der .exe) und löst damit auch mein Problem. Ich bau mal alles entsprechend um und gebe dann Bescheid ob es wie geplant läuft :)

Update:

Es ist jetzt wirklich alles gelöst und läuft so wie gewünscht.
Kurze Zusammenfassung falls jemand mal ein ähnliches Problem hat:

Ich habe eine .potx Datei und mehrere Bilder als eingebettete Ressourcen in meine Anwendung integriert. Damit gibt's eine (größere) .exe die einfacher zu nutzen und zu verteilen ist.

Mit dem ersten Befehl kann ich (Nicht Bild-)Dateien aus der Ressource im Verzeichnis der .exe abspeichern. Mit dem zweiten dann ein Bild:

Code:
IO.File.WriteAllBytes(path + "\Beispielfolien.potx", My.Resources.Resource1.Beispielfolien)
My.Resources.Resource1._1.Save("1.png")

Die Dateien verwende ich dann über ihren Link in meinem Programm und nach Ablauf der Aktionen lösche ich sie einfach wieder:

Code:
IO.File.Delete(path + "\Beispielfolien.potx")
IO.File.Delete(path + "\1.png")

Problem gelöst, danke für die Mithilfe :)
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Sun_set_1
Zurück
Oben