• Hallo Oscar.

    Läuft super.

    Geht das auch incl. Unterverzeichnisse?


    LG,
    Crazy-A.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • Hi
    erstmal: Sehr genial, meine Hochachtung!

    hab einen (möglichen) Bug entdeckt:
    Zeile 77: $sNewFolder = StringReplace(StringReplace($aSource[$i], $sFile, ''), $sSourcePath, '')
    Ein Ordner kann durchaus zb "Test.zip" heißen. Wenn nun eine Datei in diesem Ornder auch "Test.zip" heißt, dann wird auch der Ordner replaced!
    Deshalb hab ich die Zeile 77 auf folgende geändert:
    $sNewFolder = StringTrimLeft(StringLeft($aSource[$i],StringInStr($aSource[$i],"\",0,-1)),StringLen($sSourcePath))

    weiters hab ich mir erlaubt einen weiteren Parameter hinzuzufügen:
    _MultiFileCopy($aSource, $sDestPath, $bOverWrite = True, $sPreFix = "Copy")

    Wenn $bOverWrite=False, dann wird die ZielDatei, falls sie existiert, nicht überschrieben, sondern mit dem Prefix umbenannt ("Text.txt" wird zu "Copy1_Text.txt")
    Falls auch die "Copy1_Text.txt" schon existiert, dann "Copy2_Text.txt"
    und die Zieldateien werden als Array zurückgegeben

    Ich brauchte das so für ein Projekt von mir...

    Script 2 mal laufen lassen, dann sollten die Dateien der 2 Demo (Zeile 28 ) umbenannt werden!

    Spoiler anzeigen
    [autoit]

    ;===werden benötigt=============================================================
    #include<String.au3>
    #include<WindowsConstants.au3>
    #include<Misc.au3>
    ;===============================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;===Beispiel 1 (komplettes Verzeichnis kopieren)================================
    ; Alle Dateien und Unterverzeichnisse (rekursiv) werden kopiert
    ; Verzeichnisstruktur der Quelle wird übernommen
    Global $sSourcePath = 'C:\Programme\AutoIt3\AutoitX'
    Global $sDestinationPath = @ScriptDir & '\Tmp1'; Zielpfad (wird ggf. erstellt)

    [/autoit] [autoit][/autoit] [autoit]

    $Ret=_MultiFileCopy($sSourcePath, $sDestinationPath)
    For $i= 1 to $Ret[0]
    MsgBox(0, "Dateien überschreiben", $i & " / " & $Ret[0] & @CRLF & $Ret[$i])
    Next
    ;===============================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;===Beispiel 2 (mehrere Dateien kopieren)=======================================
    ; Alle Dateien aus dem Array werden ins Zielverzeichnis kopiert
    ; Array[0] muss die Anzahl der zu kopierenden Dateien enthalten
    Global $aSource[4] = [3, @SystemDir & '\shell32.dll', @SystemDir & '\mspaint.exe', @SystemDir & '\eula.txt']
    Global $sDestinationPath = @ScriptDir & '\Tmp2'; Zielpfad (wird ggf. erstellt)

    [/autoit] [autoit][/autoit] [autoit]

    $Ret=_MultiFileCopy($aSource, $sDestinationPath, False)
    For $i= 1 to $Ret[0]
    MsgBox(0,"Vorhandene Dateien umbenennen", $i & " / " & $Ret[0] & @CRLF & $Ret[$i])
    Next
    ;===============================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ;
    ; Function Name: _MultiFileCopy
    ; Description:: Kopiert mehrere Dateien mit Progressbar
    ; Parameter(s): Array mit Dateien zum kopieren, Zielpfad
    ; Requirement(s):
    ; #include<String.au3>
    ; #include<WindowsConstants.au3>
    ; #include<Misc.au3>
    ; Author(s): Tom99, progandy and Oscar (http://www.autoit.de)
    ;
    ;===============================================================================
    ;
    Func _MultiFileCopy($aSource, $sDestPath, $bOverWrite = True, $sPreFix = "Copy")
    Local $opt = Opt('GUICloseOnESC', 0), $ret, $sShowSource, $sShowDest, $sSourcePath = '', $sNewFolder = '', $i, $j, $k
    Local $aMFC[12] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, False, DllOpen('user32.dll')]
    If Not IsArray($aSource) Then
    $sSourcePath = $aSource
    If StringRight($sSourcePath, 1) <> '\' Then $sSourcePath &= '\'
    ToolTip('Bitte warten! Verzeichnis wird eingelesen!')
    $aSource = _GetFilesFolder_Rekursiv($aSource, '*', 0)
    ToolTip('')
    Else
    If Not IsNumber($aSource[0]) Then Return SetError(1, 0, 0)
    EndIf
    Local $aReturn = $aSource
    If StringRight($sDestPath, 1) <> '\' Then $sDestPath &= '\'
    If Not FileExists($sDestPath) Then
    If Not DirCreate($sDestPath) Then Return SetError(2, 0, 0)
    EndIf
    $sShowDest = StringRegExpReplace($sDestPath, '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
    Local $aFileSize[UBound($aSource)]
    For $i = 1 To $aSource[0]
    $aFileSize[$i] = FileGetSize($aSource[$i])
    $aMFC[7] += $aFileSize[$i]
    Next
    Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
    Local $ptr = DllCallbackGetPtr($callback)
    __ProgressCreate($aMFC)
    $aMFC[9] = TimerInit()
    For $i = 1 To $aSource[0]
    $sArray = ''
    For $j = 0 To 11
    $sArray &= $aMFC[$j] & ';'
    Next
    If $sSourcePath <> '' Then
    $sNewFolder = StringTrimLeft(StringLeft($aSource[$i],StringInStr($aSource[$i],"\",0,-1)),StringLen($sSourcePath))
    If Not FileExists($sDestPath & $sNewFolder) Then
    If Not DirCreate($sDestPath & $sNewFolder) Then Return SetError(3, 0, 0)
    EndIf
    EndIf
    $sFile = StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
    $k = 0
    While $bOverWrite=False And FileExists($sDestPath & $sNewFolder & $sFile)
    $k+=1
    $sFile=$sPreFix & $k & "_" & StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
    WEnd
    $sShowSource = StringRegExpReplace($aSource[$i], '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
    GUICtrlSetData($aMFC[1], 'Kopiere Datei ' & @CRLF & '"' & $sShowSource & '"' & @CRLF & 'nach: "' & $sShowDest & '"')
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $aSource[$i], 'str', $sDestPath & $sNewFolder & $sFile, 'ptr', $ptr, 'str', $sArray, 'int', 0, 'int', 0)
    $aReturn[$i] = $sDestPath & $sNewFolder & $sFile
    ;~ ConsoleWrite('Return: ' & $ret[0] & @LF)
    If $ret[0] = 0 Then $aMFC[10] = True
    $aMFC[8] += $aFileSize[$i]
    Next
    GUIDelete($aMFC[0])
    DllClose($aMFC[11])
    Opt('GUICloseOnESC', $opt)
    Return $aReturn
    EndFunc ;==>_MultiFileCopy

    [/autoit] [autoit][/autoit] [autoit]

    Func __ProgressCreate(ByRef $aMFC)
    $aMFC[0] = GUICreate('FileCopy', 480, 220, -1, -1, $WS_POPUPWINDOW)
    $aMFC[1] = GUICtrlCreateLabel('', 10, 10, 460, 65)
    GUICtrlSetFont(-1, 10, 400, 0, 'Courier New')
    GUICtrlCreateLabel('Datei:', 10, 83, 60, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[2] = GUICtrlCreateLabel('0 %', 80, 83, 390, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[4] = GUICtrlCreateProgress(10, 100, 460, 20)
    GUICtrlCreateLabel('Gesamt:', 10, 133, 60, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[3] = GUICtrlCreateLabel('0 %', 80, 133, 390, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[5] = GUICtrlCreateProgress(10, 150, 460, 20)
    $aMFC[6] = GUICtrlCreateButton('Abbrechen', 200, 185, 75, 25)
    GUICtrlSetFont(-1, 9, 400, 0, 'Arial')
    GUISetState()
    Sleep(200)
    EndFunc ;==>__ProgressCreate

    [/autoit] [autoit][/autoit] [autoit]

    Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)
    Local $aSplit = StringSplit(StringTrimRight($lpData, 1), ";")
    If $aSplit[11] = 'True' Then Return 1
    Local $pos = GUIGetCursorInfo($aSplit[1])
    If _IsPressed('1B', Int($aSplit[12])) Then Return 1
    If _IsPressed('01', Int($aSplit[12])) And ($pos[4] = Int($aSplit[7])) Then Return 1
    Local $sPercent = Round($BytesTransferred / $FileSize * 100, 0), $iTime, $iTotalTime, $iTransferRate
    Local $sPercentAll = Round(($aSplit[9] + $BytesTransferred) / $aSplit[8] * 100, 0)
    If GUICtrlRead($aSplit[5]) <> $sPercent Then
    $iTime = TimerDiff($aSplit[10])
    $iTotalTime = Ceiling($iTime / 1000 / ($sPercentAll + 0.1) * 100)
    $iTransferRate = _StringAddThousandsSep(Int($aSplit[8] / $iTotalTime / 1000), '.', ',')
    GUICtrlSetData($aSplit[3], $sPercent & ' %')
    GUICtrlSetData($aSplit[5], $sPercent)
    If GUICtrlRead($aSplit[6]) <> $sPercentAll Then
    GUICtrlSetData($aSplit[4], $sPercentAll & ' % Zeit: ' & Int($iTime / 1000) & '/' & $iTotalTime & ' s (' & $iTransferRate & ' KB/s)')
    GUICtrlSetData($aSplit[6], $sPercentAll)
    EndIf
    EndIf
    EndFunc ;==>__Progress

    [/autoit] [autoit][/autoit] [autoit]

    ;==================================================================================================
    ; Function Name: _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
    ; Description: Rekursive Auflistung von Dateien und/oder Ordnern
    ; Parameter(s): $sPath der Basispfad für die Auflistung ('.' -aktueller Pfad, '..' -Parentpfad)
    ; $sExt Erweiterung für Dateiauswahl '*' oder -1 für alle (Standard)
    ; $iDir -1 Dateien+Ordner(Standard), 0 nur Dateien, 1 nur Ordner
    ; optional: $iRetType 0 gibt Array, 1 gibt String zurück
    ; optional: $sDelim legt Trennzeichen für Stringrückgabe fest
    ; 0 -@CRLF (Standard) 1 -@CR 2 -@LF 3 -';' 4 -'|'
    ; Return Value(s): Array (Standard) od. String mit den gefundenen Pfaden der Dateien und/oder Ordner
    ; Array[0] enthält die Anzahl der gefundenen Dateien/Ordner
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;==================================================================================================
    Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
    Global $oFSO = ObjCreate('Scripting.FileSystemObject')
    Global $strFiles = ''
    Switch $sDelim
    Case '1'
    $sDelim = @CR
    Case '2'
    $sDelim = @LF
    Case '3'
    $sDelim = ';'
    Case '4'
    $sDelim = '|'
    Case Else
    $sDelim = @CRLF
    EndSwitch
    If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
    If $sExt = -1 Then $sExt = '*'
    If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
    _ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
    If $iRetType = 0 Then
    Local $aOut
    $aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
    If $aOut[1] = '' Then
    ReDim $aOut[1]
    $aOut[0] = 0
    EndIf
    Return $aOut
    Else
    Return StringTrimRight($strFiles, StringLen($sDelim))
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
    If Not IsDeclared("strFiles") Then Global $strFiles = ''
    If ($Dir = -1) Or ($Dir = 0) Then
    For $file In $Folder.Files
    If $Ext <> '*' Then
    If StringRight($file.Name, StringLen($Ext)) = $Ext Then _
    $strFiles &= $file.Path & $Delim
    Else
    $strFiles &= $file.Path & $Delim
    EndIf
    Next
    EndIf
    For $Subfolder In $Folder.SubFolders
    If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
    _ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
    Next
    EndFunc

    [/autoit]

    Außerdem hab ich die Variablen $i und $j in der Funktion deklariert, da es sonst zu Problemen kommen kann, wenn man die Funktion in einer $i-Schleife aufruft...

    lgE

    • Offizieller Beitrag


    Außerdem hab ich die Variablen $i und $j in der Funktion deklariert, da es sonst zu Problemen kommen kann, wenn man die Funktion in einer $i-Schleife aufruft...

    Das kann nicht passieren, $i und $j sind Variablen in For-Schleifen. Diese werden per default als Local deklariert.

  • Ciao! nicht schlecht das Ganze :D

    könnte man das Fenster so kreieren, dass der User das auch minimieren kann ?

    Bei mir tritt der Fehler auf, wenn ich ein Fenster (während dem Kopieren) auf die MultiFileCopy Anwendung schiebe..
    und alles wieder minimiere, und dann wieder zurück schiebe..das MultiFileCopy dann wie hängt (grafik) mässig kommt es nicht mehr mit, könnte man das anders lösen? was ist Schuld? die GUI Komponente von Autoit?


    greet;s satinez

  • Bei mir friert das Fenster immer ein ich weiss nicht warum.
    Er kopiert ein Teil der Daten dann zeigt das Fenster nichts mehr an und es steht (Keine Rückmeldung).
    Dann kann ich es nicht verschieben und Abbrechen funzt auch nicht mehr :(

    Mache ich da was falsch? Die Dateien die er kopieren soll, kommen von einer Netzwerkfreigabe
    was eigentlich kein Problem sein sollte.

    Danke, auch wenn ich aufdringlich bin, ich finde dieses Script sehr nützlich und würde es gerne weiterhin gebrauchen :)

    Einmal editiert, zuletzt von satinez (15. November 2008 um 13:54)

    • Offizieller Beitrag

    Netzwerkfreigabe! Habe ich gerade mal getestet. Das stimmt!
    Dabei gibt es ein Problem: Das Script kopiert zwar im Hintergrund weiter, aber das Fenster wird nach kurzer Zeit nicht mehr refresht (siehe Screenshot). ?(
    Wobei das nur beim kopieren über's Netz passiert (egal ob Laufwerksbuchstabe oder Pfad und egal ob Quelle oder Ziel).

    Screenshot:
    AutoItImage.GIF

    Vielleicht kann sich das einer unserer DLL-Profis mal ansehen?

  • Liegt denn das wirklich an der DLL ?

    hmmm..gibts denn da ne möglichkeit, den windows normalen kopier-dialog zu verwenden ?

    • Offizieller Beitrag

    Wobei das nur beim kopieren über's Netz passiert (egal ob Laufwerksbuchstabe oder Pfad und egal ob Quelle oder Ziel).


    Ich denke, das ist ein reines Windows-Problem. Wenn ich per Explorer ins Netz kopiere, funktioniert die Fortschrittsanzeige auch nur bedingt, d.h. die Statusbar arbeitet rein nach Anzahl der Dateien (z.B. 2 Dateien - je 50% Statusbar) und zeigt diesen 'Fortschritt' bei Beginn des Kopiervorgangs für diese Datei an. Ist die letzte Datei eine größere, hast du ewig eine 100% - Anzeige.

    • Offizieller Beitrag

    BugFix : Kann ich nicht nachvollziehen. Bei mir funktioniert die Anzeige beim kopieren mit dem Explorer ganz normal (vom Netzwerklaufwerk auf's Lokale Laufwerk und umgekehrt). Habe ich gerade mal getestet, weil ich ja sonst immer den TotalCommander dafür benutze. :)

    Ich hab auch schon versuchsweise, die Zeilen zum Abbrechen aus meinem Script entfernt, aber das Problem bleibt. ?(