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