自解压的Delphi程序

6
我正在使用Delphi7编写更新程序,该程序只需运行一次,但需要许多文件才能运行。
我希望实现以下目标:
1. 用户运行exe文件。 2. Exe文件解压缩文件并运行更新程序。 3. 如果更新程序检测到错误,则提示用户通过电子邮件发送日志。 4. 运行更新程序后,删除临时文件(其中一些文件是updater程序使用的dll文件,因此必须在删除这些文件之前关闭updater)。
请问有什么好的解决方案吗?我考虑过使用Inno Setup(对于这样一个简单的任务来说太复杂了),或者使用自解压缩zip文件(但如何在之后删除文件)?
谢谢!
3个回答

12

个人而言,我会选择使用 Inno Setup,因为它非常适合这种类型的任务。使用脚本事件很容易删除文件,并将您的删除操作作为后安装步骤的一部分执行。


事实上,Inno Setup旨在完全实现您在问题中描述的内容。当然,还有其他方法可以完成您所要求的操作。 - Alan Fletcher
1
+1. Inno有什么不好的呢?它是用Delphi编写的,如果这有帮助的话。而且它几乎可以做到你所需要的一切。如果有其他功能无法通过脚本实现(脚本可以做很多事情),你可以编写一个DLL或EXE并调用它来完成额外的工作。 - Chris Thornton
1、我不想显示任何Innosetup对话框(欢迎安装,blah,blah)2、如果程序显示错误消息,现在会有两个任务栏按钮,一个是Inno的,一个是我的应用程序的 - 这会让用户感到困惑。这是不可接受的。 - Steve
1
你可以使用 /VERYSILENT/SUPPRESSMSGBOXES 命令行参数来隐藏 Inno Setup 对话框。http://bit.ly/dr0eoj - stukelly
是的,但我不能告诉我的用户使用/Verysilent或/suppressmsgboxes运行更新程序! - Steve
显示剩余4条评论

2

我正在使用资源来更新我的程序。我使用brcc32编译资源,然后编译更新程序。当更新程序运行时,它会自行检查一切并写入或更新新的内容。但是,在此过程中,您必须在程序运行的位置具有正确的写入、删除权限。

我在下面添加了一个示例代码。

文件exe.rc

newprog RCDATA Application.exe

文件制作res.bat

brcc32 exe.rc

文件更新器.dpr

{$R exe.res}

单元文件和过程

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;

我认为这可以帮助你的1、2、3个问题。对于第4个问题,你可以扩展代码。

你好!1、我需要将文件提取到临时目录并在那里运行我的程序。一些dll文件需要与程序放在同一个目录下,如果程序没有管理员权限,则无法使用基本目录来提取文件。2、我的程序使用一个dll文件连接到数据库。如果我在断开连接后尝试删除dll文件,它仍然被DB组件使用。因此,我需要调用一个单独的程序来删除这些文件,这会引起各种问题。 - Steve
我明白。您需要在Vista和7中提升权限。但对于XP标准受限用户,您需要提示用户以管理员身份运行。我不知道XP的解决方案,但我知道您必须再次从代码内部运行进程,并使用Shellexecuteex。如果您在谷歌上搜索,会找到很好的示例。但是对于权限提升,我可以发送一个示例项目。 - sabri.arslan
1
所以这是最终解决方案,而你的方法最接近:我决定编写自己的提取程序。步骤:1、提取程序从资源中提取文件;2、提取程序使用ShellExecuteEx启动主更新程序;3、一旦更新程序完成,提取程序将从临时文件夹中删除文件。这证明这是最佳解决方案,而不是使用第三方垃圾软件。谢谢! - Steve

0

可能不是 Delphi 的答案,但如果你购买了WinRAR的许可证,你可以使用内置的简单安装功能(压缩成自解压文件,并将脚本存储在注释文件中)

非常容易使用,可以自动清理并压缩得很好!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接