Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

Hilfreiche Erklärungen und Tipps zum Lernen von Autohotkey

Moderator: jNizM

just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

13 Feb 2014, 03:35

Das Kommando FileInstall fügt beliebige Dateien in die beim Kompilieren erzeugte exe Datei ein. Normalerweise wird es dafür genutzt, diese Dateien bei der Ausführung der Anwendung in das Dateisystem zu stellen. Die Hilfe sagt dazu:
Bemerkungen

Dieser Befehl ist eine Direktive für den Ahk2Exe-Compiler, die Dir erlaubt, zusätzliche Dateien in das kompilierte Script einzufügen. Sobald das kompilierte Script ausgeführt wird, werden diese Dateien wieder auf das Laufwerk extrahiert.

Die Datei wird hinzugefügt, während das Script kompiliert wird. Sobald das kompilierte Script ausgeführt und FileInstall erreicht wird, wird die Datei ins Ziel extrahiert.

Dateien, die auf diese Weise hinzugefügt werden, sind komprimiert und auch verschlüsselt.

Wenn dieser Befehl in einem normalen (nicht kompilierten) Script verwendet wird, erfolgt stattdessen ein einfaches Kopieren der Datei (das hilft dabei, Skripts zu testen, die eventuell kompiliert werden sollen).
Wie lexikos im anderen Forum erklärt hat (siehe) gilt das für den von fincs geschriebenen aktuellen Compiler nicht mehr so ganz. Die Dateien werden weder komprimiert noch verschlüsselt, sondern unverändert als Ressourcen vom Typ RCDATA eingebunden. Außerdem ergibt sich aus
Sobald das kompilierte Script ausgeführt und FileInstall erreicht wird, wird die Datei ins Ziel extrahiert.
dass sie Dateien eben nicht extrahiert werden, wenn die Anweisung FileInstall an einer Stelle im Skript steht, die nicht ausgeführt wird. Beides zusammen schafft die Möglichkeit, Dateien in die kompilierte exe einzubinden,
  1. die nicht ins Dateisystem gestellt werden und
  2. auf die dennoch mit Hilfe der API Funktionen für Ressourcen zugegriffen werden kann.

Der Zugriff gestaltet sich relativ einfach, wenn man sich das o.a. Beispiel von lexikos anschaut. Man braucht dafür nur den im Kommando FileInstall als Parameter Quelle verwendeten Namen, der Ressourcentyp ist immer RCDATA. Ich habe das mal in die folgende Funktion gepackt (die internen Beschreibungen sind leider englisch, das sollte aber keine allzu hohe Hürde sein):

Code: Select all

; ======================================================================================================================
; FI_GetResource  Loads a resource included in a compiled script with 'FileInstall'.
; Parameters:
;     ResName     -  The name of the resource, i.e. file name as used as source parameter in 'FileInstall'.
; Return values:
;     If the resource is available, the function returns an object containing two key/value pairs:
;        Ptr      -  Pointer to the resource data.
;        Size     -  Size of data in bytes.
;     Otherwise, the return value is zero.
; Credits:
;     Adopted from a scriptlet written by lexikos
;     -> www.autohotkey.com/board/topic/76065-fileextract-fileextract-tomem-examples-for-unicode-builds/
; ======================================================================================================================
FI_GetResource(ResName) {
   ; RT_RCDATA := 10 
   If !(A_IsCompiled)
      Return False
   If (HRSRC := DllCall("Kernel32.dll\FindResource", "Ptr", 0, "Str", ResName, "Ptr", 10, "UPtr"))
   && (HRES := DllCall("Kernel32.dll\LoadResource", "Ptr", 0, "Ptr", HRSRC, "UPtr"))
      Return {Ptr: DllCall("Kernel32.dll\LockResource", "Ptr", HRES, "UPtr")
            , Size: DllCall("Kernel32.dll\SizeofResource", "Ptr", 0, "Ptr", HRSRC, "UInt")}
   Return False
}
So weit, so gut. Jetzt haben wir einen Pointer auf die Daten und die Größe in Bytes. Für viele Zwecke mag das ausreichen, um die Daten weiter zu verwenden. Wenn es aber um Bilder geht, ist das noch nicht wirklich hilfreich. Dem Himmel sei Dank hat SKAN für dieses Problem schon eine Lösung im alten Forum vorgestellt (siehe). Mit ein paar kleinen Änderungen kann man dieser ein Ressourcenobjekt aus FI_GetResource() übergeben, und schon spuckt sie ein HBITMAP oder HICON Handle aus:

Code: Select all

; ======================================================================================================================
; FI_GetImage     Gets a handle to an image included in a compiled script with 'FileInstall'.
; Parameters:
;     ImgRes      -  Resource object as returned by FI_GetResource().
;     ImgType     -  Type of the included image: 0 = Image, 1 = Icon.
; Return values:
;     Returns the handle to the image data on success; otherwise zero.
; Credits:
;     Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to Image ?" by SKAN
;     -> www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-Image/?p=139257
; ======================================================================================================================
FI_GetImage(ImgRes, ImgType := 0) {
   If !(A_IsCompiled)
      Return False
   If !IsObject(ImgRes) || (ImgRes.Ptr = "") || (ImgRes.Size = "")
      Return False
   GlData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", ImgRes.Size, "UPtr")
   Data := DllCall("Kernel32.dll\GlobalLock", "Ptr", GlData, "UPtr")
   DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", Data, "Ptr", ImgRes.Ptr, "UPtr", ImgRes.Size)
   DllCall("Kernel32.dll\GlobalUnlock", "Ptr", GlData )
   DllCall( "Ole32.dll\CreateStreamOnHGlobal", "Ptr", GlData, "Int", True, "PtrP", Stream)
   GdipHMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
   VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
   DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", GdipToken, "Ptr", &SI, "Ptr", 0)
   DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", Stream, "PtrP", Bitmap)
   If (ImgType = 0)
      DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", Bitmap, "PtrP", Image, "UInt", 0)
   Else
      DllCall("Gdiplus.dll\GdipCreateHICONFromBitmap", "Ptr", Bitmap, "PtrP", Image)    
   DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", Bitmap )
   DllCall("Gdiplus.dll\GdiplusShutdown",  "Ptr", GdipToken )
   DllCall("Kernel32.dll\FreeLibrary", "Ptr", GdipHMod)
   DllCall(NumGet(NumGet(Stream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", Stream) ; Stream::Release
   DllCall("Kernel32.dll\GlobalFree", "Ptr", GlData, "UPtr")
   Return Image
}
Zuletzt noch ein Demoskript, den Namen der Bilddatei müsst ihr anpassen, die FileInstall Anweisung steht aus gutem Grund ganz unten:

Code: Select all

#NoEnv
SS_REALSIZECONTROL := 0x40
IncludedImage := "Pic.png"
If (A_IsCompiled) {
   Gui, Margin, 20, 20
   Gui, Add, Picture, w200 h200 hwndHPIC Border AltSubmit +0xE +%SS_REALSIZECONTROL%
   Image := FI_GetResource("Pic.png")
   HIMG := FI_GetImage(Image)
   SetImage(HPIC, HIMG)
   Gui, Show, , Res Test
   Return
}
Else
   MsgBox, 0, Res Sample, Compile the script, please.
GuiClose:
ExitApp
; ======================================================================================================================
SetImage(HWND, HIMG) {
  SendMessage, 0x172, 0, HIMG, , ahk_id %HWND%
  Return (ErrorLevel = "FAIL" ? 0 : ErrorLevel)
}
; ======================================================================================================================
; FI_GetResource  Loads a resource included in a compiled script with 'FileInstall'.
; Parameters:
;     ResName     -  The name of the resource, i.e. file name as used as source parameter in 'FileInstall'.
; Return values:
;     If the resource is available, the function returns an object containing two key/value pairs:
;        Ptr      -  Pointer to the resource data.
;        Size     -  Size of data in bytes.
;     Otherwise, the return value is zero.
; Credits:
;     Adopted from a scriptlet written by lexikos
;     -> www.autohotkey.com/board/topic/76065-fileextract-fileextract-tomem-examples-for-unicode-builds/
; ======================================================================================================================
FI_GetResource(ResName) {
   ; RT_RCDATA := 10 
   If !(A_IsCompiled)
      Return False
   If (HRSRC := DllCall("Kernel32.dll\FindResource", "Ptr", 0, "Str", ResName, "Ptr", 10, "UPtr"))
   && (HRES := DllCall("Kernel32.dll\LoadResource", "Ptr", 0, "Ptr", HRSRC, "UPtr"))
      Return {Ptr: DllCall("Kernel32.dll\LockResource", "Ptr", HRES, "UPtr")
            , Size: DllCall("Kernel32.dll\SizeofResource", "Ptr", 0, "Ptr", HRSRC, "UInt")}
   Return False
}
; ======================================================================================================================
; FI_GetImage     Gets a handle to an image included in a compiled script with 'FileInstall'.
; Parameters:
;     ImgRes      -  Resource object as returned by FI_GetResource().
;     ImgType     -  Type of the included image: 0 = Image, 1 = Icon.
; Return values:
;     Returns the handle to the image data on success; otherwise zero.
; Credits:
;     Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to Image ?" by SKAN
;     -> www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-Image/?p=139257
; ======================================================================================================================
FI_GetImage(ImgRes, ImgType := 0) {
   If !(A_IsCompiled)
      Return False
   If !IsObject(ImgRes) || (ImgRes.Ptr = "") || (ImgRes.Size = "")
      Return False
   GlData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", ImgRes.Size, "UPtr")
   Data := DllCall("Kernel32.dll\GlobalLock", "Ptr", GlData, "UPtr")
   DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", Data, "Ptr", ImgRes.Ptr, "UPtr", ImgRes.Size)
   DllCall("Kernel32.dll\GlobalUnlock", "Ptr", GlData )
   DllCall( "Ole32.dll\CreateStreamOnHGlobal", "Ptr", GlData, "Int", True, "PtrP", Stream)
   GdipHMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
   VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
   DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", GdipToken, "Ptr", &SI, "Ptr", 0)
   DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", Stream, "PtrP", Bitmap)
   If (ImgType = 0)
      DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", Bitmap, "PtrP", Image, "UInt", 0)
   Else
      DllCall("Gdiplus.dll\GdipCreateHICONFromBitmap", "Ptr", Bitmap, "PtrP", Image)    
   DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", Bitmap )
   DllCall("Gdiplus.dll\GdiplusShutdown",  "Ptr", GdipToken )
   DllCall("Kernel32.dll\FreeLibrary", "Ptr", GdipHMod)
   DllCall(NumGet(NumGet(Stream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", Stream) ; Stream::Release
   DllCall("Kernel32.dll\GlobalFree", "Ptr", GlData, "UPtr")
   Return Image
}
; ======================================================================================================================
; The following line will not be executed, but processed by the compiler
FileInstall, Pic.png, Pic.png ; adjust both names to the value of 'IncludedImage'
; ======================================================================================================================
Last edited by just me on 24 Jan 2017, 09:38, edited 2 times in total.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressour

13 Feb 2014, 05:36

WOW, genau danach habe ich gesucht.
Vielen Dank!
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressour

13 Feb 2014, 08:23

Nice :D
Recommends AHK Studio
ruespe
Posts: 26
Joined: 09 Nov 2013, 04:47

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressour

26 Feb 2014, 14:02

Bravo. Gut und verständlich beschrieben. Und dann auch noch ein lauffähiges Beispiel.
Peter2
Posts: 325
Joined: 21 Sep 2014, 14:38
Location: CH

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

28 Sep 2015, 05:19

Vielen Dank - habe es jetzt (fast) hingekriegt mit #Include und zwei verschiedenen Bildtypen.

Aber: die Grössenanpassung habe ich nicht im Griff. Die Bilder sind gross - und bleiben gross, obwohl ich sie anpassen will. Wahrscheinlich habe ich irgendeinen Grundbefehl verbockt ...

Die relevanten Fragmente sind:

Code: Select all

ShowStartDialog:
    
    SS_REALSIZECONTROL := 0x40     ; erzwingt Grössenanpassung des Bildes in die Control

    Gui, new,+HwndAcadFlex,Flexstart 

    ; Tab-Struktur
    Gui -Resize -MaximizeBox Border ToolWindow
    Gui, Add, Tab2, h430 w600 , Main Settings|AutoCAD Switches|About   ; Tab2 vs. Tab requires v1.0.47.05.
    ...
    Gui, Tab, 3

    Gui,Add,Picture,  x20 y80 w580   gWebseite      vlogo  +0xE hwndHFIRMENLOGO

    ; Ausserhalb des Tabs
    ; ----
    Gui,Add,Picture,  w50  x+50 ys    +0xE    %SS_REALSIZECONTROL% hwndHPROGRAMMLOGO
Die Bilder (1 EMF, 1 PNG) erscheinen zwar im GUI, aber riesig in der Originalgrösse. Ich hatte es auch schon mit h-1 bzw. dem Wert 0x40 (statt Variable) versucht - das Bild bleibt riesig ....

Ich danke für einen Hinweis zu meinem Fehler.
Peter (AHK Beginner) / Win 10 x64, AHK Version v1.1.33
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

28 Sep 2015, 05:31

Du musst die größe definieren (w & h)
Gui, Add, Picture, x** y** w*** h***, ...
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Peter2
Posts: 325
Joined: 21 Sep 2014, 14:38
Location: CH

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

28 Sep 2015, 05:47

Das heisst, diverse Varianten wie h-1 klappen hier nicht?

BTW: Ich habe auch in der Hilfe und im Forum gesucht, was +0xE im Code heisst - war nicht erfolgreich ...

Code: Select all

Gui, Add, Picture, w200 h200 hwndHPIC Border AltSubmit +0xE +%SS_REALSIZECONTROL%
Peter (AHK Beginner) / Win 10 x64, AHK Version v1.1.33
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

28 Sep 2015, 06:14

Also soweit ich weiß nimmt man entweder
Gui, Add, Picture, w200 h200 +0xE hwndHPIC (+0x40 Passt die Bitmap auf die Größe des Steuerelements an)
oder
Gui, Add, Picture, w200 h-1 +0xE hwndHPIC
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

29 Sep 2015, 01:40

Moin,

so, wie das hier vorgestellt wurde, muss man die Größe des Controls (w... und h...) festlegen. Das sollte ja aber bei Bildern, die man selbst per FileInstall eingebunden hat, kein Problem sein. Angaben wie w-1 oder h-1 bringen hier nichts, weil die Bilder nicht per Gui... Anweisung von AHK geladen werden, und AHK deshalb die Größe der Bilder nicht kennt.

Außerdem muss man den Stil SS_BITMAP (0x0E) (bzw. SS_ICON (0x03)) setzen, der die Art des Bildes festlegt, das das Control später anzeigen soll. Wenn die Göße des Bildes nicht mit der des Controls übereinstimmt muss dem Control auch der Stil SS_REALSIZECONTROL (0x40) zugewiesen werden, allerdings mit der Option +, weil sonst der im Beispiel davor einzeln zugewiesene Stil SS_BITMAP (0x0E) sofort wieder entfernt wird. Zusammengefasst kann man auch die Kombination 0x4E (auch ohne +) zuweisen.

Alternativ (und von mir bevorzugt, weil man die volle Kontrolle über das Ergebnis hat) kann man die Bildgröße mit einem Bildeditor auf die gewünschte Größe anpassen und dann die angepassten Bilder einbinden. Dann braucht es SS_REALSIZECONTROL nicht.
highend
Posts: 47
Joined: 24 Nov 2014, 16:57

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 02:09

Wäre es auch möglich, das Ganze mit einer .dll (die dann die zugehörigen icons enthält) Datei zu benutzen, statt mit einer Liste von Grafikdateien?
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 02:24

Um Icons aus einer DLL zu laden, brauchst Du das hier gar nicht (siehe).
highend
Posts: 47
Joined: 24 Nov 2014, 16:57

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 05:57

Sicher geht das auch anders, aber nur wenn man wiederum per FileInstall die .dll auch wirklich auf dem Rechner ablegen will. Da meine momentane Applikation allerdings zwar in einem administrativ geschütztem Ordner abgelegt werden darf, selber aber nicht mit höheren Rechten laufen soll wäre eure hier vorgestellte Lösung optimal...
Peter2
Posts: 325
Joined: 21 Sep 2014, 14:38
Location: CH

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 06:05

Und was spricht dagegen, die Bilder aus der DLL zu nehmen und in die EXE zu packen und dann wie beschrieben zu verwenden?
Oder du verwendest ausser dem Programmverzeichnis noch ein Verzeichnis unter "Appdata", wo das Programm sein Zeugs hinlegen kann.
Peter (AHK Beginner) / Win 10 x64, AHK Version v1.1.33
highend
Posts: 47
Joined: 24 Nov 2014, 16:57

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 06:36

Und was spricht dagegen, die Bilder aus der DLL zu nehmen und in die EXE zu packen und dann wie beschrieben zu verwenden?
Etwa 300 FileInstall Aufrufe (~300 icons)...
Oder du verwendest ausser dem Programmverzeichnis noch ein Verzeichnis unter "Appdata", wo das Programm sein Zeugs hinlegen kann.
Sicher, das wäre das möglich. Aber bei mehreren hundert FileInstalls auch nicht gerade "super elegant" und es schränkt dann eben auch die Portabilität ein
(da das Data Verzeichnis dann getrennt im %TEMP% oder im %USERPROFILE% liegen müsste) :)

Wenn's nicht geht, dann geht's nicht. Fragen hielt ich hier aber für die sinnvollere Alternative.
Peter2
Posts: 325
Joined: 21 Sep 2014, 14:38
Location: CH

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 07:04

highend wrote:... Fragen hielt ich hier aber für die sinnvollere Alternative.
Natürlich. Ich bin hier im Forum auch vor allem ein Fragender ...

Wenn es nur um ein Programm geht würde sich die einmalige Arbeit vielleicht auszahlen - alle Bilder aus der DLL holen und dann per Fileinstall dazupacken. Oder sich das "extract" und "add" von resourehacker anschauen - dass kann man mit Batch dann automatisch beim Kompilieren auslösen.

Code: Select all

@echo off
rem ResHacker.exe  command  command_parameters
rem -add			ExeFile, SaveAsFile, ResourceFile, ResourceMask
rem -addskip		ExeFile, SaveAsFile, ResourceFile, ResourceMask
rem -addoverwrite		ExeFile, SaveAsFile, ResourceFile, ResourceMask
rem -modify			ExeFile, SaveAsFile, ResourceFile, ResourceMask
rem -extract			ExeFile, ResourceFile, ResourceMask
rem -delete			ExeFile, SaveAsFile, ResourceMask
rem ResHacker.exe -addoverwrite MyProg.exe, MyProgNew.exe, NewImage.bmp , bitmap,128,
Peter (AHK Beginner) / Win 10 x64, AHK Version v1.1.33
highend
Posts: 47
Joined: 24 Nov 2014, 16:57

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 07:24

Wenn es nur um ein Programm geht würde sich die einmalige Arbeit vielleicht auszahlen - alle Bilder aus der DLL holen und dann per Fileinstall dazupacken
Das wäre gar nicht nötig, ich hab alle .ico Dateien auch einzeln da, ich verpacke sie lediglich in eine .dll (automatisiert). 300 FileInstalls kommen trotzdem nicht in Frage, dann löse ich das Problem lieber anders.
Oder sich das "extract" und "add" von resourehacker anschauen - dass kann man mit Batch dann automatisch beim Kompilieren auslösen.
Funktioniert mit der aktuellen Fassung hier nicht. Das log sagt, er hätte die aufsteigend nummerierten ICONGROUP's hinzugefügt, öffnet man die .dll danach wieder mit dem Resource Hacker, sieht man... weder Icon noch Icongroup Einträge, wobei die Ziel-DLL lustigerweise um die hinzugefügten Icons größer geworden ist. Spielt aber keine Rolle, es gibt ja u.a. Resource Tuner Console...

.
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

05 Oct 2015, 15:42

Ich verstehe Dich nicht so ganz. Du kannst doch die DLL per FileInstall in A_AppData oder einem eigenen Unterverzeichnis ablegen, wenn sie noch nicht da ist. Das ist dann nur 1 FileInstall. Außerdem könntest Du für die Installation beider Teile auch ein SetUp-Programm basteln, das natürlich mit erhöhten Rechten ausgestattet sein müsste.
User avatar
haichen
Posts: 631
Joined: 09 Feb 2014, 08:24

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

13 Dec 2015, 08:35

Manche tollen Beiträge findet man immer etwas später. :D
Ganz langsam beginne ich das mit den pointern und dllCall zu begreifen...

Da ich gerade den Text aus Textresourcen wie htm js und css files brauchte, habe ich mir das ganze mühsam zusammengepusselt. Und dann finde ich das hier!!

Da habe ich hier auch gleich die Funktionen zur Textextraktion und zum Soundabspielen angepasst:

Code: Select all

If A_IsCompiled
 {
  tada  := FI_GetResource("tada.wav")
  html  := FI_GetResource("accordion.html")
  html:= GetTextResource(html)
  PlaySoundResource(tada)
  msgbox, Compiled `n`n%html%
 }
  else If !A_IsCompiled
 {
  FileRead, html, accordion.html
  FileRead, tada, *c tada.wav
  PlaySoundResource(tada)
  msgbox, Uncompiled `n`n%html%
 }
return

GetTextResource(TxtRes){
    Return StrGet(TxtRes.Ptr, TxtRes.Size, "UTF-8")
}

PlaySoundResource(SndRes) {
 Return DllCall( "winmm.dll\PlaySound" ( A_IsUnicode ? "W" : "A" ), UInt,( A_IsCompiled ? SndRes.ptr : &SndRes ), UInt,0
               , UInt, 0x6 ) ; SND_MEMORY := 0x4 | SND_NODEFAULT := 0x2
}

; ======================================================================================================================
; FI_GetResource  Loads a resource included in a compiled script with 'FileInstall'.
; Parameters:
;     ResName     -  The name of the resource, i.e. file name as used as source parameter in 'FileInstall'.
; Return values:
;     If the resource is available, the function returns an object containing two key/value pairs:
;        Ptr      -  Pointer to the resource data.
;        Size     -  Size of data in bytes.
;     Otherwise, the return value is zero.
; Credits:
;     Adopted from a scriptlet written by lexikos
;     -> www.autohotkey.com/board/topic/76065-fileextract-fileextract-tomem-examples-for-unicode-builds/
; ======================================================================================================================

FI_GetResource(ResName,ResType="10") {
   ; RT_RCDATA := 10 ;Fileinstall is always 10
   If !(A_IsCompiled)
      Return False
   If (HRSRC := DllCall("Kernel32.dll\FindResource", "Ptr", 0, "Str", ResName, "Ptr", ResType, "UPtr"))
   && (HRES := DllCall("Kernel32.dll\LoadResource", "Ptr", 0, "Ptr", HRSRC, "UPtr"))
      Return {Ptr: DllCall("Kernel32.dll\LockResource", "Ptr", HRES, "UPtr")
            , Size: DllCall("Kernel32.dll\SizeofResource", "Ptr", 0, "Ptr", HRSRC, "UInt")}
   Return False
}

; ======================================================================================================================
; The following line will not be executed, but processed by the compiler
FileInstall, Pic.png, Pic.png ; adjust both names to the value of 'IncludedImage'
FileInstall, tada.wav, tada.wav ;
FileInstall, accordion.html, accordion.html ;
; ======================================================================================================================
Peter2
Posts: 325
Joined: 21 Sep 2014, 14:38
Location: CH

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

07 Mar 2016, 09:40

Bis jetzt habe ich die einzubindenden Dateien im Scriptverzeichnis gehabt und daher ohne Pfad eingebunden:

Code: Select all

If !(A_IsCompiled)
{
    FileInstall, programmlogo.png, programmlogo.png, 0
}
Alles bestens, aber wenn dem Esel zu Wohl ist dann versucht er absolute Pfade:

Code: Select all

If !(A_IsCompiled)
{
    FileInstall, x:\Daten\Projekte\Switch\programmlogo.png, programmlogo.png, 0
}
Und jetzt ist der Spass vorbei - der ganze Pfad wird als Struktur in die Exe hineinkompiliert, und das AHK zum Auslesen findet das nicht mehr.
Hat schon jemand absolute Pfade erfolgreich verwendet?
Peter (AHK Beginner) / Win 10 x64, AHK Version v1.1.33
User avatar
haichen
Posts: 631
Joined: 09 Feb 2014, 08:24

Re: Zugriff auf mit 'FileInstall' eingebundene Skriptressourcen

07 Mar 2016, 11:45

Wenn Du programmlogo.png als ressource verwenden willst, ist der Klammerausdruck überflüssig. Fileinstall muss nur da stehen wo du sonst auch deine Funktionen hinschreibst. Es soll gar nicht "korrekt" ausgeführt werden. Der Kompiler bindet dann die Datei in exe ein, extrahiert sie aber nicht wenn die exe ausgeführt wird. Die eingebundene Datei findet sich dann immer an derselben Stelle in der kompilierten Exe. Das kannst Du mit dem ResHacker überprüfen.

Willst Du Fileinstall wie vorgesehen nutzen ist der If-Block ebenso unsinnig. Der Befehl sollte dann dort stehen wo FileInstall automatisch augeführt wird (vor dem ersten return im skript). Fileinstall verpackt beim kompilieren das Bild in die Exe. Beim Ausführen der exe wird das Bild dann in das Verzeichnis extrahiert, das du angegeben hast. In diesem Fall das Arbeitsverzeichnis.

Return to “Tutorials”

Who is online

Users browsing this forum: No registered users and 12 guests