Inno Setup磁力链接下载实施

时间:2017-01-29 18:57:25

标签: inno-setup torrent

我目前正在使用Inno Download Plugin来下载我的安装程序的文件,这个问题最大的问题是faila正确下载文件。因为连接不良等诸多原因。我想添加一种替代方法来下载文件,因此用户可以选择是否需要常规方式或torrent方式。我知道我可以使用aria2c.exe应用程序(https://aria2.github.io/),有人可以帮我实现它的inno设置代码吗?

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

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

1 个答案:

答案 0 :(得分:2)

只需运行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, 1, 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, 1, P);
        P := Pos('(', Progress);
        if P > 0 then
        begin
          Log('b');
          Transferred := Copy(Progress, 1, P - 1);
          Delete(Progress, 1, P);
          P := Pos('%)', Progress);
          if P > 0 then
          begin
            Log('c');
            Percent := StrToIntDef(Copy(Progress, 1, 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, 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

Torrent download progress

相关问题