2017-01-29 226 views
1

我目前使用Inno下載插件爲我的安裝程序下載文件,這最大的問題是它無法正確下載文件。由於連接不好等諸多原因。我想添加一個替代方法來下載文件,所以用戶可以選擇他是否需要常規方式或者洪流方式。我知道我可以使用aria2c.exe應用程序(https://aria2.github.io/),有人可以幫我實施它到inno安裝程序的代碼?Inno Setup torrent下載執行

我需要的是使用torrent(aria2.exe)下載7z文件,然後將內容解壓到{{app}}位置中定義的文件夾。

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

回答

1

只需運行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 '[email protected] stdcall'; 
function KillTimer(hWnd: LongWord; uIDEvent: LongWord): BOOL; 
    external '[email protected] stdcall'; 

function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord; 
    external '[email protected]: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

+0

我的回答有幫助嗎? –