我目前正在使用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