inno-setup – Inno Setup磁力链接下载实施

前端之家收集整理的这篇文章主要介绍了inno-setup – Inno Setup磁力链接下载实施前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我目前正在使用Inno Download Plugin为我的安装程序下载文件,这个问题最大的问题是faila正确下载文件.因为连接不良等诸多原因.我想添加一种替代方法来下载文件,因此用户可以选择是否需要常规方式或torrent方式.我知道我可以使用aria2c.exe应用程序( https://aria2.github.io/),有人可以帮我实现它的inno设置代码吗?

我需要的是使用torrent(aria2.exe)下载7z文件,然后将内容解压缩到{{app}}位置的已定义文件夹.

好的代码示例可能就是我所需要的.

解决方法

只需运行aria2c,将其输出重定向文件并轮询文件内容获取下载进度.

它实际上与我对此答案的解决方案非常相似:
Inno Setup – Make Inno Setup Installer report its installation progress status to master installer

#define TorrentMagnet "magnet:..."

[Files]
Source: aria2c.exe; Flags: dontcopy
Source: InnoCallback.dll; Flags: dontcopy

[Code]

function BufferToAnsi(const Buffer: string): AnsiString;
var
  W: Word;
  I: Integer;
begin
  SetLength(Result,Length(Buffer) * 2);
  for I := 1 to Length(Buffer) do
  begin
    W := Ord(Buffer[I]);
    Result[(I * 2)] := Chr(W shr 8); { high byte }
    Result[(I * 2) - 1] := Chr(Byte(W)); { low byte }
  end;
end;

type
  TTimerProc = procedure(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);

function SetTimer(Wnd: LongWord; IDEvent,Elapse: LongWord; TimerFunc: LongWord): LongWord;
  external 'SetTimer@user32.dll stdcall';
function KillTimer(hWnd: LongWord; uIDEvent: LongWord): BOOL;
  external 'KillTimer@user32.dll stdcall';

function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord;
  external 'wrapcallback@files:innocallback.dll stdcall';

var
  ProgressPage: TOutputProgressWizardPage;
  ProgressFileName: string;

procedure UpdateProgressProc(H: LongWord; Msg: LongWord; Event: LongWord; Time: LongWord);
var
  S: AnsiString;
  I: Integer;
  L: Integer;
  P: Integer;
  Max: Integer;
  Progress: string;
  Buffer: string;
  Stream: TFileStream;
  Transferred: string;
  Percent: Integer;
  Found: Boolean;
begin
  Found := False;
  try
    { Need shared read as the output file is locked for writting,}
    { so we cannot use LoadStringFromFile }
    Stream := TFileStream.Create(ProgressFileName,fmOpenRead or fmShareDenyNone);
    try
      L := Stream.Size;
      Max := 100*2014;
      if L > Max then
      begin
        Stream.Position := L - Max;
        L := Max;
      end;
      SetLength(Buffer,(L div 2) + (L mod 2));
      Stream.ReadBuffer(Buffer,L);
      S := BufferToAnsi(Buffer);
    finally
      Stream.Free;
    end;

    if S = '' then
    begin
      Log(Format('Progress file %s is empty',[ProgressFileName]));
    end;
  except
    Log(Format('Failed to read progress from file %s',[ProgressFileName]));
  end;

  if S <> '' then
  begin
    P := Pos('[#',S);
    if P = 0 then
    begin
      Log('Not found any progress line');
    end
      else
    begin
      repeat
        Delete(S,1,P - 1);
        P := Pos(']',S);
        Progress := Copy(S,2,P - 2);
        Delete(S,P);
        P := Pos('[#',S);
      until (P = 0);

      Log(Format('Found progress line: %s',[Progress]));
      P := Pos(' ',Progress);
      if P > 0 then
      begin
        Log('A');
        Delete(Progress,P);
        P := Pos('(',Progress);
        if P > 0 then
        begin
          Log('b');
          Transferred := Copy(Progress,P - 1);
          Delete(Progress,P);
          P := Pos('%)',Progress);
          if P > 0 then
          begin
            Log('c');
            Percent := StrToIntDef(Copy(Progress,P - 1),-1);
            if Percent >= 0 then
            begin
              Log(Format('Transferred: %s,Percent: %d',[Transferred,Percent]));
              ProgressPage.SetProgress(Percent,100);
              ProgressPage.SetText(Format('Transferred: %s',[Transferred]),'');
              Found := True;
            end;
          end;      
        end;
      end;
    end;
  end;

  if not Found then
  begin
    Log('No new data found');
    { no new progress data,at least pump the message queue }
    ProgressPage.SetProgress(ProgressPage.ProgressBar.Position,100);
  end;
end;

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  TorrentDownloaderPath: string;
  TempPath: string;
  CommandLine: string;
  Timer: LongWord;
  InstallError: string;
  ResultCode: Integer;
  S: AnsiString;
begin
  ExtractTemporaryFile('aria2c.exe');

  ProgressPage := CreateOutputProgressPage('Torrent download','Downloading torrent...');
  ProgressPage.SetProgress(0,100);
  ProgressPage.Show;
  try
    Timer := SetTimer(0,250,WrapTimerProc(@UpdateProgressProc,4));

    TempPath := ExpandConstant('{tmp}');
    TorrentDownloaderPath := TempPath + '\aria2c.exe';
    ProgressFileName := ExpandConstant('{tmp}\progress.txt');
    Log(Format('Expecting progress in %s',[ProgressFileName]));
    CommandLine :=
      Format('"%s" "%s" > "%s"',[
        TorrentDownloaderPath,'{#TorrentMagnet}',ProgressFileName]);
    Log(Format('Executing: %s',[CommandLine]));
    CommandLine := Format('/C "%s"',[CommandLine]);
    if not Exec(ExpandConstant('{cmd}'),CommandLine,TempPath,SW_HIDE,ewWaitUntilTerminated,ResultCode) then
    begin
      Result := 'Cannot start torrent download';
    end
      else
    if ResultCode <> 0 then
    begin
      LoadStringFromFile(ProgressFileName,S);
      Result := Format('Torrent download Failed with code %d',[ResultCode]);
      Log(Result);
      Log('Output: ' + S);
    end;
  finally
    { Clean up }
    KillTimer(0,Timer);
    ProgressPage.Hide;
    DeleteFile(ProgressFileName);
  end;
end;

BufferToAnsi及其使用基于:
Inno Setup LoadStringFromFile fails when file is open in another process

猜你在找的Delphi相关文章