[AHK] ファイルコピーで進捗状況を表示

      2018/10/04

大きなファイルをコピーするときには、コピーの進捗状況を表示できると便利ですよ。

SPONSORED LINK

フリーズかと見紛う FileCopy

AutoHotkeyでファイルコピーをする場合、通常FileCopyコマンドを使用します。しかし、コピーするファイルサイズが大きかったり、ドライブの速度が遅かったりすると、ファイルコピーしている間AutoHotkeyスクリプトは何の反応もしなくなります。

特にGUIを持つスクリプトの場合、裏ではコピーが実行されているのにGUIはWindowsに「応答なし」と判断されてしまうため、スクリプトがフリーズしたのか区別できなくなります。

SPONSORED LINK

進捗状況を表示できるファイルコピー方法

AutoHotkeyの標準コマンドだけでは進捗情報付きのファイルコピーはできません。そこでDllCallでCopyFileExを呼び出します。

; pSourceFilePath: コピー元ファイルパス
; pDestFilePath  : コピー先ファイルパス
FileCopyProgress(pSourceFilePath, pDestFilePath)
{
	global cancelFlag, gSourceSize, gCopiedSize, gProgressSizePrev
	callbackAdr := RegisterCallback("CopyProgressRoutine", "Fast")
	VarSetCapacity(cancelFlag, 1, 0)
	FileGetSize, gSourceSize, %pSourceFilePath%

	gCopyingFile := pSourceFilePath
	gCopiedSize:= 0
	gProgressSizePrev := 0
	DllCall( "CopyFileEx"
		, "WStr", pSourceFilePath
		, "WStr", pDestFilePath ".part"
		, "Ptr", callbackAdr
		, "Int", 0
		, "UInt", &cancelFlag
		, "UInt", 0x00000000 )
	FileMove, %pDestFilePath%.part, %pDestFilePath%
}

CopyProgressRoutine(pFullSize, var2, pProgressSize, var4)
{
	global gSourceSize, gCopiedSize, gProgerssSizePrev
	; pFullSize: 転送中のブロック全体のサイズ
	; pProgressSize: ブロック中のコピー済みファイルサイズ
	if(pProgressSize < gProgressSizePrev)
		gCopiedSize += gProgressSizePrev
	gProgressSizePrev := pProgressSize
	copiedMB := Round((pProgressSize + gCopiedSize) / 1024 / 1024, 1)
	sourceMB := Round(gSourceSize / 1024 / 1024, 1)
	percent := Round((pProgressSize + gCopiedSize) / gSourceSize * 100, 1)
	GuiControl, , editHoge, %copiedMB%MB / %sourceMB%MB 完了
	GuiControl, , editFuga, %percent% `%
}

ファイルコピー中に CopyProgressRoutine 関数が繰り返し呼ばれます。この中にGuiControlなどでGuiの書き換え処理を書いておけば、進捗を表示できます。

コピー失敗対策付き

コピーが開始されるとコピー先にファイルが作成されます。何らかの要因(スクリプトを強制終了する、PCの電源が落ちる など)で処理が中断されてしまうと、コピー途中なのにファイルが作成されていて、コピーがちゃんと完了しているのか分からなくなってしまいます。

そこでコピー処理では宛先ファイル名に「.part」を付加してコピーが途中であることを明示しておきます。コピーがちゃんと完了したら、宛先ファイル名から「.part」を外します。コピー途中で処理が中断してしまうと「.part」ファイルのままになっているのでコピーが失敗したことが分かります。こうなった場合は「.part」付きファイルは削除して改めてコピー処理を始めます。

コピーのキャンセル可能

CopFileEx にはキャンセルフラグの指定ができるので、cancelFlag を 1 にするとその時点でファイルコピーを中断できます。

注意点

CopyFileEx の仕様として、約3.8GB以上のファイルは約3.8GB単位に分割されて処理されます。このとき CopyProgressRoutine に渡される pFullSize と pProgressSize は分割単位のサイズです。

3.8GB以上のファイルをコピーする場合の対策として、全体サイズを事前取得し、コピー済みサイズ取得にちょっとした工夫を入れています。

itjo レスポンシブ 本文下

 - AutoHotkey
 - , ,