Q&A

  • 프로그램 종료에 문제가..
단순무식한 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.
1  COMMENTS
  • Profile
    구창민 2003.02.06 23:39
    정확한 원인이 아닐수도 있습니다만,

    Thread 를 생성시 FreeOnTerminate 를 이용하시고

    종료시 Terminate 를 호출하는 방식으로

    바꿔보세요.

    그럼~ 즐거운 프로그래밍 하시길~


    • 머슴
      2003.02.07 06:28
        바뀐 시험으로는 책이 안나온데요... 수지가 안맞는다나...   방법은 VB책의 문...
    • 델파이정복자
      2003.02.07 20:05
      답변 고마웠습니다... 수고하세여.. 님.........
    • 이뿌이
    • 2003.02.06 20:42
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 하얀까마귀
      2003.02.06 20:47
      안녕하세요 하얀까마귀 입니다. 디비 그리드라면 dataSet에 연결이 되어있을껍니다. 디비그리드의 클...
    • 이뿌이
      2003.02.06 20:48
      답변해 주셔서 정말 감사합니다. 즐프하세염
    • 이병훈
      2003.02.07 07:20
      안녕하세요. 헐.~ 저와 같은 이름이네여. 푸헐~ 머 똑같습니다. 솔라리스라구 다를 것이 있나요...
    • 구창민
      2003.02.06 23:17
      지금 델파이코리아(www.delphikorea.com)로 달려가셔서 강좌나 팁란중 어딘가에 권용길님이 쓰신 '...
    • KDDG_ZZOM
      2003.02.06 20:38
      아마도... BDE Administrator에서 Configuration텝에서 Native의 오라클을 선택하시고 VENDOR INIT인가???...
    • 주엔이
    • 2003.02.06 19:32
    • 0 COMMENTS
    • /
    • 0 LIKES
    • 김상수
    • 2003.02.06 06:09
    • 1 COMMENTS
    • /
    • 0 LIKES
    • KDDG_ZZOM
      2003.02.06 19:09
      글세요...^^ 근데 쿼리문이 얼마나 복잡하길레 사이즈걱정을... 예전에 한 1000라인되는 쿼리문도 문제...
    • 백호
    • 2003.02.06 05:21
    • 0 COMMENTS
    • /
    • 0 LIKES
    • 권민호
    • 2003.02.06 05:19
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 구창민
      2003.02.06 23:39
      정확한 원인이 아닐수도 있습니다만, Thread 를 생성시 FreeOnTerminate 를 이용하시고 종료시 Termi...
    • 아폴론
    • 2003.02.06 04:20
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 아폴론
      2003.02.06 21:31
      with ADOConnection1 do begin    try       connectionstri...
    • 한방러쉬
      2003.02.06 23:56
      SQL 서버 클라이언트 안깔려도 됩니다요...
    • 이뿌이
    • 2003.02.06 04:13
    • 0 COMMENTS
    • /
    • 0 LIKES
    • KDDG_hyun
    • 2003.02.06 02:42
    • 5 COMMENTS
    • /
    • 0 LIKES
    • 구창민
      2003.02.06 03:09
      현아 연산식이 길게 늘어졌구나.. 연산 우선순위를 차례로 나열해서 코딩해두고, 하나씩 연산해서 밑...
    • KDDG_hyun
      2003.02.06 03:18
      울 길드 게시판에두 적었는데 String 로 형식을 변환함면 갑이 제대로 나와요.. 아 머리아포요..
    • 성더기
      2003.02.06 09:14
      소수점 이하는 무저건 잘라 버릴거 같은디... 아닌가?..ㅡㅡ;;
    • KDDG_hyun
      2003.02.06 18:52
      Trunc 말고 round 도 써 봤는데 매 한가지고.. 둘다 안써봐도 그러고.. 그게 아니더라도 걍 0 이 나...
    • 또치
      2003.02.06 20:00
      A := Trunc((Aa * Q_qry1.FieldByName('AAa').AsInteger / 100 + Ab *    Q_qry1.Fiel...
    • 유재훈
    • 2003.02.06 02:21
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 구창민
      2003.02.06 02:53
      안녕하세요~ 구창민입니다. 머 여러가지 방법이 있겠지만, 어플내에서만 동작하는 훅을 설치해보세여...
    • 도니
    • 2003.02.06 02:20
    • 2 COMMENTS
    • /
    • 0 LIKES
    • KDDG_Cali
      2003.02.06 03:13
      indexFieldNames 으로는 해결방법이 없는듯 한데.. indexName 으로 써 보세요.. SimpleDataSet.Index...
    • 도니
      2003.02.06 19:54
      아직 안해봐서 되는지 안되는지는 모르겠지만.. 신경써주셔서 감사합니다..^^
    • KDDG_BaSTaD
      2003.02.06 21:52
      ==> 말그대로 등록되지 않은 이미지 확장자라는 뜻입니다. 기본적으로 Graphics.pas 에는 bmp만 등록...
    • KDDG_ZZOM
      2003.02.06 18:56
      image1.picture.loadfromfile('c:programimagebackground풍경구 름.jpg'); 여기서... 디렉토리가 잘못된...
    • KDDG_ZZOM
      2003.02.06 19:02
      OnEnter에서 해보세요... 저도 예전에 비슷한걸 한것같네요... 근데 개인적으로 콤보박스는 리소스를 ...
    • 성더기
      2003.02.06 09:17
      ComboBox에 값을 채우는 프로시져를 하나 만드시구 디비가 변경될때마다 그넘을 호출해 주는 것은 어떨까...
    • 델파이탐크루즈
      2003.02.06 02:17
      방법론을 알려드릴께여... 한번 해보세요.. 처음에는 폼 생성될때 Query로 끌고 오셔서 item add...
    • 또치
    • 2003.02.06 01:29
    • 5 COMMENTS
    • /
    • 0 LIKES
    • 한원희
      2003.02.06 07:26
      안녕하세요. 한원희입니다. 동일한 함수로 정의하고, 각 DLL을 어떻게 사이트별로 구별하느냐가 문제군...
    • 또치
      2003.02.06 20:06
      답변 고맙습니다. ^^ 근데여..... 각 DLL 마다 자신의 정보를 알려주는 함수를 동일한 이름으로 추가...
    • 한원희
      2003.02.06 20:29
      안녕하세요. 한원희입니다. 음... 아래와 같이 정적으로 하게되면, 추가되는 DLL을 적용할 수가 없게 되...
    • 또치
      2003.02.06 21:29
      정말 고맙습니다. 책에 있는 줄 알았으면 책을 더 찾아보았을텐데.... ㅡㅡ; 덕분에 고민고민 했던게...
    • 또치
      2003.02.06 21:27
      정말 고맙습니다. 책에 있는 줄 알았으면 책을 더 찾아보았을텐데.... ㅡㅡ; 덕분에 고민고민 했던게...
    • 하얀까마귀
      2003.02.06 00:44
      안녕하세요 하얀까마귀 입니다. 폼의 프로퍼티에 보시면 position 을 조정해주시면 됩니다. poMainFo...
    • 도니
    • 2003.02.05 22:53
    • 4 COMMENTS
    • /
    • 0 LIKES
    • 윤민규
      2003.02.05 23:07
      update Table1 set Date = 'YYYYMMDD' where Date = (Select max(Date) From Table1) 이런 식으로 쓰면 ...
    • 도니
      2003.02.05 23:26
    • 이중철
      2003.02.05 23:04
      냉무
    • 도니
      2003.02.05 23:28