Как добавить прогресс бар для backup'а?

Ivan_000

Мимокрокодил
Есть такой скрипт на создание бэкапа перед установкой и возвратом в исходное состояние после установки
#define SourceDir "SourceDir";
#define BackupDir "Backup\SourceDir";

[_______________________________________________Code]
procedure CopyFiles(FromPlace, ToPlace: String);
var
ResultCode: Integer;
begin
Exec('xcopy.exe', '/E /C /H /R /Y /F /I ' + AddQuotes(FromPlace) + ' ' + AddQuotes(ToPlace), ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
ThereIsFolders: Boolean;
begin
ThereIsFolders := (DirExists(AddBackslash(WizardDirValue()) + '{#SourceDir}') and (not DirExists(AddBackslash(WizardDirValue()) + '{#BackupDir}')) );
if ThereIsFolders then
if CurStep=ssInstall then
begin
WizardForm.ProgressGauge.Hide;
WizardForm.StatusLabel.Caption:='Создание резервных копий файлов...';
CopyFiles(ExpandConstant('{app}') + '\{#SourceDir}\*.*', ExpandConstant('{app}') + '\{#BackupDir}');
WizardForm.ProgressGauge.Show;
WizardForm.StatusLabel.Caption:=SetupMessage(msgStatusExtractFiles);
end;
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
CopyFiles(ExpandConstant('{app}') + '\{#BackupDir}\*.*', ExpandConstant('{app}') + '\{#SourceDir}');
DelTree(ExpandConstant('{app}\Backup'), True, True, True);
end;
end;
И есть код, как я понимаю, создания прогресс бара
function PBProc(h:hWnd;Msg,wParam,lParam:Longint):Longint;
var
dt,at,pr,i1,i2: Extended;
lt: Longint;
p: string;
tc: DWORD;
begin
Result:=CallWindowProc(PBOldProc,h,Msg,wParam,lParam);
if (Msg=$402) and (WizardForm.ProgressGauge.Position>WizardForm.ProgressGauge.Min) then begin
i1:=WizardForm.ProgressGauge.Position-WizardForm.ProgressGauge.Min;
i2:=WizardForm.ProgressGauge.Max-WizardForm.ProgressGauge.Min;

tc:=GetTickCount;
if tc-eTime>=1000 then begin
dt:=(tc-sTime)/1000;
at:=i2*dt/i1;
lt:=Round(at-dt)
TimeLeft:=LongintToStringTime(lt);
eTime:=tc;
end;

pr:=i1*100/i2;
p:=Format('%f',[pr])+' %. ';
if Length(TimeLeft)>0 then ProgressInfoLabel.Caption:=ExpandConstant('{cm:AllProgress} ')+p+ExpandConstant('{cm:Remains} ')+TimeLeft;

if StatusLabel.Caption<>WizardForm.StatusLabel.Caption then StatusLabel.Caption:=WizardForm.StatusLabel.Caption;
if FileNameLabel.Caption<>WizardForm.FilenameLabel.Caption then FileNameLabel.Caption:=WizardForm.FilenameLabel.Caption;

//Cлайд-шоу по процентам
//Использовать при отключении модуля "FreeArc"

{if pr-OldPosition>=ProgressStep then begin
OldPosition:=OldPosition+ProgressStep;
ImgSetVisibility(AImg[CurrentImage],False);
CurrentImage:=CurrentImage+1;
if CurrentImage>GetArrayLength(AImg)-1 then CurrentImage:=0;
ImgSetVisibility(AImg[CurrentImage],True);
end;}

//Cлайд-шоу по таймеру
//Использовать при подключении модуля "FreeArc"

if GetTickCount-LastTimerEvent>5000{5 секунд} then begin
LastTimerEvent:= GetTickCount;
ImgSetVisibility(AImg[CurrentImage],False);
CurrentImage:=CurrentImage+1;
if CurrentImage=GetArrayLength(AImg) then CurrentImage:=0;
ImgSetVisibility(AImg[CurrentImage],True);
end;

ImgPBSetPosition(NewPB,pr);
ImgApplyChanges(WizardForm.Handle);
end;
end;
Можно как-то добавить прогресс бар при установке во время резервного копирования и при удалении во время возврата резервных файлов и их удалении?
 

Ivan_000

Мимокрокодил
Там же пример имеется


Писалось под юникод версию
function mCallback( what: PAnsiChar; int1: Longint; str: PAnsiChar): Boolean;
begin
if (string(what) = 'allsize') then
AllSize:= int1;

if(string(what) = 'filename') then
FileInfoLabel.Caption:= MinimizePathName(str, WizardForm.StatusLabel.Font, WizardForm.StatusLabel.Width);

if (string(what) = 'write') then begin
CopyInfoLabel.Caption:= 'Скопировано '+MbOrTb(int1) + ' из ' + MbOrTb(AllSize);
WizardForm.ProgressGauge.Position:= Round(int1);
WizardForm.ProgressGauge.Max:= AllSize;
end;
Application.ProcessMessages;
end;

На этой строке ошибка Could not call proc

======
Попробовал изменить папки откуда и куда копировать - стали копироваться все папки из корня диска с ополовиненным именем
(поставил версию unicode если что)
=====
Закоменитировал эту строчку, теперь всё копируется, но вопрос всё тот же - как добавить процесс копирования в прогресс бар?
За основу взял скрипт Need for Speed™ Undercover.iss с вашего форума.
 
Последнее редактирование:

vint56

Ветеран
Проверенный
Ivan_000,
#define MyAppName "My Program"
#define MyAppVersion "1.5"

[Setup]
AppName={#MyAppName}
AppVersion={#MyAppVersion}
DefaultDirName={pf}\{#MyAppName}
OutputDir=.
Compression=none

[Tasks]
Name: "backup"; Description: "Обновить с сохранением текущих настроек"; Flags: unchecked

[Files]
[Files]
Source: "C:\Program Files (x86)\ACD Systems\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: "BackupFile()"; Tasks: backup;

;Source: "1.txt"; DestDir: "{app}"; BeforeInstall: "BackupFile()"; Flags: ignoreversion ; Tasks: backup;
;Source: "2.txt"; DestDir: "{app}"; BeforeInstall: "BackupFile()"; Flags: ignoreversion ; Tasks: backup;

[code ]
type
#ifdef UNICODE
#define A "W"
PChar = PAnsiChar;
#else
#define A "A"
#endif
TSHFileOpStruct = record
Wnd: HWND;
wFunc: UINT;
pFrom: PChar;
pTo: PChar;
fFlags: Word;
fAnyOperationsAborted: BOOL;
hNameMappings: HWND;
lpszProgressTitle: PChar;
end;

const
FO_MOVE = $0001;
FO_COPY = $0002;
FOF_SILENT = $0004;
FOF_NOCONFIRMATION = $0010;
FOF_FILESONLY = $0080;
FOF_NOCONFIRMMKDIR = $0200;

function SHFileOperation(const lpFileOp: TSHFileOpStruct):Integer; external 'SHFileOperation@shell32.dll stdcall';

procedure BackupFile();
var
file, backFile, backpath: string;
begin
if FileExists(ExpandConstant(CurrentFileName)) then
begin
File := ExpandConstant(CurrentFileName);
backpath := file;
StringChangeEx(backpath, ExpandConstant('{app}'), '', True);
backFile := ExpandConstant('{app}\Backup') + backpath;
ForceDirectories(ExtractFilePath(backfile));
RenameFile(file, backfile);
end;
end;

function BackupDir(const fromDir, toDir: ansistring; IsMove: Boolean): Boolean;
var
fos: TSHFileOpStruct;
_fromDir, _toDir: ansistring;
SR: TFindRec;
res: Boolean;
begin
ForceDirectories(toDir);
if IsMove then
fos.wFunc := FO_MOVE else
fos.wFunc := FO_COPY;
fos.fFlags := FOF_FILESONLY or FOF_SILENT or
FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
_fromDir:= AddBackslash(fromDir);
_toDir := AddBackslash(toDir);
if (Length(fromDir) = Length(_fromDir)) then
begin
res:= FindFirst(_fromDir + '*', SR);
try
while res do
begin
if (SR.Name <> '') and (SR.Name <> '.') and (SR.Name <> '..') then
begin
if SR.Attributes = FILE_ATTRIBUTE_DIRECTORY then
begin
_fromDir:= _fromDir + SR.Name + #0#0;
_toDir := _toDir + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
end else
begin
_fromDir:= _fromDir + SR.Name + #0#0;
_toDir := _toDir + SR.Name + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
end;
Result := (0 = ShFileOperation(fos));
_fromDir:= ExtractFilePath(_fromDir);
_toDir:= ExtractFilePath(_toDir);
end;
res := FindNext(SR);
end;
finally
FindClose(SR);
end;
end else
begin
_fromDir:= RemoveBackslashUnlessRoot(_fromDir) + #0#0;
_toDir := RemoveBackslashUnlessRoot(_toDir) + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
Result := (0 = ShFileOperation(fos));
end;
end;

procedure RestoreBackup(backDir: string);
begin
BackupDir(backDir, ExpandConstant('{app}'), True);
DelTree(backDir, true, true, true);
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usdone then
begin
RestoreBackup(ExpandConstant('{app}\Backup\'));
end;
end;
 

Ivan_000

Мимокрокодил
Ivan_000,
#define MyAppName "My Program"
#define MyAppVersion "1.5"

[Setup]
AppName={#MyAppName}
AppVersion={#MyAppVersion}
DefaultDirName={pf}\{#MyAppName}
OutputDir=.
Compression=none

[Tasks]
Name: "backup"; Description: "Обновить с сохранением текущих настроек"; Flags: unchecked

[Files]
[Files]
Source: "C:\Program Files (x86)\ACD Systems\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: "BackupFile()"; Tasks: backup;

;Source: "1.txt"; DestDir: "{app}"; BeforeInstall: "BackupFile()"; Flags: ignoreversion ; Tasks: backup;
;Source: "2.txt"; DestDir: "{app}"; BeforeInstall: "BackupFile()"; Flags: ignoreversion ; Tasks: backup;

[code ]
type
#ifdef UNICODE
#define A "W"
PChar = PAnsiChar;
#else
#define A "A"
#endif
TSHFileOpStruct = record
Wnd: HWND;
wFunc: UINT;
pFrom: PChar;
pTo: PChar;
fFlags: Word;
fAnyOperationsAborted: BOOL;
hNameMappings: HWND;
lpszProgressTitle: PChar;
end;

const
FO_MOVE = $0001;
FO_COPY = $0002;
FOF_SILENT = $0004;
FOF_NOCONFIRMATION = $0010;
FOF_FILESONLY = $0080;
FOF_NOCONFIRMMKDIR = $0200;

function SHFileOperation(const lpFileOp: TSHFileOpStruct):Integer; external 'SHFileOperation@shell32.dll stdcall';

procedure BackupFile();
var
file, backFile, backpath: string;
begin
if FileExists(ExpandConstant(CurrentFileName)) then
begin
File := ExpandConstant(CurrentFileName);
backpath := file;
StringChangeEx(backpath, ExpandConstant('{app}'), '', True);
backFile := ExpandConstant('{app}\Backup') + backpath;
ForceDirectories(ExtractFilePath(backfile));
RenameFile(file, backfile);
end;
end;

function BackupDir(const fromDir, toDir: ansistring; IsMove: Boolean): Boolean;
var
fos: TSHFileOpStruct;
_fromDir, _toDir: ansistring;
SR: TFindRec;
res: Boolean;
begin
ForceDirectories(toDir);
if IsMove then
fos.wFunc := FO_MOVE else
fos.wFunc := FO_COPY;
fos.fFlags := FOF_FILESONLY or FOF_SILENT or
FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
_fromDir:= AddBackslash(fromDir);
_toDir := AddBackslash(toDir);
if (Length(fromDir) = Length(_fromDir)) then
begin
res:= FindFirst(_fromDir + '*', SR);
try
while res do
begin
if (SR.Name <> '') and (SR.Name <> '.') and (SR.Name <> '..') then
begin
if SR.Attributes = FILE_ATTRIBUTE_DIRECTORY then
begin
_fromDir:= _fromDir + SR.Name + #0#0;
_toDir := _toDir + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
end else
begin
_fromDir:= _fromDir + SR.Name + #0#0;
_toDir := _toDir + SR.Name + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
end;
Result := (0 = ShFileOperation(fos));
_fromDir:= ExtractFilePath(_fromDir);
_toDir:= ExtractFilePath(_toDir);
end;
res := FindNext(SR);
end;
finally
FindClose(SR);
end;
end else
begin
_fromDir:= RemoveBackslashUnlessRoot(_fromDir) + #0#0;
_toDir := RemoveBackslashUnlessRoot(_toDir) + #0#0;
fos.pFrom := PChar(_fromDir);
fos.pTo := PChar(_toDir);
Result := (0 = ShFileOperation(fos));
end;
end;

procedure RestoreBackup(backDir: string);
begin
BackupDir(backDir, ExpandConstant('{app}'), True);
DelTree(backDir, true, true, true);
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usdone then
begin
RestoreBackup(ExpandConstant('{app}\Backup\'));
end;
end;
У меня в принципе и скрипт из первого сообщения работает, но будет ли отображаться в полосе прогресс бара это резервное копирование?
 

South

Знаток
Проверенный
еще один пример копирования файлов с прогрессбаром. лет 8 назад выкладывал
[Setup]
AppName=My Program
AppVerName=My Program v.1.2
DefaultDirName={pf}\My Program

[Languages]
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"

Код:
type
  TMsg = record
  hwnd: HWND;
  message: UINT;
  wParam: Longint;
  lParam: Longint;
  time: DWORD;
  pt: TPoint;
  end;

const
  BlockSize = 65536;
  PM_REMOVE = 1;
  WM_QUIT  = $0012;

var
  Page: TInputDirWizardPage;
  PB,PB2: TNewProgressBar;
  L1,L2,L3:TNewStaticText;
  DS,CS:Extended;
  CancelBtn:TButton;
  CancelOperation:boolean;

function PeekMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessageA@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMsg): BOOL; external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMsg): Longint; external 'DispatchMessageA@user32.dll stdcall';

procedure AppProcessMessage;
var
  Msg: TMsg;
begin
  while PeekMessage(Msg, WizardForm.Handle, 0, 0, PM_REMOVE) do begin
  TranslateMessage(Msg);
  DispatchMessage(Msg);
  end;
end;

procedure CopyFile_(Source,Target:string);
var
  FileSize,ElapsedSize,CopySize:LongWord;
  SourceStream,TargetStream:TFileStream;
  a:Extended;
begin
  SourceStream:=TFileStream.Create(Source,fmOpenRead);
  TargetStream:=TFileStream.Create(Target,fmCreate);
  ElapsedSize:=SourceStream.Size-SourceStream.Position;
  FileSize:=SourceStream.Size;
  PB.Max:=100;
  PB.Position:=0;
  L1.Caption:=ExtractFileName(Source);
  L2.Caption:='0 %';
  while ElapsedSize>0 do begin
  if ElapsedSize<BlockSize then CopySize:=ElapsedSize else CopySize:=BlockSize;
  TargetStream.CopyFrom(SourceStream,CopySize);
  ElapsedSize:=SourceStream.Size-SourceStream.Position;
  a:=(ElapsedSize div FileSize)*100;
  a:=100-a; //хз че здесь за глюки, но писать эти действия в одну строчку нельзя
  PB.Position:=Round(a);//SourceStream.Position;
  L2.Caption:=IntToStr(PB.Position)+' %'
  L2.Invalidate;
  CS:=CS+BlockSize;//(1024*1024);
  a:=CS*100;  //такая же ересь, написав все
  a:=a/DS  //в одну строку ни хрена не считается
  PB2.Position:=Round(a);//Round(CS*100/DS);
  L3.Caption:=IntToStr(PB2.Position)+' %'
  AppProcessMessage;
  if CancelOperation then Break;
  end;
  //FileSetDate(TargetStream.Handle,FileGetDate(SourceStream.Handle));
  //дату файла надобы сменить на старую, возиться лень
  TargetStream.Free;
  SourceStream.Free;
  if CancelOperation then DeleteFile(Target);
end;

procedure CopyDir(const FromDir,ToDir,FileMask:string;IncludeSubDirs:boolean);
var
  FindRec:TFindRec;
  sFileName,fd,td:string;
//  i,j:Int64;
  ii:integer;
begin
  fd:=AddBackslash(FromDir);
  td:=AddBackslash(ToDir);
  ForceDirectories(td);
  if FindFirst(fd+FileMask,FindRec) then begin
  try
  repeat
  sFileName:=fd+FindRec.Name;
  if ((FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0) then CopyFile_(sFileName,td+FindRec.Name)
  else
  if IncludeSubDirs then
  if (FindRec.Name<>'') and (FindRec.Name<>'.') and (FindRec.Name<>'..') then
  CopyDir(sFileName,td+FindRec.Name,FileMask,IncludeSubDirs);
  AppProcessMessage;
  until not (FindNext(FindRec) and not CancelOperation);
  finally
  FindClose(FindRec);
  end;
  end;
end;

procedure GetDirSize(const Dir,FileMask:string;IncludeSubDirs:boolean);
var
  FindRec:TFindRec;
  sFileName,d:string;
//  i:Int64;
begin
  d:=AddBackslash(Dir);
  if FindFirst(d+FileMask,FindRec) then begin
  try
  repeat
  sFileName:=d+FindRec.Name;
  if ((FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0) then DS:=DS+4294967295*FindRec.SizeHigh+FindRec.SizeLow
  else
  if IncludeSubDirs then
  if (FindRec.Name<>'') and (FindRec.Name<>'.') and (FindRec.Name<>'..') then GetDirSize(sFileName,FileMask,IncludeSubDirs);
  AppProcessMessage;
  until not (FindNext(FindRec) and not CancelOperation);
  finally
  FindClose(FindRec);
  end;
  end;
end;

procedure CancelBtnClick(Sender:TObject);
begin
  CancelOperation:=True;
end;

procedure InitializeWizard();
begin
  Page:=CreateInputDirPage(wpSelectTasks,'Пример копирования файлов', 'Укажите каталоги','',False,'NewFolder');
  Page.Add('Откуда копировать');
  Page.Values[0] := 'e:\1\1';//'c:\';//ExpandConstant('{userappdata}');
  Page.Add('Куда копировать');
  Page.Values[1] := 'e:\1\2';//'c:\';
  PB:=TNewProgressBar.Create(WizardForm);
  with PB do begin
  Left:=0;
  Top:=130;
  Width:=Page.Surface.Width;
  Parent:=Page.Surface;
  end;
  L1:=TNewStaticText.Create(WizardForm);
  with L1 do begin
  Left:=0;
  Top:=115;
  AutoSize:=False;
  Width:=Page.Surface.Width-30;
  Parent:=Page.Surface;
  end;
  L2:=TNewStaticText.Create(WizardForm);
  with L2 do begin
  Left:=Page.Surface.Width-30;
  Top:=115;
  AutoSize:=False;
  Width:=30;
  //Alignment:=taRightJustify;
  Parent:=Page.Surface;
  end;
  PB2:=TNewProgressBar.Create(WizardForm);
  with PB2 do begin
  Left:=0;
  Top:=170;
  Width:=Page.Surface.Width;
  Parent:=Page.Surface;
  end;
  L3:=TNewStaticText.Create(WizardForm);
  with L3 do begin
  Left:=Page.Surface.Width-30;
  Top:=155;
  AutoSize:=False;
  Width:=30;
  //Alignment:=taRightJustify;
  Parent:=Page.Surface;
  end;
  CancelBtn:=TButton.Create(WizardForm);
  with CancelBtn do begin
  Left:=Page.Surface.Width-150;
  Top:=200;
  Width:=150;
  Parent:=Page.Surface;
  Caption:='Отменить копирование';
  OnClick:=@CancelBtnClick;
  end;

end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result:=True;
  if CurPageID=Page.ID then begin
  L1.Caption:='Подсчет размера "'+Page.Values[0]+'"';
  L2.Caption:='';
  L3.Caption:='';
  DS:=0;
  PB.Position:=0;
  PB.Max:=100;
  PB2.Position:=0;
  PB2.Max:=100;
  CS:=0;
  CancelOperation:=False;
  WizardForm.NextButton.Enabled:=False;
  WizardForm.CancelButton.Enabled:=False;
  WizardForm.BackButton.Enabled:=False;
  GetDirSize(Page.Values[0],'*.*',True);
  CopyDir(Page.Values[0],Page.Values[1],'*.*',True);
  WizardForm.NextButton.Enabled:=True;
  WizardForm.CancelButton.Enabled:=True;
  WizardForm.BackButton.Enabled:=True;
  end;
end;


[/spoiler]
 
Сверху