How can I copy a folder including all subfolders to another location?

Hi all,

I have an “assets” folder with subfolders like:
C:\TEMP\assets
C:\TEMP\assets\css
C:\TEMP\assets\fonts
C:\TEMP\assets\js\

Now I would like to copy the complete “assets” folder C:\TEMP\assets*.* including all subfolders to:
%APPDATA%

So that I get:
%APPDATA%\assets
%APPDATA%\assets\css
%APPDATA%\assets\fonts
%APPDATA%\assets\js\

Is this possible with a default Clarion command? Or some smart piece of code?

Thank you and best regards
Jeffrey

I think you can get there with your old friend SHFileOperation, using FO_Copy. :slight_smile:
Pretty sure the default is to recurse. SHFILEOPSTRUCTA (shellapi.h) - Win32 apps | Microsoft Learn

Thank you Jeff!

I will try to figure out how to use this API in Clarion.

Best regards
Jeffrey

There are some posts and equates about it this thread Windows API help with CopyFileExA() and Callback to show Progress - #2 by CarlBarnes

You do have to be careful with SHFileOperation to pass it correct parameters or bad things can happen, see the various comments on the MSDN page like …

Remarks

Important You must ensure that the source and destination paths are double-null terminated. A normal string ends in just a single null character. If you pass that value in either the source or destination members, the function will not realize when it has reached the end of the string and will continue to read on in memory until it comes to a random double null value. This can at least lead to a buffer overrun, and possibly the unintended deletion of unrelated data.


A simpler way might be to RUN() a DOS command either XCOPY or RoboCopy. PowerShell would be another. I like RoboCopy, but it does have a lot of switches. It can give you a log. AI can help.

Thank you Carl!

I also like RoboCopy but don’t like the black splash window which the RUN command shows.

Best regards
Jeffrey

Have a look at Hide Command Prompt Window when RUN Batch file for ideas of how to hide the command window when you Run() a command.

Thank you all, enough ideas.

Best regards
Jeffrey

Hi Jeffrey

Capesoft Oddjob does a great job of controlling and hiding running of batch files
and you get feedback into a variable,
which you can then display in your clarion window

regards

Johan

1 Like

Hi Jeffrey,

I use something like this

loc:FileName='cmd.exe'
loc:Parameters='/c robocopy "'&clip(glo:uncInstallatiepad)&'" "'&clip(loc:doelmap)&'" *.* /XF robocopy.* *.ini *.log /LEV:1 /Z /XA:SH /NDL /NJH /NJS /nc /ns /np /MT:8 /LOG:reserveprogramma.log'

if shellexecuteex_wacht(loc:FileName,,loc:Parameters,1,1)  
   message('Er is een fout opgetreden ('&runcode()&') bij kopieren van de programmabestanden. Zie reserveprogramma.log','Fout',ICON:Exclamation)
   cycle 
end   

--------


shellexecuteex_wacht PROCEDURE  (String pFile,<String pDirectory>,<String pParameters>,<Long pWait>,<Long pHide>) ! Declare Procedure

SHi                     LIKE(D_SHELLEXECUTEINFO)
new:File                &CSTRING
new:Param           &CSTRING
new:Directory       &CSTRING
Verb                     long(0) 
hProc                   UNSIGNED!LONG 
lRetCode              LONG
resultaat               LONG

SEE_MASK_NOCLOSEPROCESS  EQUATE(40h) 
SEE_MASK_NOASYNC         EQUATE(100h)
SEE_MASK_FLAG_NO_UI    EQUATE(400h)
SW_SHOWNORMAL              EQUATE(1)    
INFINITE                                 EQUATE(4294967295)  


W WINDOW,AT(,,204,25),FONT('Arial',9,,),CENTER,ALRT(EscKey),ALRT(AltF4),GRAY,DOUBLE,MODAL
       STRING('Externe programma is bezig, wachten aub...'),AT(7,7,195,10),USE(?String1),FONT(,,,FONT:bold)
END

CODE
  new:file &= NEW CString(Len(Clip(pFile))+4) !+4 als met " en <0,0>
  new:file = '"'&Clip(pFile)&'"' 
  If Not Omitted(pDirectory)
      new:Directory &= NEW CSTRING(LEN(CLIP(makeunc(pDirectory)))+5)
      new:Directory = '"'&clip(makeunc(pDirectory))&'"' 
  end

  If Not Omitted(pParameters)
        new:Param &= NEW CString(Len(pParameters)+3)
        new:Param = '"'&clip(pParameters)&'"'!&'<0,0>'
  End

   CLEAR(shi)
   shi.fMask          = SEE_MASK_NOCLOSEPROCESS + SEE_MASK_NOASYNC
   shi.hwnd           = 0{PROP:Handle}
   shi.lpVerb         = ADDRESS(Verb) 
   shi.lpFile           = ADDRESS(new:file)
   shi.lpParameters      = ADDRESS(new:Param)     
   shi.lpDirectory   = ADDRESS(new:Directory)
   if pHide     
      shi.nShow          = 0 
   else
      shi.nShow          = SW_SHOWNORMAL
   end
   SHi.lpIDList          =  0    
   shi.lpClass           =  0                          
   shi.hkeyClass      =  0                         
   shi.dwHotKey       =  0                          
   shi.DUMMYUNIONNAME    =  0
   shi.cbSize            = SIZE(shi)
   IF ShellExecuteEx(ADDRESS(shi)) 
      hProc = shi.hProcess
   else
      hProc = 0
   END

   If hProc 
      If pWait
         Open(W)
         W{Prop:Timer} = 50
         Accept
             Case Event()
             Of EVENT:Timer
             if WaitForSingleObject(shi.hProcess,0)=0 
                 I#= GetExitCodeProcess(hProc, lRetCode)
                 I# = CloseHandle(shi.hProcess)        
                 W{PROP:Timer} = 0 
              End 
              close(W)
             End !case
         End!end accept loop
      end!pwait
   end!hproc
  If Not(new:file &= NULL)            !opschonen
     Dispose(new:file)
  End
  if NOT(new:Directory &= NULL)
     DISPOSE(new:Directory)
  end
  if NOT(new:Param &= NULL)
     DISPOSE(new:Param)
  end
  RETURN(resultaat)

Hartelijk bedankt Dirk!
Thank you!

Best regards
Jeffrey

As I show in the below post if you run a batch file you can change the look so it looks a little better and not your typical DOS window.

If you’re going to use RoboCopy the RUN BAT file is an easy to get started. Once it works right then work on the look.

I would think Power Shell offers more options for changing the look.

Thanks Carl!

Best regards
Jeffrey

If you have CapeSoft’s WinEvent then you might try its “ds_CopyDirectory” function. It has an option to copy subfolders, too.

Thank you!
I will look at it.

Best regards
Jeffrey

Late to the party again so I’m sure you’ll have cracked this by now, but as-per JSlarve’s suggestion, this I how I do it.

The last parameter is nice because it shows/hides the OS progress window.

jhTools.FileAPI_Copy Procedure(String inSourceFilename, String inTargetFilename,<BYTE inHideProgress>)              
    
szSource                CString(256)
szTarget                CString(256)

FO_Copy                 Equate(2)
FOF_ALLOWUNDO           Equate(040H)
FOF_NOCONFIRMATION      Equate(010H)
FOF_No_UI               EQUATE(0614H)

grp_SHFileOPStruct      GROUP
hWnd                       Long
wFunc                      Long
pFrom                      Long
pTo                        Long
fFlags                     Long 
fAnyOperationsAborted      BYTE
hNameMappings              Long
lpszProgressTitle          LONG
                        .

   Code
      !-- Note: double NULL termination
      szSource = Clip(inSourceFilename) & '<0><0>'
      szTarget = Clip(inTargetFilename) & '<0><0>'

      grp_SHFileOPStruct.hWnd = 0
      grp_SHFileOPStruct.wFunc = FO_Copy
      grp_SHFileOPStruct.pFrom = Address(szSource)
      grp_SHFileOPStruct.pTo = Address(szTarget)
      grp_SHFileOPStruct.fFlags = FOF_NOCONFIRMATION

      !-- Hide Progress, ie: No GUI ?
      if inHideProgress
         grp_SHFileOPStruct.fFlags = FOF_NO_UI
      .

      !-- Create the folders in the target path..
      !--
      !SELF.CreateDirectoriesInPath(szTarget)

      if SHFileOperation(Address(grp_SHFileOPStruct)) = 0     ! No Error
         Return(True)
      .
            
      !-- Error..
      Return(False)

`

Thank you!!

Best regards
Jeffrey