Jump to content

Store Executable (or other kind of file) Inside your Executable and Execute it

- - - - -

  • Please log in to reply
No replies to this topic

#1
LuthfiHakim

LuthfiHakim

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 765 posts
In this tutorial I will show you how to embed a program into your program and then execute it from your program. While I do say embed a program, but actually you can embed any kind of file inside your program. And with the way we execute it in this tutorial, you could also execute the file/document. If you check this thread, this tutorial is actually the solution of same problem. Only this time we do it with Delphi.

Embedding a program

To embed or include a program inside your executable, you have to treat it as a resource and include it into your resource script. Usually Delphi done and hide these things for you transparently. But not this time. This time you have to do it by your own.

If you don't have a resource script, then create one. It's just a simple text file anyway. Usually resource scripts are given extension .rc. But this is not mandatory. In this tutorial let's assume we want to embed a program named hello.exe. All this program does is, surprise surprise, popping a "Hello!" message. To include this program, add this line to the resource script.

Quote

Hello RCDATA hello.exe

Let's name the resource script embed.rc. Now let's compile it into resource format. For this we can use Borland Resource Compiler (brcc32.exe). You can run brcc32.exe using command prompt, of create a .BAT file to make life easier when you have to build the resource more than once or twice (it's quite usual in medium and big projects).

The command to compile the resource in our tutorial is:

brcc32 -32 -fo embed.res embed.rc

It tells the resource compiler to compile scripts in embed.rc into 32 bit resource format and name the result as embed.res. In the attached demo project, you can see how to add this inside a .BAT file.

Now that we have the resource, it's time to add the resource into our Delphi project. In Delphi create a new Application project and then view the project's source. There add the following line before the [/I]begin[/I] line.

{$R 'embed.res' 'embed.rc'}

That line specifically tells the compiler to include our resource contained in embed.res.

And that's it for this section. Everytime we compile the project, resources inside embed.res will also included in our application. Now let's move on how to execute it from our application.

Execute Embedded Program

To execute the program, we have to extract it to temporary file, preferably inside temporary folder, and then run it. For extracting a resource we can use TResourceStream class that is specifically designed to deal with reading resources. It has a method to save a resource into a file.

To execute a file, we can use Windows api ShellExecute or CreateProcess. In this tutorial we chose to use ShellExecute since this api also allow us to also "execute" file or document. When executing non-executable file, ShellExecute will try to find default program for it and run it. Sounds more interesting, right?

In the demo application I placed a button in the main form. Whenever the button is pushed, it will extract the hello.exe and then execute it. And the code for the button's OnClick event is:


procedure TForm1.Button1Click(Sender: TObject);

var

  vExeFile: string;

  RS: TResourceStream;

begin

  // create and instance of TResourceStream and point it to the resource

  // we are interested in

  RS := TResourceStream.Create(HInstance, 'Hello', RT_RCDATA);

  try

    // setting up the temporary file name

    vExeFile := ExtractFilePath(ParamStr(0)) + 'tmp.exe';


    // extract hello.exe to the temporary file

    RS.SaveToFile(vExeFile);


    // execute the temporary file

    ShellExecute(Self.Handle, 'open', PChar(vExeFile), nil, nil, SW_NORMAL)

  finally

    RS.Free;

  end;

end;


I believe the comments inside the code are pretty explanatory.

Full source code of the the demo project is attached. Feel free to use or improve the code, and don't hesitate to give feedback.

EDIT: I came across this post asking for solution for the problem that is addressed by this tutorial. Unfortunately the poster asking for code in C#, making this tutorial could not provide direct answer. However I decided to provide code to extract and run the embedded file using pure windows api (no VCL). I hope with this sample code, anyone can easily convert it to any language that supports windows api calls.

So here is the code for extracting and executing the embedded files using only Windows api.

procedure TForm1.Button1Click2(Sender: TObject);

var

  vResHndle: THandle;

  HGlobal  : THandle;

  vData    : Pointer;

  vResSize : DWORD;

  vFile    : THandle;

  vExeFile : string;

  vCount   : DWORD;

begin

  // get the handle to the resource we are interested in

  vResHndle := FindResource(HInstance, 'Hello', RT_RCDATA);

  if vResHndle = 0 then Exit;


  // load the resource to memory

  HGlobal := LoadResource(HInstance, vResHndle);

  if HGlobal = 0 then Exit;


  // find the address of the resource we've just load into memory

  vData := LockResource(HGlobal);

  // get the size of the resource

  vResSize := SizeOfResource(HInstance, vResHndle);


  // setting up the temporary file name

  vExeFile := ExtractFilePath(ParamStr(0)) + 'tmp.exe';


  // create the temporary file

  vFile := CreateFile(PChar(vExeFile)

                      , GENERIC_WRITE, FILE_SHARE_READ

                      , nil

                      , CREATE_ALWAYS

                      , FILE_ATTRIBUTE_ARCHIVE

                      , 0);


  if vFile=INVALID_HANDLE_VALUE then

    // show error msg if file creation failed

    ShowMessage(SysErrorMessage(GetLastError))

  else try

    // write the resource into the file

    WriteFile(vFile, vData^, vResSize, vCount, nil);

  finally

    // close the file (and do the actual storing to disk 

    CloseHandle(vFile);

  end;


  // execute the temporary file

  ShellExecute(Self.Handle, 'open', PChar(vExeFile), nil, nil, SW_NORMAL)

end;

Attached Files


Edited by LuthfiHakim, 30 January 2011 - 11:35 PM.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users