단순무식한 backup 프로그램을 만들었는데
프로그램이 종료가 안되어서 그럽니다. 좀 도와주세요.
종료 버튼을 누르면 메인 폼, Form1은 사라집니다만은
작업관리자로 조사해보면 프로세스에 프로그램 이름이 그대로 있습니다.
프로세스는 종료가 안되네요. 그러니까 프로그램을 실행할 수록 메모리를 계속 잡아 먹는 것입니다.
좀 도와주세요.
unit BackupMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, CheckLst, Buttons, ToolWin, ComCtrls, EditBtn,
AdvEdBtn, AdvDirectoryEdit, ExtCtrls, ShellAPI, Gauges, AdvEdit;
type
TForm1 = class(TForm)
CoolBar1: TCoolBar;
BackupstartBtn: TSpeedButton;
AddDirBtn: TSpeedButton;
DelDirBtn: TSpeedButton;
OptionBtn: TSpeedButton;
CloseBtn: TSpeedButton;
CheckListBox1: TCheckListBox;
Label1: TLabel;
AdvDirectoryEdit1: TAdvDirectoryEdit;
Gauge1: TGauge;
Label2: TLabel;
BackupAbortBtn: TSpeedButton;
StatusBar1: TStatusBar;
Button1: TButton;
Button2: TButton;
procedure AddDirBtnClick(Sender: TObject);
procedure CloseBtnClick(Sender: TObject);
procedure DelDirBtnClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BackupstartBtnClick(Sender: TObject);
procedure BackupAbortBtnClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FileBackupThread : TThread; // 화일복사를 Thread를 이용하여 실시하여야 여러가지
// 인터페이스 작업을 할수 있다.
public
{ Public declarations }
end;
var
Form1: TForm1;
ProgramDir, BackupDir: string;
TotalBackupFileSize, FinishedFileSize : Int64;
implementation
uses AddDir;
{$R *.dfm}
type
TFileBackupThread = Class(TThread)
SizeCheckFlag : Boolean;
private
procedure BackupStart;
procedure BackupComplete;
procedure FileFindCurrentFolder(Target:string;var Found:string;var Time,Size:integer);
procedure CopyFileWin2000(const Source,Destination: String);
procedure StartCopy;
procedure CopyFileInFolder(RootDir:string);
protected
procedure Execute; override;
end;
procedure TFileBackupThread.FileFindCurrentFolder(Target:string;var Found:string;var Time,Size:integer);
var
filen : TSearchRec;
DosError : integer;
begin
DosError := FindFirst(Target,faAnyFile,filen);
if (DosError = 0) then
begin
Found := filen.name;
Time := filen.Time;
Size := filen.Size;
end;
FindClose(filen);
end;
procedure TFileBackupThread.CopyFileWin2000(const Source,Destination: String);
var
SHFileOpStruct : TSHFileOpStruct;
begin
FillChar(SHFileOpStruct,SizeOf(TSHFileOpStruct),#0);
SHFileOpStruct.Wnd:= Form1.Handle;
SHFileOpStruct.wFunc:=FO_COPY;
SHFileOpStruct.fFlags:=FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;;
SHFileOpStruct.hNameMappings:=nil;
SHFileOpStruct.pFrom:=PChar(Source+#0+#0);
SHFileOpStruct.pTo:=PChar(Destination+#0+#0);
ShFileOperation(SHFileOpStruct);
end;
procedure TFileBackupThread.StartCopy;
var
Dir,TDir,filename,dums : string;
FileInfo : TSearchRec;
i,DosError : integer;
STime, TTime,Ssize,Tsize : integer;
begin
GetDir(0,Dir); TDir := Dir;
filename := '';
i:=Pos(':',TDir); Delete(TDir,1,i);
TDir := BackupDir + TDir;
DosError := FindFirst('*.*',faAnyFile,FileInfo);
while (DosError = 0) do
begin
Filename := FileInfo.Name;
STime := FileInfo.Time;
TTime := FileAge(TDir+''+filename);
if SizeCheckFlag then
begin
TotalBackupFileSize := TotalBackupFileSize + FileInfo.Size;
Form1.StatusBar1.Panels[1].Text :=
Format('%S %d: %S',['총백업될 화일크기 계산중',TotalBackupFileSize div 1000000,'M bytes']);
end
else
begin
FinishedFileSize := FinishedFileSize + FileInfo.Size;
Form1.Gauge1.Progress := ((FinishedFileSize*100) div TotalBackupFileSize );
Form1.StatusBar1.Panels[1].Text := Format('%s',[Dir+''+filename]);
end;
if (STime > TTime) and (not SizeCheckFlag) then
begin
CopyFile(PChar(Dir+''+filename),PChar(TDir+''+filename),false);
// CopyFile2000(Dir+''+filename,TDir+''+filename);
// : 윈도 탐색기에서 화일복사하는 방법같은 방법 애니메이션을 보여줌.
end;
DosError := FindNext(FileInfo);
end;
FindClose(FileInfo);
end;
Procedure TFileBackupThread.CopyFileInFolder(RootDir:string);
var
Dirinfo : TSearchRec;
Doserror : integer;
NewDir : PChar;
s,dum : string;
begin { mainbody : TFileBackupThread.CopyFileInFolder(RootDir:string) }
ChDir(RootDir);
StartCopy;
DosError := FindFirst('*.*',faAnyfile,Dirinfo);
while DosError = 0 do
begin
if (Dirinfo.Name <>'.') and (Dirinfo.Name <> '..') and (Dirinfo.attr = faDirectory) then
begin
if ( Pos('Document for',Dirinfo.Name)>0) then
dum := NewDir;
GetDir(0,dum);
ChDir(Dirinfo.Name);
GetDir(0,s);
Delete(s,1,Pos('',s));
NewDir := Pchar(BackupDir + ''+s);
if not DirectoryExists(NewDir) then
if not CreateDirectory(NewDir,nil) then
// if not CreateDir(NewDir) then
raise Exception.Create('Cannot create '+NewDir);
CopyFileInFolder(DirInfo.name);
ChDir(dum);
end;
DosError := FindNext(Dirinfo);
end;
FindClose(Dirinfo);
end;
Procedure TFileBackupThread.BackupStart;
var
i: integer;
s:string;
begin
if SizeCheckFlag then
begin
for i := 1 to Form1.CheckListBox1.Count do
begin
if Form1.CheckListBox1.Checked[i-1] then
CopyFileInFolder(Form1.CheckListBox1.Items[i-1]);
end;
i := trunc(TotalBackupFileSize / 1024 /1024);
Form1.StatusBar1.Panels[1].Text:= Format('%S %d: %S',['총백업에 필요한 디스크 크기:',i,'M bytes']);
SizeCheckFlag := false;
end;
FinishedFileSize := 0;
for i := 1 to Form1.CheckListBox1.Count do
if Form1.CheckListBox1.Checked[i-1] then
CopyFileInFolder(Form1.CheckListBox1.Items[i-1]);
end;
procedure TFileBackupThread.Execute;
begin
if TotalBackupFileSize = 0 then
SizeCheckFlag := true
else
SizeCheckFlag := false;
BackupStart;
Synchronize(BackupComplete);
end;
Procedure TFileBackupThread.BackupComplete;
begin
Form1.StatusBar1.Panels[1].Text:= Format('%S ',['백업이 끝났습니다.']);
Form1.BackupstartBtn.enabled := true;
Form1.BackupAbortBtn.enabled := false;
Form1.AddDirBtn.Enabled := true;
Form1.DelDirBtn.Enabled := true;
TotalBackupFileSize := 0;
Form1.Gauge1.Progress := 0;
end;
procedure TForm1.AddDirBtnClick(Sender: TObject);
begin
AddDirForm.Show;
end;
procedure TForm1.CloseBtnClick(Sender: TObject);
begin
Form1.Close;
end;
procedure TForm1.DelDirBtnClick(Sender: TObject);
begin
if CheckListBox1.ItemIndex > -1 then
CheckListBox1.Items.Delete(CheckListBox1.ItemIndex);
end;
procedure TForm1.FormShow(Sender: TObject);
var
f : TextFile;
s : string;
begin
ProgramDir := getCurrentDir;
if FileExists('BackupList.Txt') then
begin
AssignFile(f,'BackupList.Txt'); reset(f);
Readln(f,s);
Form1.AdvDirectoryEdit1.Text := s;
while Not EOF(f) do
begin
readln(f,s);
ChecklistBox1.Items.Add(s);
ChecklistBox1.Checked[ChecklistBox1.Count-1] := true;
end;
CloseFile(f);
end;
end;
procedure InitFileSave;
var
f : TextFile;
i : integer;
s : string;
begin
s := ProgramDir + 'Backuplist.txt';
{$I-}
assignFile(f,s);
rewrite(f);
writeln(f,Form1.AdvDirectoryEdit1.Text);
for i:= 1 to Form1.CheckListBox1.Count do
begin
writeln(f,Form1.CheckListBox1.Items[i-1]);
end;
CloseFile(f);
Form1.Close;
{$I+}
end;
procedure CreateTargetDir(RootDir:string);
var
DirR, DirT,s : string;
i : integer;
TargetDrive : string;
begin
DirR := RootDir;
i:= Pos('',DirR); Delete(DirR,1,i);
DirT := BackupDir;
Form1.StatusBar1.Panels[1].Text := '백업할 곳에 폴더를 만들고 있습니다.';
if not DirectoryExists(DirT) then
CreateDir(DirT);
while (i <> 0) do
begin
i:= Pos('',DirR);
if i > 0 then
S:= Copy(DirR,1,i-1)
else
S:= DirR;
DirT := DirT +''+S;
if not DirectoryExists(DirT) then
begin
if not CreateDir(DirT+'') then
begin
ShowMessage('"'+DirT+'" Directory is not created');
exit;
end;
end;
Delete(DirR,1,i);
end;
Form1.StatusBar1.Panels[1].Text := '백업을 시작합니다.';
end;
procedure TForm1.BackupstartBtnClick(Sender: TObject);
var
i : integer;
begin
Form1.BackupstartBtn.enabled := false;
Form1.BackupAbortBtn.enabled := true;
Form1.AddDirBtn.Enabled := false;
Form1.DelDirBtn.Enabled := false;
BackupDir := AdvDirectoryEdit1.Text;
// Create Direcoty in bacup target directory
for i := 1 to CheckListBox1.Count do
if CheckListBox1.Checked[i-1] then
CreateTargetDir(CheckListBox1.Items[i-1]);
// Backup Starting as a Thread
if Assigned (FileBackupThread) then
FreeAndNil(FileBackupThread);
FileBackupThread := TFileBackupThread.Create(True);
with FileBackupThread do
begin
priority := tpLower;
Resume;
end;
end;
procedure TForm1.BackupAbortBtnClick(Sender: TObject);
begin
if Assigned (FileBackupThread) then
// FreeAndNil(FileBackupThread);
Form1.StatusBar1.Panels[1].Text := '백업이 취소되었습니다.';
if MessageDlg('백업을 취소하셨습니다. 최소할려면 프로그램을 종료해야합니다. 중단할까요?', mtInformation,
[mbYes, mbCancel], 0) = mrYes then
Form1.CloseBtnClick(Sender);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
for i := 1 to CheckListBox1.Count do
CheckListBox1.Checked[i-1] := false;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i : integer;
begin
for i := 1 to CheckListBox1.Count do
CheckListBox1.Checked[i-1] := true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
InitFileSave;
if Assigned(FileBackupThread) then
FileBackupThread.Free;
end;
end.
Thread 를 생성시 FreeOnTerminate 를 이용하시고
종료시 Terminate 를 호출하는 방식으로
바꿔보세요.
그럼~ 즐거운 프로그래밍 하시길~