Jump to content
RTollison

IFileOperation recursion happens when set not to

Recommended Posts

function CopyFileIFileOperationForceDirectories(const srcFile, destFile : string) : boolean;
//works on Windows >= Vista and 2008 server
var
  r : HRESULT;
  fileOp: IFileOperation;
  siSrcFile: IShellItem;
  siDestFolder: IShellItem;
  destFileFolder, destFileName : string;
  pbc : IBindCtx;
  w32fd : TWin32FindData;
  ifs : TFileSystemBindData;
begin
  result := false;

  destFileFolder := ExtractFileDir(destFile);
  destFileName := ExtractFileName(destFile);

  //init com
  r := CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE);
  if Succeeded(r) then
  begin
    //create IFileOperation interface
    r := CoCreateInstance(CLSID_FileOperation, nil, CLSCTX_ALL, IFileOperation, fileOp);
    if Succeeded(r) then
    begin
      //set operations flags
      r := fileOp.SetOperationFlags(FOF_FILESONLY OR FOF_NORECURSION OR FOF_NOCONFIRMATION OR FOFX_NOMINIMIZEBOX);
      if Succeeded(r) then
      begin
        //get source shell item
        r := SHCreateItemFromParsingName(PChar(srcFile), nil, IShellItem, siSrcFile);
        if Succeeded(r) then
        begin
          //create binding context to pretend there is a folder there
          if NOT DirectoryExists(destFileFolder) then
          begin
            ZeroMemory(@w32fd, Sizeof(TWin32FindData));
            w32fd.dwFileAttributes := FILE_ATTRIBUTE_DIRECTORY;
            ifs := TFileSystemBindData.Create;
            ifs.SetFindData(w32fd);
            r := CreateBindCtx(0, pbc);
            r := pbc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, ifs);
          end
          else
            pbc := nil;

          //get destination folder shell item
          r := SHCreateItemFromParsingName(PChar(destFileFolder), pbc, IShellItem, siDestFolder);

          //add copy operation
          if Succeeded(r) then r := fileOp.CopyItem(siSrcFile, siDestFolder, PChar(destFileName), nil);
        end;

        //execute
        if Succeeded(r) then r := fileOp.PerformOperations;

        result := Succeeded(r);

        OleCheck(r);
      end;
    end;

    CoUninitialize;
  end;
end;

when i issue the command to copy, it copies all of the subfolders when all i want it the specified folder only.

CopyFileIFileOperationForceDirectories('c:\dir1', 'd:\dir1')

it shows the copying of c:\dir1 to d:\dir1 but then when that is done it shows to be copying c:\dir1\subdir1 and all of its files. i only wish to copy the directory and none of the subfolders

 

 

Share this post


Link to post

You have to enumerate all the files and copy them. Put these files into a double null terminated list. 

 

COM should not be initialised here. It needs to be initialised by the owner of the thread. 

Share this post


Link to post
9 hours ago, David Heffernan said:

Put these files into a double null terminated list. 

That applies to SHFileOperation(), but not to IFileOperation.  You would have to either:

 

- call CopyItem() for each desired source file individually.

 

- call CopyItems() for the whole list of desired files.

 

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×