0

i'm having touble using SHFileOperation do Copy and delete *.mb and *.db files

the CopyFiles code works great, copy all files and create the folder if needed but when i call DeleteFiles code something strange happens, all files in 'bkp' folder are deleted, but not the folder.

when i try to access the folder it say's "Access denied", after i close my application, folder get deleted ok.

here my procedure :

procedure TForm1.Button1Click(Sender: TObject);
var
  shFOS : TShFileOpStruct;
  FileNameTemp: string;
  sr: TSearchRec;
begin
  try
    shFOS.Wnd := Application.MainForm.Handle;
    shFOS.wFunc := FO_COPY;
    shFOS.pFrom := PChar(DBEdit4.text+'\*.db' + #0);
    shFOS.pTo := PChar(ExtractFilePath(ParamStr(0))+'bkp'+ #0);
    shFOS.fFlags := FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
    SHFileOperation(shFOS);

    shFOS.Wnd := Application.MainForm.Handle;
    shFOS.wFunc := FO_COPY;
    shFOS.pFrom := PChar(DBEdit4.text+'\*.mb' + #0);
    shFOS.pTo := PChar(ExtractFilePath(ParamStr(0))+'bkp'+ #0);
    shFOS.fFlags := FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
    SHFileOperation(shFOS);
  finally
    application.ProcessMessages;
    //zip copied files
    FilenameTemp:=ExtractFilePath(ParamStr(0))+FormatDateTime('dd-mm-yyyy-hh-nn-zzz',now)+'.zip';
    ZipForge1.FileName := FilenameTemp;
    ZipForge1.OpenArchive(fmCreate);
    ZipForge1.BaseDir := ExtractFilePath(ParamStr(0))+'bkp';
    ZipForge1.AddFiles('*.*');
    ZipForge1.CloseArchive();
  end;

// check if any files were copied in order to create the zip file and upload it
// if i skip the FindFirst code works greate
if (FindFirst(ExtractFilePath(ParamStr(0))+'bkp\*.db',faAnyFile,sr)=0) or (FindFirst(ExtractFilePath(ParamStr(0))+'bkp\*.mb',faAnyFile,sr)=0) then
    begin

    idftp1.Username:=user.Text;
    idftp1.Password:=pw.Text;
    idftp1.Port:=21;
    idFTP1.Passive := false;

    try
      idftp1.Connect;
    except
      on E : Exception do
      begin
        Show;
        if (Pos(LowerCase('user cannot'), LowerCase(E.Message)) > 0) and (Pos(LowerCase('log in.'), LowerCase(E.Message)) > 0) then
          Application.MessageBox('USUÁRIO OU SENHA INVÁLIDO',Pchar(appCaption),mb_iconError+mb_ok)
        else if (Pos(LowerCase('socket error'), LowerCase(E.Message)) > 0) and (Pos(LowerCase('host not found.'), LowerCase(E.Message)) > 0) then
          Application.MessageBox('FALHA NA CONEXÃO, VERIFIQUE SUA INTERNET',Pchar(appCaption),mb_iconError+mb_ok)
        else if e.Message<>'' then
        begin
          Application.MessageBox(Pchar('ERRO DESCONHECIDO, FAVOR ENTRAR EM CONTATO COM NOSSO SUPORTE TÉCNICO'
                                      +#13+#10
                                      +#13+#10+'INFORME O SEGUINTE ERRO :'
                                      +#13+#10
                                      +#13+#10+e.Message),Pchar(appCaption),mb_iconError+mb_ok);
        end;

        exit;
      end;
    end;

    try
     idftp1.Put(FileNameTemp,ExtractFileName(FilenameTemp));
    finally
      //DeleteFiles
      idftp1.Disconnect;
      ZeroMemory(@shFOS, SizeOf(TShFileOpStruct));
      shFOS.Wnd := Application.MainForm.Handle;
      shFOS.wFunc := FO_DELETE;
      shFOS.pFrom := PChar(ExtractFilePath(ParamStr(0))+'bkp'+#0);
      shFOS.fFlags := FOF_NOCONFIRMATION;
      SHFileOperation(shFOS); // The error occurs here, files in bkp folder are deleted
    //but the folder still exists, and everytime i try to make another backup or remove the
//folder manually through windows the error os "Access denied"
    end;
  end;
end;
tshepang
  • 12,111
  • 21
  • 91
  • 136
Rebelss
  • 364
  • 1
  • 5
  • 15
  • 1
    How about adding some error checking? What is the return value of the API call? – David Heffernan Dec 29 '13 at 23:34
  • i already did, the return is 2 on microsoft website i found the description : ERROR_FILE_NOT_FOUND 2 (0x2) The system cannot find the file specified. maybe the findFirst that i use between Copy and delete are messing with ShFileOperation ? – Rebelss Dec 29 '13 at 23:46
  • There is no error checking in the code in the question. – David Heffernan Dec 29 '13 at 23:50
  • The return of 'SHFileOperation(shFOS);' is 2, i implement after o post my question, sorry. – Rebelss Dec 29 '13 at 23:52
  • 2 just means failure. No more. Read the docs. Don't try to program against an api without reading the docs. Again, there's no error checking in the Q. Don't expect us to debug details that appear in comments. Fix the question. – David Heffernan Dec 30 '13 at 00:00
  • Also, don't hide code from us. Don't talk about FindFirst. Show the code! An SSCCE is needed here. Or perhaps it will be obvious from the code. Maybe you never call FindClose. Not much fun trying to guess. – David Heffernan Dec 30 '13 at 00:02
  • you are right, i'll update the procedure. – Rebelss Dec 30 '13 at 00:19

1 Answers1

2

The obvious problem in the updated code is that you call FindFirst, but do not match those with calls to FindClose. Quite possibly the search handles that you fail to close are what blocks the delete operation from completing.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • There are lots of other problems with the code that I don't want to get in to. Repetition. Poor try/finally blocks. Wild exception handling. Nasty ProcessMessages calls. You do need to break this down and factor it better. But I don't really want to get in to all of that here. – David Heffernan Dec 30 '13 at 00:26
  • i'll re-write it good now that i'm know the source of the problem, thanks David, FindClose(sr); works like a charm! – Rebelss Dec 30 '13 at 00:32