Several people have had problems with their GUIs freezing when they try to copy large files using FileCopy(). This is because FileCopy() is a blocking function, and the GUI stops responding to messages from the OS during the operation. If that goes on long enough, the OS thinks it is hung and you get the (Not Responding) thing going on.
Here's a function that copies large files using Windows API calls in 8MB 2 MB chunks. This keeps the GUI alive and responsive. I've added additional copy verification functionality as well (disabled by default).
Take a look at my A3COPY project for a great usage example of this UDF.
- Moved a few more functions into _FileEx.
- Fixed a bug in GetDiskClusterSize function.
- Fixed bug due to missing RtlCopyMemory and RtlCompareMemory exports in x86 kernel32.dll. Now uses RtlMoveMemory and RtlCompareMemory from ntdll.dll (sorry).
Read NOTES at top of UDF
- Reduced default buffer size to 2 MB
- Added flags for copying source file attributes, all three file times individually, ACL security descriptors and ownership, and NTFS specific compression and encryption
- Optimized buffer creation
- Enhanced path handling to fully support UNC and network conventions ( C:... , ?C:... , srvshare... , ?UNCsrvshare... )
- Removed C runtime functions (msvcrt.dll) in favor of native kernel32 functions
- Code cleanup and many optimizations in LFC and the accompanying _FileEx UDF
- Added additional verification methods - bit by bit, and size only
- The default verification method (ie iFlag 8) is now bit by bit - it is faster and less computationally intensive than MD5 hashing, it also allows the function to bail out early in the case of a failed copy operation
SCRIPT BREAKING CHANGES
- Combined some parameters into one iFlags parameter
- Re-ordered some parameters based on priority
- Added a parameter to specify a different read buffer size
- Destination file is now opened with GENERIC_READ | GENERIC_WRITE per MSDN for better compatibility copying files across a network
- No longer create destination directory structure unless specified in iFlags parameter
- Removed tracexxx's hashing functions (sorry!) in favor of a different method which is not RAM limited
- Hashing algorithm can be specified (those supported by Crypt.au3: CALG_MD2, CALG_MD4, CALG_MD5, CALG_SHA1)
- Fix for failed verification of 0 byte files
- Added check for 0 byte source in RAW functions
- Small change to CreateFile function to avoid errors when opening SYSTEM or HIDDEN files when specifying CREATE_ALWAYS.
- Added _LargeFileCopyUnbuffered and _LargeRawCopyUnbuffered which will copy files using unbuffered I/O.
- MD5 hashing of the source file / memory block is now done on the fly from the memory buffer. This avoids an additional read of the source file later on and saves time.
- Destination file MD5 hashing is now done with trancexxx's nice hashing UDF. It uses the Windows API and is really fast.
- Added _LargeRawCopy which will copy large memory blocks (usually from an embedded resource) to a file in the same manner as _LargeFileCopy. This function also has the verify functionality via MD5 hash.
- Added optional user function and variable parameters. This function, if given, will be called after each write operation with the total bytes written, total file size in bytes, and the user given variable. This is perfect for a copy-with-progess type of function call.
#NoTrayIcon #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <_LargeFileCopy.au3> _Main() Func _Main() Local $msg, $timer, $ret Local $src = "ubuntu-10.04-desktop-i386.iso" ; <---- path to a really large file goes here, recommended 600MB+ Local $destpath = @DesktopDir & "testdir" ; <---- destination path goes here GUICreate("File Copy Test", 250, 150) GUICtrlCreateLabel("Try to interact with the GUI during file copy...", 20, 15) Local $go = GUICtrlCreateButton("Copy Large File", 50, 50, 150, 50) Local $doing = GUICtrlCreateLabel("Ready...", 20, 120, 200) GUISetState() Do $msg = GUIGetMsg() If $msg = $go Then ; create destination path DirCreate($destpath) ; internal FileCopy() function GUICtrlSetData($doing, "FileCopy()...") $timer = TimerInit() ConsoleWrite("FileCopy:" & @CRLF) $ret = FileCopy($src, $destpath, 1) ConsoleWrite("return: " & $ret & @CRLF & "error: " & @error & @CRLF & "time: " & TimerDiff($timer) & " ms" & @CRLF) ConsoleWrite("====================" & @CRLF) ; _LargeFileCopy() UDF function GUICtrlSetData($doing, "_LargeFileCopy()...") $timer = TimerInit() ConsoleWrite("_LargeFileCopy:" & @CRLF) $ret = _LargeFileCopy($src, $destpath, 1) ConsoleWrite("return: " & $ret & @CRLF & "error: " & @error & @CRLF & "time: " & TimerDiff($timer) & " ms" & @CRLF) ConsoleWrite("====================" & @CRLF) GUICtrlSetData($doing, "Ready...") EndIf Until $msg = -3 EndFunc LargeFileCopy.zip