|
|
2023/12/4(Mon) 21:08:46|NO.100729
いつもお世話になっております。
早速ですが、
フォルダからフォルダへ、別途のフォルダをコピーしたとき、コピーの終了の通知を
windowsから受け取ることは出来ないものでしょうか。方法があれば教えていただきた
くお願いいたします。
dirlistを使う方法は試しましたが、コピーが完全に終わった段階で、即時に次の処理
に入りたいため不都合です。(フォルダ内のファイル数が多いと、コピーの途中でフォ
ルダーが作られるようです)
よろしくお願いいたします。
|
|
2023/12/7(Thu) 00:58:36|NO.100761
意図しているものとは違うかもしれませんが
win32apiのCopyFileEx関数を使えば進捗状況を知ることが出来ますよ
コピーが終了で関数を抜けます
進捗状況はコールバックで受け取ります
簡単にサンプル書いてみましたが、いかがでしょうか
#uselib "KERNEL32.DLL"
#func global CopyFileEx "CopyFileExA" sptr,sptr,sptr,sptr,sptr,sptr
#include "modclbk3.hsp"
//定数
#define global TRUE 1
#define global FALSE 0
#define global COPY_FILE_RESTARTABLE 0x00000002
//コールバック関数登録
newclbk3 wProc, 13, *WndProc
//コピー開始
// 実行ファイルがあるフォルダの1.zipを2.zipとしてコピー
mes "コピー中…"
pbCancel = FALSE
CopyFileEx dir_exe +"\\1.zip", dir_exe +"\\2.zip", wProc, 0, varptr(pbCancel), COPY_FILE_RESTARTABLE
mes "終わったよ"
stop
//コールバック関数
*WndProc
dim CopyProgress, 13
clbkargprotect CopyProgress
L_TotalFileSize = CopyProgress(0) // バイト単位の総ファイルサイズ
H_TotalFileSize = CopyProgress(1) // ふたつで64ビットを表現
L_TotalBytesTransferred = CopyProgress(2) // 転送された総バイト数
H_TotalBytesTransferred = CopyProgress(3)
L_StreamSize = CopyProgress(4) // このストリームの総バイト数
H_StreamSize = CopyProgress(5)
L_StreamBytesTransferred = CopyProgress(6) // このストリームに対して転送された総バイト
H_StreamBytesTransferred = CopyProgress(7)
dwStreamNumber = CopyProgress(8) // 現在のストリーム
dwCallbackReason = CopyProgress(9) // コールバック関数が呼び出された理由
hSourceFile = CopyProgress(10) // コピー元ファイルのハンドル
hDestinationFile = CopyProgress(11) // コピー先ファイルのハンドル
lpData = CopyProgress(12) // CopyFileEx 関数から渡される
return
| |
|
2023/12/8(Fri) 16:40:31|NO.100776
お返事ありがとうございます。
コピー先のフォルダーを監視し、コピーが終了したら次の処理を実行するというようなことを
考えています。説明が足りなくてすみませんでした。
|
|
2023/12/9(Sat) 01:25:11|NO.100778
もしかしてUNGAさんの聞きたいことは、
「"ユーザーが"特定のフォルダに対して特定の名前のサブフォルダをコピーしたかどうか」を
監視したいということですか?
(つまり、コピーを行うのはプログラムではなくユーザーである)
しかも、「サブフォルダが存在するだけでなく、サブフォルダの中身が全部
コピーされたことも監視したい」ということでしょうか?
そうなると、フェイズを2つに分けて、フェイズ1ではフォルダが存在することを確認し、
フェイズ2では中身がコピーされたことを確認する、という方法が思い浮かびましたが、
フェイズ1は難しくないとしても、問題はフェイズ2で、
「少なくともこのファイルがコピーされていればOK」というファイルがあるのなら
exist命令でそのファイルの存在を確かめればいいのですが、
「どんなファイルが入っているのかはわからない」となると、
ちょっと私には「dirlistを定期的に実行して、何秒か経ってもその内容が変化しないのなら
コピー完了とみなす」という方法しか思い浮かびません。
(この方法も、コピーに何秒もかかるような極端に大きなファイルがあると上手く行かないかもしれませんが)
#uselib "shlwapi.dll"
#cfunc global PathIsDirectory "PathIsDirectoryA" sptr
#include "winmm.as"
wait_time=3000 //フォルダ監視にかける時間(ミリ秒単位)
name="hoge" //対象のフォルダ名
home=dir_cur
//フェイズ1:フォルダが存在するかどうかを確認
repeat
if PathIsDirectory(name) : break //フォルダが存在するのなら脱出
await 500 //1秒間に2回判定する
loop
//フェイズ2:フォルダの中身を監視
chdir name
s=""
dirlist s,"*.*",0 : len0=strlen(s)
TimeGetTime : start=stat //現在のタイマーを取得
debug=0
repeat
await 500
dirlist s,"*.*",0 : len=strlen(s)
TimeGetTime
if len0!=len {
debug++
start=stat
len0=len
} else {
if stat>start+wait_time : break
}
loop
dialog "コピーが完了しました"
chdir home
stop
| |
|
2023/12/9(Sat) 02:10:16|NO.100779
以下の質問を見たとき、私も沢渡 さんと同様の疑問になりました。
>(フォルダ内のファイル数が多いと、コピーの途中でフォルダーが作られるようです)
HSP3はシングルタスクなので、命令でフォルダ生成やコピーを1つ1つしていれば
上記の現象は起こらないように思います。
とすると、沢渡 さんの言うユーザーが行うフォルダコピーを監視しているケースか、
exec命令や、別アプリなどがフォルダコピーを行うことでマルチタスクのような状況に
なっていることが想像できます。
(この場合ならプロセス終了を監視するなどの方法があります)
そのあたりの情報が不足しているので、可能でしたら質問箇所の説明もしくは
スクリプトを開示することは出来ませんでしょうか?
hspextのdirlist2命令を利用したものも考えましたが、
大容量ファイルやファイル数、フォルダ階層(再帰処理)が多いと監視には
不向きだと思います。
|
|
2023/12/10(Sun) 09:18:53|NO.100788
皆さま、お返事誠にありがとうございます。
やりたいことはまさしく沢渡さんのおっしゃっているとおりです。
現状では、コピー先を監視し通知を受け取ることは実現できています。
コピー終了後にやりたいことは、コピーされたフォルダーの名前の変更なのですが、
コピー元のフォルダー内のファイル数が多いと、変更が通知された時点ではフォル
ダーが作られていないことが多く、名前が変更されません。(なぜかエラーにはならない)
|
|
2023/12/10(Sun) 09:55:40|NO.100789
スクリプトの関連個所貼っておきました。
監視用モジュールの一部は省きました。
見にくくて申し訳ありません。
#deffunc stopEx label changed, label openw, label watch,local arr, local _stat
dim arr, 1
arr(0) = hObj
*@
// ウィンドウメッセージがくるかファイルが変更されるまで待機
if (observing == FALSE) { _stat = MsgWaitForMultipleObjects(0, 0, FALSE, 100, QS_ALLINPUT)
}else {
_stat = MsgWaitForMultipleObjects(length(arr), varptr(arr), FALSE, 100, QS_ALLINPUT)
}
// MsgWaitForMultipleObjects が制御を返したら内容に応じた処理を行う
if (observing == TRUE && _stat == WAIT_OBJECT_0) {
CheckIfFileUpdated
FindNextChangeNotification hObj
// もし変更されたのであればあらかじめ指定されたラベルにジャンプ
if (stat == 1) : gosub changed //監視フォルダが変更されたら *time_addへ
}
await 0
goto *@b
return
//------------------------------------main----------------------------------------------------------------------
dir_exe_=dir_cur
chdir dir_exe_
//バックアップ先の読み込み
bload "BackUp_Dir.txt",BackUp_Dir
dirlist fList_old,"*.*",2
file_old_no=stat
if file_old_no==0 : file_old_no=1
//--------------ウインドウの設定---------------------
screen 0,410,150
StartObservingFile BackUp_Dir //バックアップフォルダーの監視開始
if (stat == 0) : dialog "フォルダーの監視を開始するための処理に失敗しました" : end
stopEx *time_add, *open_window_get, *watch//変更検出時のルーチン
stop
//--------------フォルダに変化があった時に飛んでくるところ----------------------------------------------
*time_add
nen=str(gettime(0))
time="【"+strmid(nen,2,2)+"."+gettime(1)+"."+gettime(3)+" "+gettime(4)+"."+gettime(5)+"."+gettime(6)+"】"
chdir BackUp_Dir //バックアップ先
repeat 10 //現状10回繰り返しているが、バックアップ元フォルダーのファイル数が多いと引っかからない
wait 100
dirlist fList_new,"*.*",2
file_new_no=stat
if file_new_no<file_old_no { break } //バックアップ先のフォルダが削除された場合は何もしない
//if file_new_no==file_old_no { } //どのタイミングで新フォルダが作成されるのかが不確定
if file_new_no>file_old_no { //新フォルダが作成されたときの処理
repeat file_new_no
icchi=0
notesel fList_new
noteget new_file,cnt
repeat file_old_no
notesel fList_old
noteget old_file,cnt
if old_file==new_file { icchi=1 : break }
loop
if icchi==0 { //新しいフォルダが検出された
exist new_file
if strsize==-1 { time_newname=new_file+time} //コピー終了まで待機
else { time_newname=getpath(new_file,1)+time+getpath(new_file,2)}
fxren new_file,time_newname
if stat!=0 : dialog "ファイル名の書き換えに失敗しました。"
}
loop
break
}
loop
gsel 0,2
dirlist fList_old,"*.*",2
file_old_no=stat
return
//---------------------------------------------------------------------------------
| |
|
2023/12/10(Sun) 18:24:28|NO.100801
こちらで試すことはできませんが、現状、
「1秒間に1回チェックを行い、10回(都合10秒間)チェックを行ったら終了」
「ファイル数が増えていることが一度でも確認されたらチェックをやめる」
という仕様になっているので、これを以下のように
「ファイル数が増えていることが確認されたら、
そこから再度10秒間のチェックを行う」
「検出漏れを可能な限り避けられるよう、
プログラム終了時にも強制的にチェック処理を行う」
という仕様にしたらどうなるでしょうか?
dir_exe_=dir_cur
chdir dir_exe_
//バックアップ先の読み込み
bload "BackUp_Dir.txt",BackUp_Dir
//現状だとカレントディレクトリの内容をdirlistするようになっているので、
//バックアップフォルダ内の内容をdirlistするようにする。
chdir BackUp_Dir
dirlist fList_old,"*.*",2
file_old_no=stat
if file_old_no==0 : file_old_no=1
chdir dir_exe_
//--------------ウインドウの設定---------------------
screen 0,410,150
StartObservingFile BackUp_Dir //バックアップフォルダーの監視開始
if (stat == 0) : dialog "フォルダーの監視を開始するための処理に失敗しました" : end
onexit goto *exit
stopEx *time_add, *open_window_get, *watch//変更検出時のルーチン
stop
*exit
onexit 0 //もう一度[X]を押したら強制終了できるようにする
title "終了処理中"
gosub *time_add
end
//--------------フォルダに変化があった時に飛んでくるところ----------------------------------------------
*time_add
nen=str(gettime(0))
time="【"+strmid(nen,2,2)+"."+gettime(1)+"."+gettime(3)+" "+gettime(4)+"."+gettime(5)+"."+gettime(6)+"】"
chdir BackUp_Dir //バックアップ先
count_max=10
count=0
repeat
count++
wait 100
dirlist fList_new,"*.*",2
file_new_no=stat
if cnt=0 & file_new_no<file_old_no { break } //バックアップ先のフォルダが削除された場合は何もしない
//if file_new_no==file_old_no { } //どのタイミングで新フォルダが作成されるのかが不確定
if file_new_no>file_old_no { //新フォルダが作成されたときの処理
repeat file_new_no
icchi=0
notesel fList_new
noteget new_file,cnt
repeat file_old_no
notesel fList_old
noteget old_file,cnt
if old_file==new_file { icchi=1 : break }
loop
if icchi==0 { //新しいフォルダが検出された
exist new_file
if strsize==-1 { time_newname=new_file+time} //コピー終了まで待機
else { time_newname=getpath(new_file,1)+time+getpath(new_file,2)}
fxren new_file,time_newname
if stat!=0 : dialog "ファイル名の書き換えに失敗しました。"
}
loop
count=0 //変化を検出した場合はループカウントをやり直す
fList_old=fList_new : file_old_no=file_new_no //fList_oldとfile_old_noの内容を更新
//break //←「現在のファイル数>以前のファイル数」の状態になったからといってコピーが完了したとは限らないので
//breakはしない
}
if count>=count_max : break
loop
gsel 0,2
dirlist fList_old,"*.*",2
file_old_no=stat
chdir dir_exe_
return
//---------------------------------------------------------------------------------
また、「ファイル数の多いフォルダ」とは、コピーに最大でどのくらい
時間がかかるものでしょうか?
たとえばコピーに30秒くらいかかるようでしたら、
「1秒間に1回のチェックを10回」ではなく
「4秒間に1回のチェックを10回」に改めるというのはどうでしょうか?
| |
|
2023/12/10(Sun) 21:40:05|NO.100803
いろいろ考えていただいてありがとうございます。
沢渡さんのスクリプトでうまくいきました。
感謝です!
当面はこれで行こうと思います。
ただ、コピーにどれほどの時間がかかるかは不確定でもあるので、できればやはり
コピー終了の通知が受け取れればそれに越したことはないかなと思います。
引き続き皆様のご教授いただけましたらありがたいです。
|
|