Moin,
auf Wunsch eines geschätzten langjährigen deutschen Mitglieds der AHK-Gemeinde habe ich das folgende Skript von AHK 1.0 (Basic) in die 'modernere' Welt von AHK 1.1 überführt. Es stellt eine Funktion zum Kopieren eines Verzeichnisses bereit, die mit einer eigenen Gui über den Fortschritt der Aktion informiert.
Die Funktion hat folgende Parameter:
- Source
Pfad des Quellverzeichnisses mit oder ohne abschließendem Backslash \ - Dest
Pfad des Zielverzeichnisses mit oder ohne abschließendem Backslash \ - Optional: Flag
0 = Dateien im Zielverzeichnis nicht überschreiben
1 = Dateien im Zielverzeichnis überschreiben
2 = Zielverzeichnis ggf. vor dem Kopieren löschen
Standard: 1 - Optional: Pattern
Dateiauswahlmuster (z.B. "*.ahk") oder Komma-getrennte Liste von Dateierweiterungen (z.B. "ahk,ini,hlp")
Standard: "" = "*.*"
Bei Vorgabe eines Suchmusters werden Ordner, die keine entsprechenden Dateien enthalten, nicht übernommen! - Optional: Owner
Name, Nummer oder HWND/ID der 'Eigentümer-Gui'
Wenn die Funktion fehlerfrei komplett durchläuft, gibt sie 1 (Wahr/True) zurück, sonst 0 (Falsch/False).
Wer Änderungswünsche hat oder eine Version für AHK v2 wünscht, der melde sich.
Code: Select all
#NoEnv
SetBatchLines, -1
Quelle := "D:\AHK_Alt"
Ziel := "D:\AHK_Sav"
MsgBox, % CopyDirWithProgress(Quelle, Ziel, 2, "ahk,ini,txt")
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
; CopyDirWithProgress()
;
; Funktion:
; Kopieren von Verzeichnissen mit erweiterter Funktionalität.
; 1. Gui mit Fortschrittsanzeige
; 2. Löschen des Zielverzeichnisses vor dem Kopieren
; 3. Auswahl bestimmter Dateien mittels Suchmuster
;
; Parameter:
; Source Quellverzeichnis
; Dest Zielverzeichnis
; Optional: Flag 0 = Dateien im Zielverzeichnis nicht überschreiben
; 1 = Dateien im Zielverzeichnis überschreiben
; 2 = Zielverzeichnis ggf. vor dem Kopieren löschen
; Standard: 1
; Optional: Pattern Dateiauswahlmuster (z.B. "*.ahk") oder Komma-getrennte
; Liste von Dateierweiterungen (z.B. "ahk,ini,hlp")
; Standard: "" = "*.*"
; Bei Vorgabe eines Suchmusters werden Ordner, die keine
; entsprechenden Dateien enthalten, nicht übernommen!
; Optional: Owner Name, Nummer oder HWND/ID der 'Eigentümer-Gui'
;
; Danksagung:
; Mein spezieller Dank gilt Superfraggle, ahklerner und tonne für
; http://www.autohotkey.com/forum/post-143928.html
; ----------------------------------------------------------------------------------------------------------------------
CopyDirWithProgress(Source, Dest, Flag := 1, Pattern := "", Owner := "") {
; -------------------------------------------------------------------------------------------------------------------
; Statische Variablen
Static Callback := RegisterCallback(A_PtrSize = 8 ? "CopyDirWithProgress_Progress_64"
: "CopyDirWithProgress_Progress_32")
Static DeleteDest := 2
Static OverWrite := 1
; -------------------------------------------------------------------------------------------------------------------
; Sprachabhängige Konstanten
Static TXG := {EN: " Copy" , DE: " Kopieren"}
Static TXS := {EN: "Source:`t`t" , DE: "Quelle:`t"}
Static TXD := {EN: "Destination:`t" , DE: "Ziel:`t"}
Static TXC := {EN: "Cancel" , DE: "Abbruch"}
Static TXT := {EN: "Total: " , DE: "Gesamt: "}
Static TXS1 := {EN: "Getting files ..." , DE: "Dateien werden ermittelt ..."}
Static TXS2 := {EN: "File " , DE: "Datei "}
Static TXS3 := {EN: " of " , DE: " von "}
Static TXS4 := {EN: "Done!" , DE: "Fertig!"}
Static TXS5 := {EN: "Terminated!" , DE: "Abgebrochen!"}
Static TXM1 := {EN: "Error while copying file " , DE: "Fehler beim Kopieren der Datei "}
Static TXM2 := {EN: "Size of source: " , DE: "Originalgröße: "}
Static TXM3 := {EN: "Size of copy: " , DE: "Größe der Kopie: "}
Static TXM4 := {EN: "Terminate the copying?" , DE: "Kopiervorgang abbrechen?"}
; -------------------------------------------------------------------------------------------------------------------
; Spracheinstellung
Static LANG := (SubStr(A_Language, 3) = "07") ? "DE" : "EN"
; -------------------------------------------------------------------------------------------------------------------
; Parameter auswerten
Source := RTrim(Source, "\")
If !InStr(FileExist(Source), "D") {
MsgBox, 16, %A_ThisFunc%, Ungültiges Quellverzeichnis:`n%Source%
Return False
}
Dest := RTrim(Dest, "\")
MEXT := ""
If (Pattern = "")
Pattern := "*.*"
Else If InStr(Pattern, ",") {
MEXT := Pattern
Pattern := "*.*"
}
; -------------------------------------------------------------------------------------------------------------------
; Zielverzeichnis ggf. löschen?
If (Flag = DeleteDest) {
If (FileExist(Dest)) {
FileRemoveDir, %Dest% , 1
If (ErrorLevel) {
MsgBox, 16, %A_ThisFunc%, Das Zielverzeichnis`n%Dest%`nkonnte nicht gelöscht werden!
Return False
}
}
}
; -------------------------------------------------------------------------------------------------------------------
; Objekt für den Informationsaustausch mit der Callback-Funktion initialisieren
CDWP := {HGUI: 0, HPGB1: 0, HPGB2: 0, TotalSize: 0, FileCopied: 0, TotalCopied: 0, Cancel: False}
; -------------------------------------------------------------------------------------------------------------------
; Gui
TxtW := 600 ; minimale Breite
Gui, New, +AlwaysOnTop +HwndHGUI +Toolwindow +OwnDialogs +LastFound +Owner%Owner% +Label_CDE_Gui_
Gui, Margin, 10, 10
Gui, Add, Text, xm hwndHCTL, % TXS[LANG] . Source
GuiControlGet, P, Pos, %HCTL%
TxtW := Max(TxtW, PW)
Gui, Add, Text, xm y+5 hwndHCTL, % TXD[LANG] . Dest
GuiControlGet, P, Pos, %HCTL%
TxtW := Max(TxtW, PW)
Gui, Add, Text, xm w%TxtW% hwndHTX1 +0x8000 ; SS_PATHELLIPSIS = 0x8000
Gui, Add, Progress, xm y+3 wp hwndHPGB1 cLime, 0 ; -Smooth
Gui, Add, Text, xm y+5 wp, % TXT[LANG]
Gui, Add, Progress, xm y+3 wp hwndHPGB2 cLime, 0 ; -Smooth
BtnX := 10 + TxtW - 100
Gui, Add, Button, x%BtnX% w100 hwndHCTL g_CDE_Gui_Close, % TXC[LANG]
GuiControlGet, P, Pos, %HBTN%
TxtW -= PW
Gui, Add, Text, xm yp w%TxtW% h%PH% hwndHSB +0x0200, % TXS1[LANG]
Gui, Show, , % TXG[LANG]
CDWP.HGUI := HGUI
CDWP.HPGB1 := HPGB1
CDWP.HPGB2 := HPGB2
; -------------------------------------------------------------------------------------------------------------------
; Anzahl der Dateien und Gesamtgröße ermitteln
StartPos := StrLen(Source) + 1
CDWP.TotalSize := 0
Files := 0
Paths := []
Index := 0
Loop, Files, %Source%\%Pattern%, % (Pattern = "*.*" ? "DFR" : "FR")
{
NewFile := Dest . SubStr(A_LoopFileLongPath, StartPos)
If (Flag = 0) && FileExist(NewFile)
Continue
If (MEXT) {
If A_LoopFileExt Not In %MEXT%
Continue
}
IsDir := InStr(A_LoopFileAttrib, "D")
If !(IsDir) {
CDWP.TotalSize += A_LoopFileSize
Files++
}
Paths[++Index] := {Src: A_LoopFileLongPath, Dst: NewFile, Size: IsDir ? "D" : A_LoopFileSize}
}
; -------------------------------------------------------------------------------------------------------------------
; Dateien kopieren
Gui, +OwnDialogs
CDWP.TotalCopied := 0
CDWP.Cancel := False
Index := 0
LastDir := ""
For I, File In Paths {
NewFile := File.Dst
If (File.Size = "D") {
If !FileExist(NewFile) {
FileCreateDir, %NewFile%
If (ErrorLevel) {
MsgBox, 16, %A_ThisFunc%, Das Verzeichnis`n%NewFile%`nkonnte nicht erstellt werden!
Gui, %HGUI%:Destroy
Return False
}
}
LastDir := File.Dst
Continue
}
GuiControl, , %HSB% , % TXS2[LANG] . ++Index . TXS3[LANG] . Files
SplitPath, NewFile, , Dir
If (Dir != LastDir) {
If !FileExist(Dir) {
FileCreateDir, %Dir%
If (ErrorLevel) {
MsgBox, 16, %A_ThisFunc%, Das Verzeichnis`n%Dir%`nkonnte nicht erstellt werden!
Gui, %HGUI%:Destroy
Return False
}
}
LastDir := Dir
}
GuiControl, , %HTX1%, % File.Src
GuiControl, , %HPGB1%, 0
CDWP.FileCopied := 0
RetVal := DllCall("CopyFileEx", "Str" , File.Src, "Str" , NewFile, "Ptr", Callback
, "Ptr", &CDWP, "Ptr", 0, "UInt", 0)
Sleep, -1
If (CDWP.Cancel)
Break
If (RetVal = 0) || (ErrorLevel != 0) || (CDWP.FileCopied < File.Size) {
MsgBox, 36, %A_ThisFunc%, % TXM1[LANG] . NewFile . "!`n`n"
. "RetVal: " . RetVal . " *`n"
. "A_LastError: " . A_LastError . " *`n"
. TXM2[LANG] . File.Size . " *`n"
. TXM3[LANG] . CDWP.FileCopied . " *`n`n"
. TXM4[LANG]
IfMsgBox, Yes
{
FileDelete, %NewFile%
Gui, %HGUI%:Destroy
Return False
}
}
CDWP.TotalCopied += File.Size
}
; -------------------------------------------------------------------------------------------------------------------
; Fertig!
GuiControl, , %HPGB1%, 0
GuiControl, , %HSB%, % CDWP.Cancel ? TXS5[LANG] : TXS4[LANG]
Sleep, 1000
Gui, %HGUI%:Destroy
Return % CDWP.Cancel ? False : True
; -------------------------------------------------------------------------------------------------------------------
_CDE_Gui_Close:
_CDE_Gui_Escape:
CDWP.Cancel := True
Return
}
; ------------------------------------------------------------------------------
; Callback-Funktion f�r die Fortschrittsanzeige - 32-Bit
CopyDirWithProgress_Progress_32(P1L, P1H, P2L, P2H, P3L, P3H, P4L, P4H, P5, P6, P7, P8, P9) {
; LARGE_INTEGER TotalFileSize (2 * Integer)
; LARGE_INTEGER TotalBytesTransferred (2 * Integer)
; LARGE_INTEGER StreamSize (2 * Integer)
; LARGE_INTEGER StreamBytesTransferred (2 * Integer)
; DWORD dwStreamNumber
; DWORD dwCallbackReason
; HANDLE hSourceFile
; HANDLE hDestinationFile
; LPVOID lpData
CDWP := Object(P9)
FileSize := (P1H << 32) + P1L
CDWP.FileCopied := (P2H << 32) + P2L
GuiControl, % CDWP.HGUI . ":", % CDWP.HPGB1, % Round(CDWP.FileCopied / FileSize * 100)
GuiControl, % CDWP.HGUI . ":", % CDWP.HPGB2, % Round((CDWP.FileCopied + CDWP.TotalCopied) / CDWP.TotalSize * 100)
Return CDWP.Cancel
}
; Callback-Funktion f�r die Fortschrittsanzeige - 64-Bit
CopyDirWithProgress_Progress_64(P1, P2, P3, P4, P5, P6, P7, P8, P9) {
; LARGE_INTEGER TotalFileSize
; LARGE_INTEGER TotalBytesTransferred
; LARGE_INTEGER StreamSize
; LARGE_INTEGER StreamBytesTransferred
; DWORD dwStreamNumber
; DWORD dwCallbackReason
; HANDLE hSourceFile
; HANDLE hDestinationFile
; LPVOID lpData
CDWP := Object(P9)
FileSize := P1
CDWP.FileCopied := P2
GuiControl, % CDWP.HGUI . ":", % CDWP.HPGB1, % Round(CDWP.FileCopied / FileSize * 100)
GuiControl, % CDWP.HGUI . ":", % CDWP.HPGB2, % Round((CDWP.FileCopied + CDWP.TotalCopied) / CDWP.TotalSize * 100)
Return CDWP.Cancel
}
Anmerkung:
Die zugehörige API-Funktion CopyFileEx() ruft eine Callback-Funktion auf, um u.a. eine Fortschrittsanzeige zu ermöglichen. Die ersten vier Parameter der Funktion sind 64-Bit Werte. Die werden mit AHK 64-Bit in einem Parameter, mit AHK 32-Bit aber in zwei Parametern übergeben. Deshalb gibt es zwei Versionen der Callback-Funktion. Alternativ wäre es möglich, die unterschiedlichen Parameter innerhalb einer Funktion unterschiedlich zu behandeln.