我目前正在使用Inno Download Plugin来下载我的安装程序的文件,这个问题最大的问题是faila正确下载文件。因为连接不良等诸多原因。我想添加一种替代方法来下载文件,因此用户可以选择是否需要常规方式或torrent方式。我知道我可以使用aria2c.exe应用程序(https://aria2.github.io/),有人可以帮我实现它的inno设置代码吗?
我需要的是使用torrent(aria2.exe)下载7z文件,然后将内容解压缩到{{app}}位置的已定义文件夹。
好的代码示例可能就是我所需要的。
答案 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