?
Solved

Help!.. My program needs to read it's own exe file

Posted on 1999-07-28
20
Medium Priority
?
239 Views
Last Modified: 2010-04-04
 I can't get a delphi program to open it's own .exe file on disk for read access :(  for example.. a program 'test.exe'
needs to open and read the file 'test.exe' so that it can make a new copy of itself.... 'newtest.exe'   I know it can somehow be done because other windows programs open their own file easily.... my hex editor can easily open itself and read the data in... it won't write to it but reading works just fine...Aspack can open itself as well... so HOW can I do this using Delphi? all my attempts fail :(   here is the source for the latest attempt... what am I doing wrong?  or what am I not doing right?    

unit mainform;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, ComCtrls, Gauges;

type
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  SrcFile, DestFile: File;
  BytesRead, BytesWritten, TotalRead: Integer;
  Buffer: array[1..500] of byte;
  FSize: Integer;
begin

  AssignFile(SrcFile, 'test.exe');
  AssignFile(DestFile, 'newtest.exe');
  Reset(SrcFile, 1); // Open source file for read access.
  try
    try
      Rewrite(DestFile, 1); // Open destination file for write access.
      try
        TotalRead := 0;

        FSize := FileSize(SrcFile);

        repeat
          BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
          if BytesRead > 0 then begin
            BlockWrite(DestFile, Buffer, BytesRead, BytesWritten);
            if BytesRead <> BytesWritten then
              raise Exception.Create('Error copying file')
            else begin
              TotalRead := TotalRead + BytesRead;
              ProgressBar1.Position := Trunc(TotalRead / Fsize) * 100;
              ProgressBar1.Update;
            end;
          end
        until BytesRead = 0;
      finally
        CloseFile(DestFile); // Close destination file.
      end;
    finally
      CloseFile(SrcFile);   // Close source file.
    end;
  except

    Erase(DestFile);
    raise;
  end;

end;

end.




Gwen
0
Comment
Question by:Gwena
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 7
  • 4
20 Comments
 
LVL 10

Expert Comment

by:viktornet
ID: 1391712
Some programs such as Notepad (that's why there is the 64kb limit) read the whole file into a buffer, and keep it in memory... the thing is that when a program opens up, it can set some attributes... for example the lock attribute... once that is set, you cannot open the file, because it will give you an error and let you know that the EXE is in use... You cannot open your own application because that would result in a crash.. the only way to do something like that is to have another program which waits for yours to finish then copy it or whatever, and ends itself... That's what a self deleting program does :)

If you need more info ask!

..-=ViKtOr=-..
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391713
I'm very curious about this... it seems that the inability to read a running exe file is limited ONLY to delphi... this seems odd.... I wrote 2 new small programs..
'test.exe' and 'test2.exe'   both are identical except for their names....all they do is try and copy 'test.exe' to 'newtest.exe'   when I run test2.exe by itself it works flawlessly..it copies the not-running test.exe to the new file 'newtest.exe' ... when I run 'test.exe' it fails with an error as it is trying to read it's own exe file...now here is the odd part---  when I run them both... then test2.exe also fails????  so what this seems to mean is that a delphi program cannot read the exe file of any other running  program???? but when i run a program written in another language it IS able to read the exe file of any running delphi program! So.... is it that other languages allow the reading of 'locked' files or running exe's but delphi stands alone in it's inability to do so???  Not only that but i ran a C++ program and it was able to not only read the exe of any running delphi app but it can modify that exe and even delete it while the delphi program continues to run ???  Delphi seems to have a shortcoming here... this makes it IMPOSSIBLE to have a delphi app check it's own exe file as it runs to ensure that some other program has not modified it with a virus..or whatever...   :-(   booo hissss   this seems like a very dubious feature for Borland to have inflicted upon delphi!  at least they should have made this an option that one could set to enable/disable the opening of running files......Lord have mercy on me I'd hate to break out that awful MS C++ compiler again to write my programs :-(   and spawning a second delphi program and then shutting down the first one so the second one can copy it to a new file.. then restarting the first file so it can finally access that data is just too Rube Goldberg for me :)  I suppose I could write a tiny C++ program and put it into a resource file in a delphi app..it could spawn this C++ file and the C++ file could then read the Still Running! delphi app...whew!  that makes me dizzy :)

Another odd thing... I thought Aspack was written in Delphi?  How come it can
open itself and write a copy as  aspack.bak ?
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391714
There SURE is a way to do that, but it would be extremely difficult, and you MUST have a good knowledge of Windows and the language you're using, in this case Delphi,,, there are functions such as VirtualProtect() that would let you change the state of a particular page in memory... that way you can unlock some parts of the program.. that's how selfmodifying program work... (some of 'em are viruses of course ;-))...

Some info about this func,..
========
The VirtualProtect function changes the access protection on a region of committed pages in the virtual address space of the calling process. This function differs from VirtualProtectEx, which changes the access protection of any process.

BOOL VirtualProtect(

    LPVOID lpAddress,      // address of region of committed pages
    DWORD dwSize,      // size of the region
    DWORD flNewProtect,      // desired access protection
    PDWORD lpflOldProtect       // address of variable to get old protection  
   );      
 ======

Also check out the rest of the functions in that group..

..-=ViKtOr=-..
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 5

Author Comment

by:Gwena
ID: 1391715
Sorry..but I have to reject...

"when a program opens up, it can set some attributes... for example the lock attribute... once that is set, you cannot open the file, "

-Not so.. you can open it...with an app written in another language..so it's a delphi
'feature' (bug) that nixes this... not any attribute of the file...

" You cannot open your own application because that would result in a crash."

- Nope... I can open it while it is running..and it does not crash... I can open it and it seems to keep running happily.... I just had to do it with a program written in another lang....so it's not that it would crash..it's just that delphi feature again :(

" the only way to do something like that is to have another program which waits for yours to finish then copy it or whatever, and ends itself... That's  what a self deleting program does :) "

- nope... That is not the only way to do it... I can do it while the delphi app is running.... as before..I just have to do it with another language because of the
delphi 'feature'   I may get a friend of mine to write a small C program that I can spawn just for the purpose of copying the running delphi program to a file with a different name..but in the same directory.... yuk!  I hate it that delphi comes up so short here...the idea of adulterating a delphi app by sticking in a C program in a
resource file is irksome.

I guess the correct anwer to my question is...You can't do this..because unlike other languages..ONLY delphi keeps you from even reading the exe of any open file..so you have to either live with it or use another language that acts normally
as  regards open exe files....  I still hold out hope that someone can figure out a way to make delphi act like other languages and allow access :-)  I'll cross my fingers....   This HAS to be a BUG.. because what possible harm can it do to simple read your own exe file? I can see how it would be courting disaster to write to it...

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391716
In C that would be too damn easy, but i guess in Delphi you'd have to hack a little.... and the answers to all the above questions are YES, because we're talking about Delphi here, not any other lang... so it's yes and not a NOPE.. It is windows that will allow ou to open the file, not the language... maybe Delphi sets some special attributes or something... maybe it's that way so you cannot write virses and stuff...

..-=ViKtOr=-..
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391717
try setting the FileMode parameter for file opening before using AssingFile() and the rest of the functions...
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391718
300 to anyone that can overcome this delphi shortcoming and show me code to allow me to at least READ the exe file of a running delphi application and copy it to a file with a new name...and do it using only delphi...not by spawning a program written in another lang..yukky
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391719
". maybe Delphi sets some special attributes or something... maybe it's that way so you cannot write virses and stuff..."

How could being able to simply read a running file allow delphi to modify it with a
virus ? If thats why Borland did this it was a silly decision...I think assembly and c are the virus writers languages of choice..

Gwen
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1391720
Where is the problem??? I called this without any problems!!!   :-)

  CopyFile(pchar(Application.ExeName),pchar('c:\windows\desktop\'+ExtractFileName(Application.ExeName)),false);

Regards, Madshi.

0
 
LVL 5

Author Comment

by:Gwena
ID: 1391721
Hi Madshi :)

Exactly what? does that line of code do?????  Remember that I am very new to programming and delphi... I'm working at it as fast as I can... but right now if you looked in the dictionary under 'clueless newbie' I think it just might have a picture of me as an example ;-)

Does this line of code copy the running program ? (please say it does)
if it does..where does it put the copy.. and what in the world is it's new name?
or does this somehow allow the normal file handling routines to work with the
running .exe file???? (please please say yes to this)  ;-)


ps... I went to your web site the other day to look around...very nice..very complicated stuff though.....


Gwen... waiting in anticipation :)
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391722
Gwenm it copies the file that you're running (your EXE program) to a different directory.. so now you have a copy of your EXE to work with...
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391723
Viktornet

:-0   so If I get the current directory (where the program is running from)
and then say I was to create a subdirectory in this current directory..
lets say it would be  C:\gwens_strange_files\temp\ and pasted it into the above line of code thusly



   CopyFile(pchar(Application.ExeName),pchar('C:\gwens_strange_files\temp\'+ExtractFileName(Application.ExeName)),false);  

that it would place a copy of my exe there?????????????

Wow! ... if this works it is the answer to my problem .....
I could then do whatever I wanted to with it!
I GOTTA GO TRY THIS!

What a clever man that Madshi is!
U 2 of course :)
0
 
LVL 20

Accepted Solution

by:
Madshi earned 1200 total points
ID: 1391724
Hi guys,

Vik is right. This line of code copies our currently running executable file (Application.ExeName gives us the full path of our application) to the desktop, with the same filename.
You can also do this:

CopyFile(pchar(Application.ExeName), pchar(ExtractFilePath(Application.ExeName)+'copyOfOurApp.exe'), false);

Let's say, your app is stored in "c:\gwena\yourApp.exe". So "Application.ExeName" is "c:\gwena\yourApp.exe". "ExtractFileName(Application.ExeName)" is "yourApp.exe" and "ExtractFilePath(Application.ExeName)" is "c:\gwena\".

So the last CopyFile line does this:

  CopyFile from "c:\gwena\yourApp.exe" to "c:\gwena\copyOfOurApp.exe"

Regards, Madshi.

P.S: Thanx for the compliment about my homepage. Yes, it's complicated stuff. I think there are enough "Delphi beginner webpages" out there, so my page is more addressed to the profis...  :-))
P.P.S: Sorry to Vik for taking the points away...  :-O
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1391725
P.S: You could probably use something like your code, too. But you need to use the correct flags when opening the file. I'm usually using TFileStream. I think this should work, too (but I did not test it):

  fs1:=TFileStream.Create(Application.ExeName,fmOpenRead or fmShareDenyNone);
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391726
Wow!  Thanks so so much Madshi :-)

You saved the day.. I hope someday i'm half as good at delphi as you are....
You sure deserve the 300 points!
I will try the line you said might also work...
 
 fs1:=TFileStream.Create(Application.ExeName,fmOpenRead or fmShareDenyNone);

Is it ok if I ask you about that later if I have a prob ( I mean without caughing up more points) maybe via email... I will try it out soon as I understand filestreams better :)

Thanx also to Viktor! wish you could both get the points....

.....Gwen (a happy camper)
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391727
I told you that what you were asking for can't be done, but you didn't believe me...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1391728
Ok, a little example about TFileStream:

procedure CopyFile2(source,dest: string);
var fs1, fs2 : TFileStream;
    buf      : pointer;
begin
  fs1:=TFileStream.Create(source,fmOpenRead or fmShareDenyNone);
  try
    fs2:=TFileStream.Create(dest,fmCreate);
    try
      GetMem(buf,fs1.size);
      try
        fs1.Read(buf^,fs1.size);
        fs2.Write(buf^,fs1.size);
      finally FreeMem(buf) end;
    finally fs2.Free end;
  finally fs1.Free end;
end;

You can ask me about fileStreams here or via eMails...  :-)

Regards, Madshi.
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391729
Thanks again Madshi for the info on streams!  Your great! :-)
0
 
LVL 5

Author Comment

by:Gwena
ID: 1391730
OOPS!  here's a correction on something I said earlier in this thread

I said I had used a C++ program that was able to modify a running exe file..
I was mistaken!  The program is a hex-editor that was written in C++ and it
did indeed appear able to modify the exe but on closer inspection the original file
was unaltered... the editor was able to read in and modify the exe file .. and to save
it as a new file with the changes intact.. and it gave every indication that it could
save the modified version and replace the original.. But it was wrong! It was not
able to do this... and it did not provide any indication that the 'save' failed :-(

....Gwen
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1391731
As I told you before... It reads the file in memory and that's is where it is being manipulated...
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

718 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question