Results 1 to 9 of 9

Thread: FileCopy (Resolved - great solution provided) problems

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jul 2002
    Posts
    78

    FileCopy (Resolved - great solution provided) problems

    Good afternoon,

    I was using a FileCopy function with great success, except that the screen made it appear that the program crashed... I tried adding a form that would appear and let the user know to wait, however that form also just stacked itself ontop and was actually transparent except the title bar. I have tried hourglasses also - they never appeared.

    I am using commondialogues to obtain the file information.

    I was researching solutions earlier on the forums and tried using the Windows Copy File animation but am obviously missing something. I edited from an example and obviously edited out something important!!

    If anyone wants to take a crack at reading this to see if you have any suggestions please feel free!!! Or if you have any other suggestions on what to do about the "crashed" appearance on the screen that would be good too!!

    I am copying a file that is identified through an Open dialogue, and the destination is obtained through a SaveAs dialogue.

    I also think that I need the .avi on the form but when I tried that it crashed VB (not just my program!).

    I am very new so I may also be missing references or something silly like that! I did reference the lib from the code (shell32.dll)

    Thanks,
    Mary

    *********** My attempt at the code VB 6 **************

    Option Explicit

    Private Type SHFILEOPSTRUCT
    hwnd As Long
    wFunc As Long
    fFlags As Integer
    fAnyOperationsAborted As Long
    hNameMappings As Long
    lpszProgressTitle As String
    SourceFile As String
    DestinationFile As String
    End Type

    Private Enum FO_OPS
    FO_MOVE = &H1
    FO_COPY = &H2
    FO_DELETE = &H3
    FO_RENAME = &H4
    End Enum

    Private Enum FO_FLAGS
    FOF_CREATEPROGRESSDLG = &H0
    FOF_NOCONFIRMMKDIR = &H200
    End Enum

    Private Declare Function SHFileOperation Lib "Shell32.dll" _
    Alias "SHFileOperationA" (lpFileOp As Any) As Long

    Private Sub cmdCancel_Click()
    'unload form and return to main screen
    Unload Me
    FrmMain.Show
    End Sub

    Private Sub cmdExit_Click()
    'Close and exit program
    End
    End Sub

    Private Sub cmdFindShellDB_Click()
    'Locate SRT Shell Database
    On Error GoTo ErrHandler

    diaFindShell.ShowOpen
    txtShellDBName.Text = diaFindShell.FileTitle
    ErrHandler:
    'MsgBox "Unexplained error, please try again"
    Exit Sub

    End Sub

    Private Sub cmdSaveSurveyDB_Click()

    'Save Shell as new survey database
    'On Error GoTo ErrHandler

    diaSaveSurveyDB.FileName = txtDatasetName.Text & ".mdb"
    diaSaveSurveyDB.ShowSave
    txtSurveyDBName.Text = diaSaveSurveyDB.FileTitle
    'SurveyDB = diaSaveSurveyDB.FileName
    'copy shell file to create survey specific database and show
    'Windows copy progress dialogue

    Dim fileop As SHFILEOPSTRUCT
    Dim lRet As Long
    Dim SourceFile, DestinationFile
    DestinationFile = diaSaveSurveyDB.FileName 'I have also tried
    'with 2 vbNull added
    SourceFile = diaFindShell.FileName 'I have also tried with
    '2 vbNull added
    With fileop
    .hwnd = Me.hwnd
    .SourceFile = SourceFile
    .DestinationFile = DestinationFile
    .wFunc = FO_COPY
    .fFlags = FOF_CREATEPROGRESSDLG
    'FileCopy SourceFile, DestinationFile
    End With

    lRet = SHFileOperation(fileop)

    cmdNext.Enabled = True


    'ErrHandler:
    'MsgBox "Unexplained error, please try again"
    ' Exit Sub

    End Sub


    Private Sub txtDatasetName_LostFocus()
    'ensure that user only entered an 8-character name and format for uppercase -- this name will include letters and numbers
    ' maybe add naming convention rules to help files later
    If Len(txtDatasetName.Text) <> 8 Then
    MsgBox "The dataset name should be 8 characters long
    and should match the name of your final SAS dataset. " _
    & vbCrLf & "Please try again."
    txtDatasetName.SetFocus
    Exit Sub
    End If

    End Sub
    Last edited by A441OTA; Jul 9th, 2002 at 11:39 AM.

  2. #2
    PowerPoster
    Join Date
    Aug 2001
    Location
    new jersey
    Posts
    2,904
    you probably just needed doevents in your original code

  3. #3
    Addicted Member
    Join Date
    Feb 2002
    Posts
    159

    What are you trying to copy?

    What are you trying to copy?????????????

  4. #4

    Thread Starter
    Lively Member
    Join Date
    Jul 2002
    Posts
    78
    Hi Phinds --

    I don't understand DoEvents quite yet, don't they need to go into a loop?

    Hi Notsosure --

    I am copying an Access database "shell" from an unknown place on a user's machine to an unknown place on the user's machine. The "open" dialogue has the user identify where the database is on their machine, and the "SaveAs" dialogue puts it where it should go... if you know of a better way then please feel free to tell me -- I am in a state of mind-boggle right now with the requirements that are being thrown at me!! When I was presented this job I was initially under the impression it would be simply taking raw data and making it look "pretty" through Word and Excel macros (which I have done before without a problem) -- it has now turned into full blown software development and everything is dynamic (everything imagineable!!!). I won't even get into the "stinky" database (and I'm using that term very loosely!) that I have to work with!!.

    Using "filecopy" worked great it just didn't look good!! Since there is only the one file a progress bar probably wouldn't work from what I understand? I thought about trying to figure out how to emulate Microsoft's progress bar that just bounces back and forth (Windows XP does this on load -- no steady progress denoted, just that it is working). I think in the meantime I'll just move the code to the command button instead of where the SaveAs dialogue comes up that might help a little (they don't won't much user-intervention so I was trying to aviod another "click").

    Please help if you can think of something better... I know enough VB to get me into trouble (like taking this job!! LOL) but not enough to get me out of trouble!!!!!

    Thanks,
    Mary

  5. #5
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    You were probably on the right track with just playin an animation clip... it would be alot easier than..

    To use the progress bar, you would have to keep track (via an API call, http://216.26.168.92/vbapi/ref/w/writefile.html perhaps) of how many bytes have been transferred (progressbar.value) versus how many bytes need to be transferred(progressbar.max). But you would have to use http://216.26.168.92/vbapi/ref/r/readfile.html to read the access database in bytes to memory. Then just readfile 1024 bytes, update the progress bar, then writefile 1024 bytes..
    Last edited by nemaroller; Jul 8th, 2002 at 09:16 AM.

  6. #6
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Lucky you, I'm still UNemployed...

    Put the below code in a module, call it from anywhere using
    VB Code:
    1. Call CopyAFile(Progressbar1, "C:\mysourcefile","C:\mydestfile")

    Pass the progressbar as the first parameter, source file as second, destination file as third.

    Of course, using a wide yet short progressbar makes it look
    like more progress is being done.

    Be sure to remove the Debug.print 's from the module code below when you distribute the app..

    VB Code:
    1. 'declarations section
    2. Option Explicit
    3.  
    4. Private Const FILE_SHARE_READ = &H1
    5. Private Const FILE_SHARE_WRITE = &H2
    6. Private Const CREATE_NEW = 1
    7. Private Const OPEN_EXISTING = 3
    8. Private Const GENERIC_READ = &H80000000
    9. Private Const GENERIC_WRITE = &H40000000
    10. Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
    11.  
    12. 'create file handle
    13. Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    14. Private Declare Function GetLastError Lib "kernel32.dll" () As Long
    15. 'flushes buffer to force writing to disk
    16. Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hSource As Long) As Long
    17.  
    18. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    19.  
    20.  
    21. 'reads the file
    22. Private Declare Function ReadFile Lib "kernel32.dll" (ByVal hSource As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
    23.  
    24. 'gets file size
    25. Private Declare Function GetFileSize Lib "kernel32.dll" (ByVal hSource As Long, lpFileSizeHigh As Long) As Long
    26.  
    27. 'writes the file
    28. Private Declare Function WriteFile Lib "kernel32.dll" (ByVal hSource As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
    29.  
    30. Public Sub CopyAFile(progress As Object, sourceFile As String, destFile As String)
    31. Dim hSource As Long   'file handle to source file
    32. Dim hDest As Long  'file handle to destination file
    33. Dim retVal As Long  'holder for returned values from the above api calls
    34. Dim numBytesRead As Long 'bytes read on each ReadFile call
    35. Dim numBytesWritten As Long  'bytes written on read WriteFile call
    36. Dim numBytesWrittenTotal As Long 'bytes written total as of current
    37. Dim loworder As Long    'filesize related
    38. Dim highorder As Long   'filesize related
    39. Dim donereading As Boolean  'indicates no more bytes to read, exit loop
    40. Dim byte1() As Byte  ' the Long value to write to the file
    41. Dim f As Long        ' size of byte1()
    42.  
    43. 'initialize variables
    44. ReDim byte1(10240)
    45. f = UBound(byte1)
    46. donereading = False
    47. progress.Value = 0
    48. 'create a handle to source file
    49. hSource = CreateFile(sourceFile, GENERIC_READ, FILE_SHARE_READ, ByVal CLng(0), OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, ByVal CLng(0))
    50. If hSource = -1 Then  ' the file could not be opened
    51.   Debug.Print "Unable to open the file - it may not exist, or improper flags"
    52.   Exit Sub  ' abort the program
    53. End If
    54.  
    55. 'create a handle to destination file
    56. hDest = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_READ, ByVal CLng(0), CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, ByVal CLng(0))
    57. If hDest = -1 Then  ' the file could not be opened
    58.   Debug.Print "Unable to open the file - it may already exist, or improper flags"
    59.   End  ' abort the program
    60. End If
    61.  
    62. 'retrieve file size in bytes to store as MAX parameter for progressbar
    63. highorder = 0
    64. loworder = GetFileSize(hSource, highorder)  ' read the file's size
    65. If highorder < 0 Then                     ' if file is > 2gb we may have problems
    66. highorder = loworder + 2 ^ 32             ' coder might want to investigate further
    67. End If                                    ' since GetFileSize is only correct <4gb
    68.  
    69. 'the maximum size of file to be transfered reflected in max size of progressbar
    70. progress.Max = loworder / 10240 '.Max only takes integer values to 32,7Xx..
    71.                                     'an error may occur if low/1024 >32,000
    72.  
    73. '*********************************begin loop
    74. Do While (donereading = False)
    75. 'read in  bytes from the source file
    76. retVal = ReadFile(hSource, byte1(0), f, numBytesRead, ByVal CLng(0))
    77. If numBytesRead < f Then  'we have read less than byte array bounds (near end of file)
    78.    ReDim Preserve byte1(numBytesRead) 'change the byte array to reflect
    79.    f = UBound(byte1)             'only the amount of bytes read
    80.    donereading = True            'signify done reading to loop
    81. End If
    82.  
    83. ' Write out bytes to the destination file
    84.  
    85. retVal = WriteFile(hDest, byte1(0), f, numBytesWritten, ByVal CLng(0))
    86. If retVal = 0 Then
    87.    retVal = GetLastError
    88.    Debug.Print "Error: " & retVal
    89.    End If
    90.  
    91. numBytesWrittenTotal = numBytesWrittenTotal + numBytesWritten
    92.  
    93. 'update the progress value
    94. progress.Value = numBytesWrittenTotal / 10240
    95. Loop
    96. '**********************************end loop
    97.  
    98.  
    99. ' Close the file handles.
    100. ReDim byte1(0)
    101. progress.Value = 0
    102. retVal = CloseHandle(hDest)
    103. retVal = CloseHandle(hSource)
    104. End Sub
    Last edited by nemaroller; Jul 8th, 2002 at 03:00 PM.

  7. #7
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Thanks for the appreciation...

    This code was slapped together so, there should be some changes if you are going to implement it in a program...

    As you found out, if the destination file already exists, it will exit the program...

    VB Code:
    1. 'create a handle to destination file
    2. If hDest = -1 Then  ' the file could not be opened
    3.   Debug.Print "Unable to open the file - it may already exist, or improper flags"
    4. [b]  End  ' abort the program[/b]
    5. End If

    code in bold should be...
    VB Code:
    1. Exit Sub

    You could change that whole code to a function, and have it return a number depending on the error... so the Exit Sub could be changed to
    VB Code:
    1. CopyAFile = 7  'error code #
    2. Exit Function

    Or, you could check for the source/destination files exitence before calling the sub/function...

    Btw
    you don't need the follow declaration, I forgot to take it out.
    VB Code:
    1. Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hSource As Long) As Long

  8. #8
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Just use this revised code instead.. it returns a string "Success" if sucessful, and others if not... so make sure to have a call similiar to
    mystring = CopyAFile(progressbar1, "C:\sourcefile", "C:\destfile")

    I also changed the filesize code, (higlighted in bold)to make it usable for a file from 10 bytes to file of 2gigabytes...
    and to make sure your program won't crash... if anyone wants to add to it, make suggestion revisions, please do so...

    VB Code:
    1. 'declarations section
    2. Option Explicit
    3.  
    4. Private Const FILE_SHARE_READ = &H1
    5. Private Const FILE_SHARE_WRITE = &H2
    6. Private Const CREATE_NEW = 1
    7. Private Const OPEN_EXISTING = 3
    8. Private Const GENERIC_READ = &H80000000
    9. Private Const GENERIC_WRITE = &H40000000
    10. Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
    11.  
    12. 'create file handle
    13. Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    14. 'allow return of errors encountered while writing destination file
    15. Private Declare Function GetLastError Lib "kernel32.dll" () As Long
    16. 'closes file handles
    17. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    18.  
    19. 'reads the file
    20. Private Declare Function ReadFile Lib "kernel32.dll" (ByVal hSource As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
    21.  
    22. 'gets file size
    23. Private Declare Function GetFileSize Lib "kernel32.dll" (ByVal hSource As Long, lpFileSizeHigh As Long) As Long
    24.  
    25. 'writes the file
    26. Private Declare Function WriteFile Lib "kernel32.dll" (ByVal hSource As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
    27.  
    28. Public Function CopyAFile(progress As Object, sourceFile As String, destFile As String) As String
    29. Dim hSource As Long   'file handle to source file
    30. Dim hDest As Long  'file handle to destination file
    31. Dim retVal As Long  'holder for returned values from the above api calls
    32. Dim numBytesRead As Long 'bytes read on each ReadFile call
    33. Dim numBytesWritten As Long  'bytes written on read WriteFile call
    34. Dim numBytesWrittenTotal As Long 'bytes written total as of current
    35. Dim loworder As Long    'filesize related
    36. Dim highorder As Long   'filesize related
    37. Dim donereading As Boolean  'indicates no more bytes to read, exit loop
    38. Dim byte1() As Byte  ' the Long value to write to the file
    39. Dim f As Long        ' size of byte1()
    40.  
    41. 'initialize variables
    42.  
    43. donereading = False
    44. progress.Value = 0
    45. 'create a handle to source file
    46. hSource = CreateFile(sourceFile, GENERIC_READ, FILE_SHARE_READ, ByVal CLng(0), OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, ByVal CLng(0))
    47. If hSource = -1 Then  ' the file could not be opened
    48.   Debug.Print "Unable to open the file - it may not exist, or improper flags"
    49.   CopyAFile = "Source file may not exist"
    50.   Exit Function ' abort
    51. End If
    52.  
    53. 'create a handle to destination file
    54. hDest = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_READ, ByVal CLng(0), CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, ByVal CLng(0))
    55. If hDest = -1 Then  ' the file could not be opened
    56.   Debug.Print "Unable to open the file - it may exist, or improper flags"
    57.   retVal = CloseHandle(hSource)
    58.   CopyAFile = "Destination file exists, or improper flags"
    59.   Exit Function ' abort
    60. End If
    61. [b]
    62. 'following code needs to be addressed for files >2gigabytes
    63. 'retrieve file size in bytes to store as MAX parameter for progressbar
    64. loworder = GetFileSize(hSource, highorder)  ' read the file's size
    65. If loworder > 2000000000 Then  'this code cannot handle files > 2gb
    66. retVal = CloseHandle(hDest)
    67. retVal = CloseHandle(hSource)
    68. CopyAFile = "File too large"
    69. Exit Function
    70. [/b]
    71. If loworder > 3000 Then highorder = (loworder / 1000)
    72. Else
    73. highorder = (loworder / 10)
    74. End If
    75.  
    76. ReDim byte1(highorder)
    77. f = UBound(byte1)
    78.  
    79. 'the maximum size of file to be transfered reflected in max size of progressbar
    80. progress.Max = loworder / highorder '.Max only takes integer values to 32,7Xx..
    81.                                     'an error may occur if filesize > 2gb
    82.  
    83. '*********************************begin loop
    84. Do While (donereading = False)
    85. 'read in  bytes from the source file
    86. retVal = ReadFile(hSource, byte1(0), f, numBytesRead, ByVal CLng(0))
    87. If numBytesRead < f Then  'we have read less than byte array bounds (near end of file)
    88.    ReDim Preserve byte1(numBytesRead) 'change the byte array to reflect
    89.    f = UBound(byte1)             'only the amount of bytes read
    90.    donereading = True            'signify done reading to loop
    91. End If
    92.  
    93. ' Write out bytes to the destination file
    94.  
    95. retVal = WriteFile(hDest, byte1(0), f, numBytesWritten, ByVal CLng(0))
    96. If retVal = 0 Then
    97.    retVal = GetLastError
    98.    Debug.Print "Error: " & retVal
    99.    CopyAFile = "Error writing destination file: " & retVal
    100.    retVal = CloseHandle(hDest)
    101.    retVal = CloseHandle(hSource)
    102.    Exit Function
    103. End If
    104.  
    105. ' force the OS to write the data NOW
    106. 'retVal = FlushFileBuffers(hDest)'not necessary as such
    107. numBytesWrittenTotal = numBytesWrittenTotal + numBytesWritten
    108.  
    109. 'update the progress value
    110. progress.Value = CInt(numBytesWrittenTotal / highorder)
    111. Loop
    112. '**********************************end loop
    113.  
    114.  
    115. ' Close the file handles.
    116. ReDim byte1(0)
    117. progress.Value = 0
    118. retVal = CloseHandle(hDest)
    119. retVal = CloseHandle(hSource)
    120. CopyAFile = "Success"
    121. End Function
    Last edited by nemaroller; Jul 9th, 2002 at 01:54 PM.

  9. #9
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    found a bug in the above code...

    relating to an invalid property value for PRogress.value,
    re-copy the above code, it has been edited, and changed...

    VB Code:
    1. progress.Value = [b]CInt[/b](numBytesWrittenTotal / highorder)

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