【问题标题】:Self-extracting Delphi program自解压Delphi程序
【发布时间】:2010-04-26 19:59:50
【问题描述】:

我正在用 Delphi7 编写一个更新程序,它将运行一次,但需要运行很多文件。

我想要实现的目标:

  1. 用户运行exe
  2. Exe 解压文件,运行更新程序
  3. 如果更新程序检测到错误,提示用户发送登录电子邮件
  4. 更新程序运行后,临时文件被删除(其中一些文件是更新程序使用的dll,因此必须关闭更新程序才能删除文件)

谁能推荐一个好的解决方案?我考虑过使用 Inno Setup(对于这么简单的任务来说太复杂了)或使用自解压 zip 文件(但之后如何删除文件)?

谢谢!

【问题讨论】:

    标签: delphi extraction


    【解决方案1】:

    我个人会使用 Inno Setup,因为它非常适合此类任务。使用脚本事件删除文件非常容易,并在安装后步骤中执行删除。

    【讨论】:

    • 事实上,Inno Setup 旨在完全按照您在问题中的描述进行。当然,还有其他方法可以按照您的要求进行操作。
    • +1。 Inno 有什么不喜欢的地方?它是用 Delphi 编写的,以防万一。它几乎可以满足您的所有需求。如果还有其他功能您无法通过脚本完成(可以做很多事情),您可以编写一个 DLL 或 EXE 并调用它以获得额外的东西。
    • 1,我不想显示任何 Innosetup 对话框(欢迎安装,等等,等等) 2,如果程序显示错误消息,现在将有两个任务栏按钮,一个由 Inno 和我的应用程序之一 - 让用户感到困惑。这是不行的。
    • 您可以使用 /VERYSILENT/SUPPRESSMSGBOXES 命令行参数来隐藏 Inno Setup 对话框。 bit.ly/dr0eoj
    • 如果您需要手动引导用户运行更新,则对话框会很有帮助。使用 Delphi 编写加载项 dll 非常简单。最后,Inno 设置经过了一个非常大的社区的良好测试。
    【解决方案2】:

    我正在为我的更新程序使用资源。我是用 brcc32 编译资源而不是编译更新程序。当更新程序运行它的自我检查一切并用新的写入或更新时。但是关于这个过程,你必须在你的程序运行的地方正确写入、删除权限。

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

    文件 exe.rc

    newprog RCDATA Application.exe
    

    文件 makeres.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,则数据库组件仍在使用它。因此,我需要调用一个单独的程序来删除导致各种问题的文件
    • 我明白。您需要提升 vista 和 7。但对于 xp 标准受限用户,您需要提示用户以管理员身份运行。我不知道 xp 解决方案,但我知道您必须使用 shellexecuteex 从代码内部再次运行进程。如果你用谷歌搜索,你会发现很好的例子。但对于海拔,我可以发送一个示例项目。
    • 所以这是最终解决方案,而您的解决方案是最接近的:我决定编写自己的提取程序。步骤: 1、Extractor 程序从资源中提取文件 2、Extractor 程序使用 ShellExecuteEx 启动主更新程序 3、更新程序完成后,提取程序会从 temp 文件夹中删除文件。事实证明,这是最好的解决方案,而不是使用 3rd 方的废话。谢谢!
    【解决方案3】:

    也许不是 Delphi 答案,但如果您购买了 WinRAR 的许可证,您可以使用内置的简单设置功能(您压缩为 sfx 文件,脚本存储在 cmets 文件中)

    非常好用,可以自行清理,很好压缩!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多