views:

291

answers:

3

I'm writing an updater program in Delphi7 which will be run once, but needs many files to run.

What I'd like the achieve:

  1. User runs exe
  2. Exe unpacks files, runs updater
  3. If updater detects and error, prompts the user to send log in e-mail
  4. After the updater is run, temporary files are deleted (some of these files are dlls used by the updater program, so the updater has to be closed before the files can be deleted)

Can anyone recommend a good solution? I've thought about using Inno Setup (too complicated for such an easy task) or using a self-extracting zip file (but how to delete the files afterwards)?

Thanks!

+11  A: 

Personally I would use Inno Setup, as it is very well suited for this type of task. Deleting files is very easy using scripting events, and performing your delete as part of the post installer step.

skamradt
As a matter of fact Inno Setup is designed to do exactly what you have described in your question. Sure, there are other ways of doing what you asked.
Alan Fletcher
+1. What's not to like about Inno? It's written in Delphi, in case that helps. And it does just about everything you need. If there's other functionality that you can't accomplish wiht scripting (which can do LOTS), you could write a DLL or EXE and call it for extra stuff.
Chris Thornton
1, I do not want to display any Innosetup dialogs (Welcome to install, blah, blah)2, If the program displays an error message, now there will be two taskbar buttons, one by Inno and one by my app - confusing the user. This is a no-go.
Steve
You can use the **/VERYSILENT** and **/SUPPRESSMSGBOXES** command line parameters to hide the Inno Setup dialogs. http://bit.ly/dr0eoj
stukelly
Having the dialogs is helpful if you need to manually walk a user through running the update. Writing add-in dll's using Delphi is extreemly simple. Finally, Inno setup is well tested by a very large community.
skamradt
Yes but I can't tell my user to run updater with /Verysilent or /suppressmsgboxes!
Steve
skamradt - I do use Inno, I just think it's not the perfect solution for this task...
Steve
Keep in mind you will need to most likely elevate your patch application to make changes to your existing files. On windows 7 (with standard settings) zip auto extractors won't execute scripts unless they are run as administrator.
skamradt
I've decided to write my own extractor. See the answer below. Inno is good and I'm using it as an installer for my main program, but not for this task!
Steve
+1  A: 

I am using resource for my update program. i was compile resource with brcc32 than compile updater program. when updater program run its self check everything and write or update with new ones. but about this process you have to right write,delete privileges at where your programs run.

i am adding a sample code to below.

file exe.rc

newprog RCDATA Application.exe

file makeres.bat

brcc32 exe.rc

file updater.dpr

{$R exe.res}

unit file and procedures

procedure ExtractRes(resname,fname,ext:string);
var
 rStream:TResourceStream;
 fStream:TFileStream;
 fNamex:string;
begin
 fNamex:=ExtractFilePath(Application.ExeName)+fname+'.'+ext;
 if not fileExists(fnamex) then
 begin
  try
   rStream:=tresourcestream.Create(hinstance,ResName,RT_rcDATA);
   fStream := TFileStream.Create(fnamex, fmCreate);
   fStream.CopyFrom(rStream, 0);
  finally
   rStream.Free;
   fstream.Free;
  end;
 end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
 apath:string;
begin
 if Timer1.Enabled then
  Timer1.Enabled:=false;
 apath:=ExtractFilePath(Application.ExeName);
 lblMesg.Caption:='Backup old version';
 Application.ProcessMessages;
 if FileExists(apath+'Application_old.bak') then
  DeleteFile(apath+'Application_old.bak') ;
 while FileExists(apath+'Application.exe') do
 begin
  RenameFile(apath + 'Application.exe', apath + 'Application_old.bak');
  sleep(1);
  if FileExists(apath+'Application.exe') then
  begin
   lblMesg.Caption:='It seems application still running. Waiting for end';
   if FileExists(apath+'Application_old.bak') then
    DeleteFile(apath+'Application_old.bak');
   DeleteFile(apath+'Application.exe');
  end;
  Application.ProcessMessages;
 end;
 lblMesg.Caption:='Creating New Version..';
 Application.ProcessMessages;
 ExtractRes('Application','Application','exe');
 lblMesg.Caption:='Running New Version...';
 Application.ProcessMessages;
 WinExec(pchar(apath+'Application.exe'),sw_show);
 Application.ProcessMessages;
 Halt;
end;

i think this can help your 1,2,3 question. For 4 you can extend code.

sabri.arslan
Hello! 1, I need to extract files to a temporary directory and run my program there. Some dlls need to be in the same directory with the program and if the program is run without admin rights, it can't use the base directory for extraction of files.2, My program uses a dll to connect to the database. If I try to delete the dll after being disconnected, it's still in use by the DB components. Thus, I'd need to call a separate program just to delete the files causing all sort of problems
Steve
i understand. you need elevation for vista and 7. but for xp standart limited users you need to prompt user the run as administrator. i don't know xp soluiton, but i know you have to run process from inside your code again with shellexecuteex. if you google it you found good examples.but for elevation i can send a sample project.
sabri.arslan
So here is the final solution and yours is the closest: I've decided to write my own extractor program. Steps: 1, Extractor program extracts files from resource 2, Extractor program launches main updater using ShellExecuteEx 3, Once the updater is finished, the extractor program deletes files from the temp folder. This turned out to be the best solution instead of using 3rd party bullshit. Thanks!
Steve
A: 

Maybe not a Delphi answer, but if you purchase a license for WinRAR you can use the inbuilt simple setup functionality (you compress to sfx file and the script is stored in a comments file)

Very easy to use, can clean up after itself and compresses nicely!

MarkRobinson