Results 1 to 18 of 18

Thread: CopyFile2 API Function

  1. #1

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    CopyFile2 API Function

    I'm determined to get over my fear and loathing of using the API < Maybe...

    The rather new CopyFile2 Function seems exactly what I need in that it provides callback upon completion. My application involves moving thousands to tens of thousands of files to USB drives. This can take hours even with very good 3.1 drives. Even comparatively expensive solid-state thumb drives take quite some time. I am forced to erase the drive by the quickest means possible and completely re-write for even the most minor change because the device in which it is used reads its "catalog" data from the drive in the exact sequence it was written.

    For obvious reasons an indication of actual progress is needed. Despite using all the tricks I know to keep VB from running away from itself and failing to respond in either the executable version or environment as sometimes occurs when particularly large in size folders are copied file-by-file.

    Here's the link to the function at the Microsoft website: https://learn.microsoft.com/en-us/wi...base-copyfile2

    Now my problem. Could someone kindly provide the necessary declarations to use this function in VB6?

    Compared to others it appears to be quite simple and perhaps via careful comparison of the VB code with the C presented here I can get a much better idea of how to use the API without searching for something to virtually copy and paste in near prayer that it will actually work as suggested.

  2. #2
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    Won't work with vb6, since the pointer to the callback is part of the 3rd Parameter-Structure.
    AFAIK, The only way in vb6 is with CopyFileEx (A/W)
    https://learn.microsoft.com/en-us/wi...se-copyfileexw

    There you ship the pointer directly (AddressOf)

    Remember: vb6 is single-thread (hacks to start a Thread in vb6 not withstanding).
    Would probably put it into an ActiveX-DLL, passing all necessary stuff (Handle to Parent-Window (optional) etc.) and create the Callback, Progress-Window etc. there
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  3. #3

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    Re: CopyFile2 API Function

    Quote Originally Posted by Zvoni View Post
    Won't work with vb6, since the pointer to the callback is part of the 3rd Parameter-Structure.
    AFAIK, The only way in vb6 is with CopyFileEx (A/W)
    https://learn.microsoft.com/en-us/wi...se-copyfileexw

    There you ship the pointer directly (AddressOf)

    Remember: vb6 is single-thread (hacks to start a Thread in vb6 not withstanding).
    Would probably put it into an ActiveX-DLL, passing all necessary stuff (Handle to Parent-Window (optional) etc.) and create the Callback, Progress-Window etc. there
    Thank you indeed! Should have known it wouldn't work.

    I really need to change programming languages. I'm mainly self-taught in BASIC since an original IBM PC XT. Not even sure anymore how many variants I've gone through. It's just so familiar that I can go years or decades without programming and restart easily. What was it? PLC? I learned at University?

    Thanks again!

  4. #4
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    Here is an example from a GERMAN Forum: https://www.vbarchiv.net/tipps/details.php?id=635

    The first 2 Code-Blocks go into a regular BAS-File
    The 3rd CodeBlock is an example for a CommandButton, needs a ProgressBar on the Form.
    Instead of the 2 TextBoxes you can test with hardcoded EXISTING files --> Full Path!!

    EDIT: Since you said, this is a huge Copy-Process, you might want to set the COPY_FILE_NO_BUFFERING-Flag
    Code:
    Public Const COPY_FILE_NO_BUFFERING = &H1000
    Last edited by Zvoni; Aug 12th, 2024 at 06:31 AM.
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  5. #5

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    Re: CopyFile2 API Function

    Quote Originally Posted by Zvoni View Post
    Here is an example from a GERMAN Forum: https://www.vbarchiv.net/tipps/details.php?id=635

    The first 2 Code-Blocks go into a regular BAS-File
    The 3rd CodeBlock is an example for a CommandButton, needs a ProgressBar on the Form.
    Instead of the 2 TextBoxes you can test with hardcoded EXISTING files --> Full Path!!

    EDIT: Since you said, this is a huge Copy-Process, you might want to set the COPY_FILE_NO_BUFFERING-Flag
    Code:
    Public Const COPY_FILE_NO_BUFFERING = &H1000
    Thank you again. I'll do some experimentation and report back.

    It should be easy to integrate to my progress bar as its major values are stored in two of my very, very few global variables.

  6. #6
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,258

    Re: CopyFile2 API Function

    What are you talking about of course you can use CopyFile2 in VB6.

    Public Declare Function CopyFile2 Lib "kernel32" (ByVal lpExistingFileName As LongPtr, ByVal lpNewFileName As LongPtr, pExtendedParameters As COPYFILE2_EXTENDED_PARAMETERS) As BOOL

    declares for the callback:

    Code:
    Public Const COPYFILE2_IO_CYCLE_SIZE_MIN  = 4096
    '  maximum allowed requested i/o size, in bytes (1GB)
    '  (constrains COPYFILE2_EXTENDED_PARAMETERS_V2 ioDesiredSize field).
    Public Const COPYFILE2_IO_CYCLE_SIZE_MAX  = &H40000000
    '  minimum allowed requested average i/o rate, in kbytes per second
    '  (constrains COPYFILE2_EXTENDED_PARAMETERS_V2 ioDesiredRate field).
    Public Const COPYFILE2_IO_RATE_MIN  = 512
    
    Public Type COPYFILE2_EXTENDED_PARAMETERS
        dwSize As Long
        dwCopyFlags As CopyFileFlags
        pfCancel As LongPtr
        pProgressRoutine As LongPtr
        pvCallbackContext As LongPtr
    End Type
    Public Type COPYFILE2_EXTENDED_PARAMETERS_V2
        dwSize As Long
        dwCopyFlags As CopyFileFlags
        pfCancel As LongPtr
        pProgressRoutine As LongPtr
        pvCallbackContext As LongPtr
        ' Additional copy flags (COPYFILE2_EXTENDED_PARAMETERS_V2 only;
        ' treated as zero if COPYFILE2_EXTENDED_PARAMETERS is used).
        dwCopyFlagsV2 As Long
        ' size of the i/o for each {read, write} cycle, in bytes
        ' (may be reduced, if insufficient memory is available)
        ' if zero: use a suitable default.
        ' may be ignored if ioDesiredRate is specified (i.e.,
        ' CopyFile2() will disregard if a requested size is
        ' rate is inappropriate for a requested rate.)
        ioDesiredSize As Long
        ' requested average i/o rate, in kbytes per second.
        ' if zero: use a suitable default (usually as fast as possible).
        ioDesiredRate As Long
        ' reserved for future use; must be set to zero
        reserved(0 To 7) As LongPtr
    End Type
    
    [Description("Copy union() to one of the COPYFILE2_INFO_* UDTs based on the Type member.")]
    Public Type COPYFILE2_MESSAGE
        Type As COPYFILE2_MESSAGE_TYPE
        dwPadding As Long
        #If Win64 Then
        union(71) As Byte
        #Else
        union(63) As Byte
        #End If
    End Type
    Public Type COPYFILE2_INFO_CHUNKSTARTED
        dwStreamNumber As Long
        dwReserved As Long
        hSourceFile As LongPtr
        hDestinationFile As LongPtr
        uliChunkNumber As LongLong
        uliChunkSize As LongLong
        uliStreamSize As LongLong
        uliTotalFileSize As LongLong
    End Type
    Public Type COPYFILE2_INFO_CHUNKFINISHED
        dwStreamNumber As Long
        dwFlags As Long
        hSourceFile As LongPtr
        hDestinationFile As LongPtr
        uliChunkNumber As LongLong
        uliChunkSize As LongLong
        uliStreamSize As LongLong
        uliStreamBytesTransferred As LongLong
        uliTotalFileSize As LongLong
        uliTotalBytesTransferred As LongLong
    End Type
    Public Type COPYFILE2_INFO_STREAMSTARTED
        dwStreamNumber As Long
        dwReserved As Long
        hSourceFile As LongPtr
        hDestinationFile As LongPtr
        uliStreamSize As LongLong
        uliTotalFileSize As LongLong
    End Type
    Public Type COPYFILE2_INFO_STREAMFINISHED
        dwStreamNumber As Long
        dwReserved As Long
        hSourceFile As LongPtr
        hDestinationFile As LongPtr
        uliStreamSize As LongLong
        uliStreamBytesTransferred As LongLong
        uliTotalFileSize As LongLong
        uliTotalBytesTransferred As LongLong
    End Type
    Public Type COPYFILE2_INFO_POLLCONTINUE
        dwReserved As Long
    End Type
    Public Type COPYFILE2_INFO_ERROR
        dwStreamNumber As Long
        hrFailure As Long
        dwReserved As Long
        uliChunkNumber As LongLong
        uliStreamSize As LongLong
        uliStreamBytesTransferred As LongLong
        uliTotalFileSize As LongLong
        uliTotalBytesTransferred As LongLong
    End Type
    
    Public Const CALLBACK_CHUNK_FINISHED  = &H00000000
    Public Const CALLBACK_STREAM_SWITCH  = &H00000001
    Substitute Currency or LARGE_INTEGER for LongLong as you prefer.
    Last edited by fafalone; Aug 30th, 2024 at 11:05 PM.

  7. #7
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    Since when is there a „LongPtr“ in VB6????
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  8. #8
    Frenzied Member VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,005

    Re: CopyFile2 API Function

    Quote Originally Posted by Zvoni View Post
    Since when is there a „LongPtr“ in VB6????
    There isn't but it's so ubiquitous that I'm surprised you haven't already seen it posted hundreds of times in these forums. It's declared as an empty Enum containing just an underscore as a placeholder. Quite useless unless you're using the same code in VBA or TwinBasic.

  9. #9
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    Quote Originally Posted by VanGoghGaming View Post
    There isn't but it's so ubiquitous that I'm surprised you haven't already seen it posted hundreds of times in these forums. It's declared as an empty Enum containing just an underscore as a placeholder. Quite useless unless you're using the same code in VBA or TwinBasic.
    I know that LongPtr exists in VBA, since i'm doing a lot in VBA at work.

    I'm more surprised that faf stepped into that trap......
    Nevermind that in faf's code-sample there is stuff that is "missing":
    What is "COPYFILE2_MESSAGE_TYPE"?
    What is "CopyFileFlags"?

    Am i blind?? Is faf using a TypeLib i'm not aware off?

    OP talks about using it in VB6, not VBA, not TwinBasic, not Suaheli nor Klingon
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  10. #10
    Frenzied Member VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,005

    Wink Re: CopyFile2 API Function

    He's probably using his own TypeLib, like a boss!
    Still it's free code that should help the OP if he's capable of looking up the missing declares.

  11. #11
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,258

    Re: CopyFile2 API Function

    A) I was trying to focus on the declare and structs, I assumed you already knew what enums were. But here's some more:

    Code:
    Public Enum COPYFILE2_MESSAGE_TYPE
        COPYFILE2_CALLBACK_NONE = 0
        COPYFILE2_CALLBACK_CHUNK_STARTED = 1
        COPYFILE2_CALLBACK_CHUNK_FINISHED = 2
        COPYFILE2_CALLBACK_STREAM_STARTED = 3
        COPYFILE2_CALLBACK_STREAM_FINISHED = 4
        COPYFILE2_CALLBACK_POLL_CONTINUE = 5
        COPYFILE2_CALLBACK_ERROR = 6
        COPYFILE2_CALLBACK_MAX = 7
    End Enum
    
    Public Enum COPYFILE2_MESSAGE_ACTION
        COPYFILE2_PROGRESS_CONTINUE = 0
        COPYFILE2_PROGRESS_CANCEL = 1
        COPYFILE2_PROGRESS_STOP = 2
        COPYFILE2_PROGRESS_QUIET = 3
        COPYFILE2_PROGRESS_PAUSE = 4
    End Enum
    
    Public Enum COPYFILE2_COPY_PHASE
        COPYFILE2_PHASE_NONE = 0
        COPYFILE2_PHASE_PREPARE_SOURCE = 1
        COPYFILE2_PHASE_PREPARE_DEST = 2
        COPYFILE2_PHASE_READ_SOURCE = 3
        COPYFILE2_PHASE_WRITE_DESTINATION = 4
        COPYFILE2_PHASE_SERVER_COPY = 5
        COPYFILE2_PHASE_NAMEGRAFT_COPY = 6
        '  ... etc phases.
        COPYFILE2_PHASE_MAX = 7
    End Enum
    
    Public Enum CopyFileFlags
        COPY_FILE_FAIL_IF_EXISTS = &H00000001
        COPY_FILE_RESTARTABLE = &H00000002
        COPY_FILE_OPEN_SOURCE_FOR_WRITE = &H00000004
        COPY_FILE_ALLOW_DECRYPTED_DESTINATION = &H00000008
        COPY_FILE_COPY_SYMLINK = &H00000800
        COPY_FILE_NO_BUFFERING = &H00001000
        COPY_FILE_REQUEST_SECURITY_PRIVILEGES = &H00002000
        COPY_FILE_RESUME_FROM_PAUSE = &H00004000
        COPY_FILE_NO_OFFLOAD = &H00040000
        COPY_FILE_IGNORE_EDP_BLOCK = &H00400000
        COPY_FILE_IGNORE_SOURCE_ENCRYPTION = &H00800000
    '  Don't request WRITE_DAC for the destination file access.
        COPY_FILE_DONT_REQUEST_DEST_WRITE_DAC = &H02000000
    '  If either source or target is an SMB share, compression
    '  will be requested on all READs and WRITEs.
        COPY_FILE_REQUEST_COMPRESSED_TRAFFIC = &H10000000
        COPY_FILE_OPEN_AND_COPY_REPARSE_POINT = &H00200000
        COPY_FILE_DIRECTORY = &H00000080
        COPY_FILE_SKIP_ALTERNATE_STREAMS = &H00008000&
        COPY_FILE_DISABLE_PRE_ALLOCATION = &H04000000
        COPY_FILE_ENABLE_LOW_FREE_SPACE_MODE = &H08000000
        COPY_FILE_ENABLE_SPARSE_COPY = &H20000000
    End Enum
    
    Public Const COPYFILE2_IO_CYCLE_SIZE_MIN  = 4096
    '  maximum allowed requested i/o size, in bytes (1GB)
    '  (constrains COPYFILE2_EXTENDED_PARAMETERS_V2 ioDesiredSize field).
    Public Const COPYFILE2_IO_CYCLE_SIZE_MAX  = &H40000000
    '  minimum allowed requested average i/o rate, in kbytes per second
    '  (constrains COPYFILE2_EXTENDED_PARAMETERS_V2 ioDesiredRate field).
    Public Const COPYFILE2_IO_RATE_MIN  = 512
    B) I write all VB6 code with LongPtr now for 64bit provisioning. A lot easier to just do it now rather than have to go back and convert, trust me I've done a lot of that. I do typically use oleexp.tlb, which defines LongPtr for VB6, but with tB where it is now you're going to be seeing a lot more of it, especially since it helps vba64 people too. As mentioned, it's common enough I didn't feel the need to repeat in every post

    'and if you're not using oleexp.tlb for LongPtr support, add it with:
    Code:
    Public Enum LongPtr
        [_]
    End Enum

  12. #12
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    faf, i'll take your word for it, since i admit i haven't done anything serious in vb6 for years now
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  13. #13
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,509

    Re: CopyFile2 API Function

    Quote Originally Posted by Zvoni View Post
    not Suaheli nor Klingon
    I have to pick you up on your Swahili now... Presuming you CAN speak Klingon.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  14. #14
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: CopyFile2 API Function

    Quote Originally Posted by yereverluvinuncleber View Post
    I have to pick you up on your Swahili now... Presuming you CAN speak Klingon.
    Qapla'!
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  15. #15

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    Re: CopyFile2 API Function

    I got sidetracked and didn't notice any notifications of further posts to this topic. Am about to use the info and will certainly report my results.

    Thanks all contributors for the suggestions!

  16. #16

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    Re: CopyFile2 API Function

    Update:

    @fafalone -- Thank you very much. I'd previously encountered LongPtr declarations before and mistakenly it seems thought that it could not be used with VB ever.

    I have the main function compiling in a working program and continue to study how to fully and properly implement.

    Am doing my best to add the necessary declare for the callback routine and [somehow] figure out what should be the simplest of things: passing the return value to the "SUCCEEDED Macro."

    Will spend some more time and will report back. Should I still not get it I won't ask for further assistance in the matter as I'll write things in my old ways without relying on the handy but if in my short experience at times painfully slow API functions especially with regards to file functions.

  17. #17
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,258

    Re: CopyFile2 API Function

    Public Function CopyFile2ProgressRoutine(pMessage As COPYFILE2_MESSAGE, ByVal pvCallbackContext As LongPtr) As COPYFILE2_MESSAGE_ACTION

    VB6 doesn't support unions (neither does tB currently), so using the union(63) As Byte is a little complicaticated... you need to check the Type then use CopyMemory to copy the union variable to the appropriate other UDT (I wrote custom UDTs for these in the earlier post with the others; I didn't put padding in though and don't recall offhand if you need to copy from 0 or LenB(destudt) - 64).

    SUCCEEDED just checks if a value is equal or greater than 0...

    Code:
    Public Function SUCCEEDED(hr As Long) As Boolean
        SUCCEEDED = (hr >= 0)
    End Function

    PS- Mistake in COPYFILE2_MESSAGE that doesn't impact VB6 but needs to be fixed for tB/VBA 64bit:

    Code:
    Public Type COPYFILE2_MESSAGE
        Type As COPYFILE2_MESSAGE_TYPE
        dwPadding As Long
        #If Win64 Then
        union(71) As Byte
        #Else
        union(63) As Byte
        #End If
    End Type
    Last edited by fafalone; Aug 30th, 2024 at 11:06 PM.

  18. #18

    Thread Starter
    Member
    Join Date
    Mar 2024
    Posts
    46

    Re: CopyFile2 API Function

    @fafalone

    Thank you again. Am presently dealing with other and unexpected file-related programming challenges. The most frustrating is my discovery that comparing titles when both are one are in object form does not always yield correct results. I was already well aware that capitalization is ignored for comparison when working in a command (DOS-like) shell.

    What I did not know however is that blank spaces (ASCII decimal code 32) are not always detected. For instance two consecutive spaces between words of a title are deemed equal to a single space; a space at the end of a filename just before the dot to begin the extension is not detected and deemed equivalent to one lacking that space character. As a result I'm forced to either put the file names into string variables for comparison or resort to the copy-delete-copy method of renaming.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width