Yashied

Copy UDF

84 posts in this topic

#61 ·  Posted (edited)

I'm having trouble using this script to copy the My Documents folder (@MyDocumentsDir).

The script is simply as in the OP example "GUI, directories copying", with the source set to @MyDocumentsDir.

I'm getting Access Denied (from $State[5], it equals 5, which from here... http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx indicates Access Denied)

The box is Windows 7, which in the Profile folder has kinds 2 My Docs folders one is the actual one, and another seems to be a shortcut (possibly for backwards compatibility?). this 'shortcut' also returns access denied when i try to access it.

So, how do we differentiate the two for the purposes of this script.

FYI, if i do a Run("Explorer " & @MyDocumentsDir) Explorer does pop open with the correct My Docs folder. And tests i've run copying @desktopDir and @favoritesdir both work well.

Any thoughts?

Edited by TSprouse

Share this post


Link to post
Share on other sites



Great UDF, I'm currently implementing it into SMF :).

Would it be possible to add a Callback response flag like

$COPY_OVERWRITE_RENAME

Default Win7 behavior on existing files is "Yes / No / Yes, but rename". Would it be possible to implement something similar into the DLL? That if the flag is set the original file "Test.txt" is copied / moved to something like:

Copy of Test.txt

Copy (2) of Test.txt

Copy (3) of Test.txt

Copy (4) of Test.txt

In AutoIt I would use something like this

Local $iEnum = 0
$sFileName_Target_Buffer = $sFileName_Target
while FileExists($sFileName_Target)
 $iEnum += 1
 Switch $iEnum
  Case 1
   $sFileName_Target = "Copy of " & $sFileName_Target_Buffer
  Case Else
   $sFileName_Target = "Copy (" & $iEnum & ") of " & $sFileName_Target_Buffer
 EndSwitch
WEnd

Additionaly, could you explain what effects these flags have in detail?

$COPY_FILE_NO_BUFFERING

$COPY_FILE_OPEN_SOURCE_FOR_WRITE

Best Regards

Share this post


Link to post
Share on other sites

Please ignore my request. I realized that the Dll contains plain implementations of

CopyFileEx and

MoveFileEx

and that the flags are documented on MSDN. For the rest (renaming) I wrote my own wrapper.

Share this post


Link to post
Share on other sites

#64 ·  Posted (edited)

First , you saved my day with the COPY UDF.

Anyway:

Maybe I missed it, but _Copy_OpenDll() uses an optional path to the dll. May be you could extend this to use a path and /or file?

Func _Copy_OpenDll($sDLL = '')
If $cpDLL <> -1 Then
Return SetError(6, 0, 0)
EndIf
If $sDLL Then
if StringInStr(StringRight($sDLL,StringLen($sDLL)-4),".dll") then
$sDLL=$sDLL
Else
If @AutoItX64 Then
$sDLL = StringRegExpReplace ($sDLL,"$","") & 'Copy_x64.dll'
Else
$sDLL = StringRegExpReplace ($sDLL,"$","") & 'Copy.dll'
EndIf
EndIf

Else
If @AutoItX64 Then
$sDLL = @ScriptDir & 'Copy_x64.dll'
Else
$sDLL = @ScriptDir & 'Copy.dll'
EndIf
EndIf

If Not FileExists($sDLL) Then
Return SetError(8, 0, 0)
EndIf
If StringCompare(StringRegExpReplace(FileGetVersion($sDLL), '(d+.d+).*', '1'), '1.4') Then
Return SetError(7, 0, 0)
EndIf
$cpDLL = DllOpen($sDLL)
If $cpDLL = -1 Then
Return SetError(1, 0, 0)
EndIf
OnAutoItExitRegister('__CP_AutoItExit')
For $i = 0 To 255
For $j = 0 To UBound($cpSlot, 2) - 1
$cpSlot[$i][$j] = 0
Next
Next
Return 1
EndFunc ;==>_Copy_OpenDll

As you can see my intention is to :

If Not _Copy_OpenDll(@ScriptDir & 'bin') Then
MsgBox(16, '', 'DLL not found.')
Exit
EndIf

just give a path and than let the copy.au3 decide if x64 or x32 or if I "force" it to use a certain dll file.

Does this makes sense to you?

(or is it already inside and I missed it because I'm in a hurry)

Anyway, thank you again.

(btw: I need to use this UDF because _FileCopyEx did not work on Windows 2008R2 - On my Win7(x64) it does...strange but no time to investigate - just replaced the function.....)

Edited by Tankbuster

Share this post


Link to post
Share on other sites

Hi man! And thanks for this great UDF!

I just wanna report a bug: The copy functions crashes with very long file names

Share this post


Link to post
Share on other sites

#66 ·  Posted (edited)

Define "crashes", and define "very long file names". Because taken literally, the latter could be that the former happens if you have a file named "very long file names". Knowing that's probably not what you're saying, having a description of how long the file name has to be before it "crashes" would lead to having a proper bug report so that someone doesn't have to reinvent the wheel by trying file names of ever increasing length until the function fails.

EDIT: Oh and before I forget, not mentioning the version of AutoIt you're using, or the version of Windows and whether it's x86 or x64, doesn't help trouble shoot it either.

Edited by BrewManNH

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#67 ·  Posted (edited)

Sorry :> you are right.

The UDF fails copying files with a name greater than 200 chars, and sometimes, the entire script crashes and I don't know if it's the _Copy_CopyFile or _Copy_GetStat function that crashes it.

I'm on Win7 x86 with AutoIt 3.3.8.0, and here is my testing script

#NoTrayIcon
#include <String.au3>

#include "Copy.au3"

_Copy_OpenDll("..\copy.dll")
 
; It succeds with 196, but not with 197
$sDest = @ScriptDir & "\" & _StringRepeat("a", 197) & ".au3" ; 197 + StringLen(".au3") = 201
ConsoleWrite(@ScriptFullPath & @CRLF)
ConsoleWrite($sDest & @CRLF)
_Copy_CopyFile(@ScriptFullPath, $sDest)

Dim $aStatus
Do
     Sleep(50)
     $aStatus = _Copy_GetState()
     ConsoleWrite("Status: " & $aStatus[0] & @CRLF)
Until $aStatus[0] = 0

;~ ConsoleWrite("1" & @CRLF)
;~ FileSetAttrib($sDest, "+H")
;~ ConsoleWrite("2" & @CRLF)

_Copy_CloseDll()

Any help! Thanks

Edited by matwachich

Share this post


Link to post
Share on other sites

I would guess that you've reached the limit of a path/filename in Windows, which is usually 255 characters long unless you use a UNC path.

From MSDN:

"In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "?" to the path. For more information, see Naming Files, Paths, and Namespaces."

"The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "?" prefix. For example, "?D:very long path".

Note The maximum path of 32,767 characters is approximate, because the "?" prefix may be expanded to a longer string by the system at run time, and this expansion applies to the total length."


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

This UDF is based on two API functions:

CopyFileEx()

MoveFileWithProgress()

Both functions can handle up to 32,767 characters. I'm having the same problem with long filenames (even when I've prefixed "?" to the path to make it work at all), so either it's not the unicode version used in the dll (hmmm, no, unicode seems to work), or there is some kind of internal buffer in the dll that is not large enough (my guess).

Share this post


Link to post
Share on other sites

Great!!!! Works for me, thanks man!!!!!!!!

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

#72 ·  Posted (edited)

I am trying to use the 1.4 Copy UDF.  The script I made works beautifully from my Windows 8.1 desktop, everything works as expected, (except for the X button doesnt work, but I'm trying to work through that).

But the big problem is once I try to run the same script from WinPE 3.0 (Windows 7 based), things aren't so rosy.  The initial copy screen with the source and destination listed comes up just fine, but when I select either browse button, I get basically a blank window, with no tree structure to navigate (see attached screenshot).

Any ideas?

Here is the code I am running (it is a function in a larger script):

Func Drivers()

;Prompt to make sure directory is correct
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)
Opt("GUIOnEventMode", 0)
$Source = 'y:\' & $platform & '\' & $model & ' ' & $modelnum & '\x86\Win7\DriverPack'
$Destination = 'C:\Drivers'

If Not _Copy_OpenDll() Then
    MsgBox(16, '', 'DLL not found.')
    Exit
EndIf

$DriversCopyForm = GUICreate('Drivers Copy', 400, 175)
GUICtrlCreateLabel('Source:', 14, 23, 58, 14)
$SourceInput = GUICtrlCreateInput($Source, 74, 20, 248, 19, BitOR($ES_AUTOHSCROLL, $ES_LEFT, $ES_MULTILINE))
GUICtrlSetState(-1, $GUI_DISABLE)
$SourceBrowseButton = GUICtrlCreateButton('...', 326, 19, 21, 21)
GUICtrlCreateLabel('Destination:', 14, 55, 58, 14)
$DestinationInput = GUICtrlCreateInput($Destination, 74, 52, 248, 19, BitOR($ES_AUTOHSCROLL, $ES_LEFT, $ES_MULTILINE))
GUICtrlSetState(-1, $GUI_DISABLE)
$DestinationBrowseButton = GUICtrlCreateButton('...', 326, 51, 21, 21)
$ProgressBar = GUICtrlCreateLabel('',14, 91, 332, 14)
$Progress = GUICtrlCreateProgress(14, 106, 332, 16)
$CopyButton = GUICtrlCreateButton('Copy', 135, 138, 80, 21)
$PauseButton = GUICtrlCreateButton(';', 326, 138, 21, 21)
GUICtrlSetFont(-1, 10, 400, 0, 'Webdings')
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState()

While 1
    If $Copy Then
        $State = _Copy_GetState()
        If $State[0] Then
            If $State[0] = -1 Then
                ; Preparing
            Else
                $Data = Round($State[1] / $State[2] * 100)
                If GUICtrlRead($Progress) <> $Data Then
                    GUICtrlSetData($Progress, $Data)
                EndIf
                $Data = StringRegExpReplace($State[6], '^.*\\', '')
                If GUICtrlRead($ProgressBar) <> $Data Then
                    GUICtrlSetData($ProgressBar, $Data)
                EndIf
            EndIf
        Else
            Switch $State[5]
                Case 0
                    GUICtrlSetData($Progress, 100)
                    MsgBox(64, '', 'Folder was successfully copied.', 0, $DriversCopyForm)
                Case 1235 ; ERROR_REQUEST_ABORTED
                    MsgBox(16, '', 'Folder copying was aborted.', 0, $DriversCopyForm)
                Case Else
                    MsgBox(16, '', 'Folder was not copied.' & @CR & @CR & $State[5], 0, $DriversCopyForm)
            EndSwitch
            GUICtrlSetState($SourceBrowseButton, $GUI_ENABLE)
            GUICtrlSetState($DestinationBrowseButton, $GUI_ENABLE)
            GUICtrlSetState($PauseButton, $GUI_DISABLE)
            GUICtrlSetData($Progress, 0)
            GUICtrlSetData($ProgressBar, '')
            GUICtrlSetData($CopyButton, 'Copy')
            GUICtrlSetData($PauseButton, ';')
            $Copy = 0
        EndIf
    EndIf
    $Msg = GUIGetMsg()
    Switch $Msg
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $SourceBrowseButton
            $Path = FileSelectFolder('Select source folder where drivers should be copied from', '\\itserv\data\drivers', 2, $Source, $DriversCopyForm)
            If $Path Then
                GUICtrlSetData($SourceInput, $Path)
                $Source = $Path
            EndIf
        Case $DestinationBrowseButton
            $Path = FileSelectFolder('Select destination folder where drivers should be copied to.', 'C:\', 2, $Destination, $DriversCopyForm)
            If $Path Then
                GUICtrlSetData($DestinationInput, $Path)
                $Destination = $Path
            EndIf
        Case $CopyButton
            If $Copy Then
                _Copy_Abort()
            Else
                If (Not $Source) Or (Not $Destination) Then
                    MsgBox(16, '', 'The source and destination folders must be specified.', 0, $DriversCopyForm)
                    ContinueLoop
                EndIf
                $Path = $Destination & '\' & StringRegExpReplace($Source, '^.*\\', '')
                If FileExists($Path) Then
                    If MsgBox(51, 'Copy', $Path & ' already exists.' & @CR & @CR & 'Do you want to merge folders?', 0, $DriversCopyForm) <> 6 Then
                        ContinueLoop
                    EndIf
                EndIf
                GUICtrlSetState($SourceBrowseButton, $GUI_DISABLE)
                GUICtrlSetState($DestinationBrowseButton, $GUI_DISABLE)
                GUICtrlSetState($PauseButton, $GUI_ENABLE)
                GUICtrlSetData($ProgressBar, 'Preparing...')
                GUICtrlSetData($CopyButton, 'Abort')
                _Copy_CopyDir($Source, $Path, 0, 0, 0, '_Copy_CallbackDlg', $DriversCopyForm)
                $Copy = 1
            EndIf
        Case $PauseButton
            $Pause = Not $Pause
            If $Pause Then
                GUICtrlSetData($PauseButton, '4')
            Else
                GUICtrlSetData($PauseButton, ';')
            EndIf
            _Copy_Pause($Pause)
        EndSwitch
    WEnd
    Opt("GUIOnEventMode", 1)
EndFunc

post-85458-0-19728800-1397657795_thumb.p

Edited by thefritz

Share this post


Link to post
Share on other sites

Ah, found an older post on the forum detailing what was wrong.  Appears to be an issue with WinPE not parsing the FileSelectFolder the same way Windows itself does.  You must use a CLSID as the root folder.  For more details see >FileSelectFolder Function in a WinPE 2.0 Environment.

This post is for WinPE 2.0, but I can vouch that it does the same behavior in WinPE 3.0 and WinPE 5.0.  One thing that was different is they were saying that using the optional flag to specify what kind of options you want available in the dialog box would also break it, but I didnt experience that.  It was mostly likely because I had the HTA package added to my WinPE environment.  See WinPE: Add Packages (Optional Components Reference) for how to add the HTA and the HTA_en-US package.

Thanks

Share this post


Link to post
Share on other sites

Yashied

Is there are some way to implement freeing windows cache after file copying is done? So it doesn't hog all available memory after massive copy...

Share this post


Link to post
Share on other sites

Is it possible to "_Copy_MoveDir" a folder into a folder, without including the source folder? Or to state the question differently: is it possible to rename the source folder directly into the destination folder?

Note: I may be doing this wrong but I cannot make this work right which has caused me to resort to crude post-move DirMove / DirRemove combo.. which honestly sucks.

Share this post


Link to post
Share on other sites

Sorry to ask the question again: Is there already a fixed .dll for long filenames?

The copy functions still crashes with very long file names. (And the "?" prefix won´t work)

Thanks for your help!

Share this post


Link to post
Share on other sites

Thanks this is really nice.
Great UDF, enjoyed discovering its usage

 Au3Stripper complains :
Found Call() statement using unsolvable Func, which will / could lead To removal of Funcs that are used by this Function.
copy.au3(1095, 1) Warning For line : $Result = Call($cpSlot[$iID][1], $aState, $iID, $cpSlot[$iID][2])

is there some thing that can be amended to fix this error
thanks

Share this post


Link to post
Share on other sites

#78 ·  Posted (edited)

removed

Edited by Deye

Share this post


Link to post
Share on other sites

#79 ·  Posted (edited)

My next post ..

Edited by Deye

Share this post


Link to post
Share on other sites

I have a program crash when using Copy_x64.dll in Windows 10 64 bits and program compiled in x64, any idea? when i use the copy.dll with the same program compiled in x86 all works fine in the same pc.

Share this post


Link to post
Share on other sites

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