[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 202
  • Last Modified:

Determining exe size

I'd like to be able to determine an exe's size based on information in the header; so I can read the rest of the data from the file (I'm going to append data to the exe)
I'm sure I've seen how to do this somewhere.. just cant find it.
0
delphiexpert
Asked:
delphiexpert
1 Solution
 
intheCommented:
you know about GetFileSize() api ?
0
 
intheCommented:
i cut this from larger example but it shows how to call it:

procedure TForm1.FileListBox1Change(Sender: TObject);
var
  Security: TSecurityAttributes;        // security attributes for the file
  hFile: Integer;                       // holds the file handle
  FileInfo: TByHandleFileInformation;   // holds the file information
  Intermediate: TFileTime;              // holds a file time
  SystemTime: TSystemTime;              // holds the converted file time
  FileType: DWORD;                      // holds the file type
  AMPM: string;                         // morning/evening indicator
begin
  {clear the status bar}
  StatusBar1.SimpleText:= '';

  {initialize the security information}
  Security.nLength:=SizeOf(TSecurityAttributes);
  Security.bInheritHandle:=FALSE;

  {open the selected file for reading}
  hFile:=CreateFile(PChar(FileListBox1.FileName), GENERIC_READ, 0, @Security,
                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if (hFile <> INVALID_HANDLE_VALUE) then
  begin
    {retrieve the file information}
    GetFileInformationByHandle(hFile,FileInfo);


    {display the file size}
    Label4.Caption:=IntToStr(GetFileSize(hFile, nil))+ ' bytes';
0
 
BSamsonCommented:
It sounds like you want to create a stub EXE that you can append other data to.  The EXE size isn't stored in the EXE header, the only way I know to do this is to write two programs.

One program is your EXE stub application to which you intend to append your data.

The code for your stub should open it's own EXE file and perform a file seek to a predefined file position ( this is where your other short program comes in ).

Once at your predefined location you can read your extended data.

The other application you need to write is a small program to taek your EXE stub program and your extended data and concatenate them into a new EXE file.

Note  You'll need to compile your EXE stub application with some arbitary figure for the predefined location, then once it's compiled, note down the files size of the Stub EXE, go back into the code for the stub EXE and set the predefined location to the filesize you just noted down,  now recompile the stub ( now with the correct location value ) make sure that the EXE stub file size hasn't changed from the value you noted down, then run your second application to concatenate the stub and the extended data into a single EXE.

A bit painful I know..

Brian
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
delphiexpertAuthor Commented:
D'oh, thats the way I was going to do it but I was hoping there was a better way

I'll leave this one open for a bit in case there is...

BTW there's no need to write an app to make the two files into one:
copy /b stub.exe+data.dat output.exe
works fine

0
 
BSamsonCommented:
Of course..

In the past, I automated the whole process so it would compile, check the size, edit the source file and recompile.

If you think about it, there isn't anyway that the size could be held in the EXE header, because until the file is created the size isn't known.

All the Best
Brian
0
 
ahalyaCommented:
Hello Delphi Expert,

I have created a similar "self extracting" EXE.  I do use an identifier to find the location of my data file within the EXE.  By doing this I don't have to worry about the size of the EXE or the attachemnts. All the required info will be self contained withing the "Self extracting" exe.

I can attach several files (including other EXEs :-) and at the end i write a small record with the toal size of the data files.  [Ofcouse I have a seperate exe file that calls my "AttachFiles" and "FinaliseAttachments" procedures to create the new Self Extracting EXE (by appending the DataRecords & Files to the stub EXE; My stub EXE is only 15k in size, btw)

The stub EXE first reads the "Finalised Data Record" to findout the info about the file contained within itself. It then can extract files (even selectively, if you want to).

I have copied a few of my procedures, that you may find useful.




const FileDataHeader : string[10] = '*FileData*' ;
      FinalizeHeader : string[10] = '*FileInfo*' ;
      CtrlZ         : char = ^Z                 ;

function  AttachFile(ExeName, DataFileName:string):boolean;

var f    : file ;
    size : DWord;
    data : pointer;

begin
AttachFile := false;
Size := FileSizeof(DataFileName);
AssignFile(f, DataFileName);

try
   GetMem(data, size);
   FileMode := 0; //Read only
   reset(f,1);
   BlockRead(f, Data^,Size);

   assign(f,ExeName);
   FileMode := 2        ;{Allow Read and Write}
   reset(f,1);
   Seek(f,FileSize(f));

   BlockWrite(f,FileDataHeader,SizeOf(FileDataHeader));
   FileInfo.FileName := ExtractFileName(DataFileName);
   FileInfo.FileSize := Size;

   BlockWrite(f, FileInfo, sizeof(FileInfo));
   BlockWrite(f, Data^,Size);
   BlockWrite(f,CtrlZ,1);
   Result := true;
finally
   FreeMem(Data);
   close(f);
   end;
end;


function FinaliseAttachments(ExeName:string; TotalLength:integer):boolean;

var f    : file ;
    size : DWord;
    data : pointer;

begin
result := false;
try
   AssignFile(f,ExeName);
   FileMode := 2        ;{Allow Read and Write}
   reset(f,1);
   Seek(f,FileSize(f));

   BlockWrite(f, FinalizeHeader, SizeOf(FinalizeHeader));
   BlockWrite(f, TotalLength ,   Sizeof(TotalLength));
   BlockWrite(f,CtrlZ,1);
   Result := true;
finally
   CloseFile(f);
   end;
end;

function GetAttachSize(ExeName:string):integer;

var f    : file ;
    size : DWord;
    data : pointer;

begin
result := 0;
try
   AssignFile(f,ExeName);
   FileMode := 0; //read only
   reset(f,1);

   Seek(f,FileSize(f)-Sizeof(integer)-1);
   BlockRead(f, Size , Sizeof(Size));
   Result := size;
finally
   CloseFile(f);
   end;
end;


//******************************************
//Here is the code from my stub EXE that extracts all files:
//******************************************

   StartPos := GetAttachSize(ExeName);
   try
     AssignFile(fin, ExeName);
     FileMode := 0;//read only
     reset(fin,1);
     Overhead := SizeOf(FileDataHeader) + SizeOf(TFileInfo) + SizeOf(CtrlZ);

     repeat
      Seek(fin, FileSize(fin) - StartPos - Sizeof(FinalizeHeader) - Sizeof(integer)-1);
      BlockRead(fin ,Buffer,SizeOf(FileDataHeader));
      if (Buffer = FileDataHeader) then
         begin;
         BlockRead(fin, FileInfo, sizeof(FileInfo));
         s := Dir + FileInfo.FileName;
         StartPos := StartPos - FileInfo.FileSize - OverHead;
         GetMem(Data, FileInfo.FileSize);
         try
           BlockRead(fin,Data^,FileInfo.FileSize);
           AssignFile(fout, s);//Dir contains dir & filename.
           FileMode := 1;
           ReWrite(fout, 1);
           BlockWrite(fout, Data^, FileInfo.FileSize);
         finally
           FreeMem(Data);
           CloseFile(fout);
         end;
         if IsEXEFile(s) then ExecExe(s);
         end;
     until (Buffer <> FileDataHeader);
   finally
    CloseFile(fin);
    end;
   end;
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now