Resource files

Just starting out? Need help? Post your questions and find answers here.
RobertRioja
User
User
Posts: 71
Joined: Thu May 02, 2019 3:57 am
Location: USA
Contact:

Resource files

Post by RobertRioja »

I hope that someone can help me.

I want to write a program and create an executable. I want the executable to contain the image of another executable (that I did not write). When my program runs, I want it to write the image to a file so that it can be executed on its own.

I tried the following:

Code: Select all

; Get file size.
Global Q.q
Q = FileSize("abc.exe")

; Put it  into data section.
DataSection
  thefile:
  IncludeBinary "abc.exe"
EndDataSection

; Save it into a file.
CreateFile(0, "xyz.exe")
Q = WriteData(0, ?thefile, Q)
CloseFile(0)
This works but it loads the original file into DataSection at run time. I thought that DataSection was loaded only at compile time, but I was wrong.

Next I tried to use a resource file:

Code: Select all

myfile 1000 abc.exe
This does put the file into my executable at compile time, but I cannot figure out how to then extract it and save it at run time. I cannot find any documentation that can help.

If anyone has any ideas, I would appreciate your sharing.

Thanks,
Robert
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Resource files

Post by mk-soft »

Code: Select all

; Put it  into data section.
DataSection
  startFile:
  IncludeBinary "abc.exe"
  endFile:
EndDataSection

; Define right path. Some virus scanner don't like it
; 
CreateFile(0, "xyz.exe")
WriteData(0, ?startfile, ?endFile - ?startFile)
CloseFile(0)

; RunProgram( ...) ; <- see PB help
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
RobertRioja
User
User
Posts: 71
Joined: Thu May 02, 2019 3:57 am
Location: USA
Contact:

Re: Resource files

Post by RobertRioja »

AHA!!! Yes, that works. I was close, but not close enough.
Thank you,
Robert
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Resource files

Post by Denis »

Hi RobertRioja,

another way that will answer your question, with exe inside resource.

Limits : Windows only, exe file size maxi about 3.999 Gb
In the PB file as well as in the Rc file, you must put the correct path of the file, for the resource file, \\ is the rule.
If you only have one file, MK-soft solution is a good one, if you have many files, resource file must be prefered. With resource file, only needed ones will be loaded.

As MK-sot says, Some virus scanner don't like it. So, a solution will be to first compress the exe file and then encrypt it .
When recreating it, do the operation backwards.

I've done some testes with PB 6 x64 C and i'ts Ok, exe file runs well.

First PB code (sorry, comment a almost in French but it's not a problem with inline tranlators)

Code: Select all

;https://www.purebasic.fr/english/viewtopic.php?p=588343#p588343

EnableExplicit

;- .   ...  Constantes
;  id used to access the file specified in resource (rc file)
#RC_myfile_1000_abc = 1

;- .
;- .   ...  Structure
; to get resource values
Structure Fileinfo
      *FirstAdress
      *DataSize
EndStructure

;- .
;- .   ...  Macros
Macro _MakeIntResource(_value_)
      (_value_ & $FFFF)
EndMacro
Macro _MakeLangID(_primary_, _sublang_)
      (((_sublang_)<<10) | (_primary_))
EndMacro


;- .
;- .   ...  Procedures
; ------------ No Threadsafe
Procedure.i GetModuleHandle()
      ;// Mémorise l'instance
      Static hInstance
      
      Select hInstance
            Case 0
                  hInstance = GetModuleHandle_(0)
      EndSelect
      
      ProcedureReturn hInstance
EndProcedure

Procedure.i Get_RC_DATA_Adress(id, *Fileinfo.Fileinfo)
      ;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      ;// FONCTION: Get_RC_DATA_Adress()
      ;// BUT: Retourne l'adresse de la ressource RC_DATA de l'id passé en paramètre
      ;// PARAMS: id - identifiant statique de la ressource RC_DATA
      ;// RETOURNE: Retourne le pointeur sur la mémoire de la resource spécifié en cas de succès
      ;//           Retourne #True en cas d'erreur
      ;//           Retourne #False en cas d'erreur
      ;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      ;// le handle du bloc d'informations de la ressource string
      Protected findResource
      ;// le handle du bloc d'information des données de la ressource string
      Protected loadResource_RT_RCDATA
      
      ;// l'adresse mémoire du block d'informations de la ressource chargée en mémoire      Protected *lockResource
      findResource = FindResourceEx_(#Null, #RT_RCDATA, _MakeIntResource(id), _MakeLangID(#LANG_NEUTRAL, #SUBLANG_NEUTRAL))
      If findResource = #False
            ProcedureReturn #False
      EndIf
      loadResource_RT_RCDATA = LoadResource_(GetModuleHandle(), findResource)
      If  loadResource_RT_RCDATA = #False
            ProcedureReturn #False
      EndIf
      *Fileinfo\FirstAdress = LockResource_(loadResource_RT_RCDATA)
      If *Fileinfo\FirstAdress = #False
            ProcedureReturn #False
      EndIf
      
      ; Fileinfo\DataSize is a long (MS Limitation), so be careful with ultra big file !
      ; most of the time, it's large enough
      ; maxi : 4294967295 byte  about 3.99999 Gigabyte
      *Fileinfo\DataSize = SizeofResource_(GetModuleHandle(), findResource)
      If *Fileinfo\DataSize = 0
            ProcedureReturn #False
      EndIf
      ProcedureReturn #True
EndProcedure

;- .
Procedure Main()
      Protected file.s = "G:\PureBasic\Applications codeurs\AddExe_To_Resource\xyz.exe"
      Protected Fileinfo.Fileinfo
      
      ; Get File data from resource
      If Get_RC_DATA_Adress(#RC_myfile_1000_abc, @Fileinfo) = #False
            MessageRequester("Error","Failed to load file into memory")
            End
      EndIf
      ; Resource will be freeed by Windows, so do nothing
      
      
      If  CreateFile(0, file) = 0
            MessageRequester("Error","Unable to create file")
            End
      EndIf
      
      If WriteData(0, Fileinfo\FirstAdress, Fileinfo\DataSize) <> Fileinfo\DataSize
            MessageRequester("Error","Data length written in the file is wrong")
            End
      EndIf
      CloseFile(0)
      
EndProcedure

Main()
Then you have to attach a rc file with your PB code (menu compiler\compiler option\ and the select tab and put the rc file).

Here is an example, the file is txt format (end of line CRLF only, CR can cause problems), the txt file format is ANSI (may with another format it will be Ok but i do not tests).

#define LANG_NEUTRAL 0
#define SUBLANG_NEUTRAL 0

// id used by PB to find the specified file
#define RC_myfile_1000_abc 1


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
// exe file to put in
RC_myfile_1000_abc RCDATA "C:\\Users\\xxxx\\OneDrive\\Bureau\\PureIconManager_3_00_x64.exe"
A+
Denis
RobertRioja
User
User
Posts: 71
Joined: Thu May 02, 2019 3:57 am
Location: USA
Contact:

Re: Resource files

Post by RobertRioja »

Thank you Denis.
Now I have another good way to solve the problem.
I appreciate the answers.

Robert
Post Reply