HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2023
1204
UNGAコピーの終了の通知をwindowsから受け取る方法を教えてください。8未解決


UNGA

リンク

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



UNGA

リンク

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



ze-na

リンク

2023/12/9(Sat) 02:10:16|NO.100779

以下の質問を見たとき、私も沢渡 さんと同様の疑問になりました。

>(フォルダ内のファイル数が多いと、コピーの途中でフォルダーが作られるようです)

HSP3はシングルタスクなので、命令でフォルダ生成やコピーを1つ1つしていれば
上記の現象は起こらないように思います。

とすると、沢渡 さんの言うユーザーが行うフォルダコピーを監視しているケースか、
exec命令や、別アプリなどがフォルダコピーを行うことでマルチタスクのような状況に
なっていることが想像できます。
(この場合ならプロセス終了を監視するなどの方法があります)

そのあたりの情報が不足しているので、可能でしたら質問箇所の説明もしくは
スクリプトを開示することは出来ませんでしょうか?

hspextのdirlist2命令を利用したものも考えましたが、
大容量ファイルやファイル数、フォルダ階層(再帰処理)が多いと監視には
不向きだと思います。



UNGA

リンク

2023/12/10(Sun) 09:18:53|NO.100788

皆さま、お返事誠にありがとうございます。
やりたいことはまさしく沢渡さんのおっしゃっているとおりです。
現状では、コピー先を監視し通知を受け取ることは実現できています。

コピー終了後にやりたいことは、コピーされたフォルダーの名前の変更なのですが、
コピー元のフォルダー内のファイル数が多いと、変更が通知された時点ではフォル
ダーが作られていないことが多く、名前が変更されません。(なぜかエラーにはならない)



UNGA

リンク

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回」に改めるというのはどうでしょうか?



UNGA

リンク

2023/12/10(Sun) 21:40:05|NO.100803

いろいろ考えていただいてありがとうございます。
沢渡さんのスクリプトでうまくいきました。
感謝です!
当面はこれで行こうと思います。

ただ、コピーにどれほどの時間がかかるかは不確定でもあるので、できればやはり
コピー終了の通知が受け取れればそれに越したことはないかなと思います。

引き続き皆様のご教授いただけましたらありがたいです。



記事削除

記事NO.パスワード
(質問が解決したスレッドは他の利用者に活用してもらうため、削除しないようお願いします)

NO.100729への返信

マスコット

好きなマスコットを選んでください。

名前

e-mail
HOME
  1. 初めて利用する方は、HSP3掲示板の使い方をお読みください。
  2. 不要部分の多い長いスクリプトの投稿は ご遠慮ください。
  3. 書き込みは自動改行されません。適度に改行を入れてください。
  4. スクリプトは小文字の<pre>〜</pre>で囲むと見やすく表示できます。

削除用パスワード

解決したら質問者本人がここをチェックしてください。

エラー発生時、再送信すると二重送信になることがあります。
回答が得られたら、お礼書き込み時に[解決]チェックしてください。
SPAM防止のためURLから始まる文章は投稿できません。
SPAM防止のため英文字のみの本文を投稿することはできません。

ONION software Copyright 1997-2023(c) All rights reserved.