2018年02月21日

VC++でファイル更新待ち

長らく棚上げになっていたファイル更新待ち関数を暫定的に書き換えた、とくに数値はテキトー。忘れても紛失してもいいようにメモしておく、スレッドセーフでもなんでもないトラディショナルC言語的なアプリでもそうしたいときはあるのだ。

// ファイル更新を無限に待つ
// arg:filename rv=0:OK
int waitFileUpdate(char *target){
BOOL b;
DWORD d;
HANDLE hFFCN, hFile;
FILETIME rv, ftbefore, ftafter;
char sDrive[2048], sDir[2048], sFile[2048], sExt[2048], tDir[2048];

hFile = CreateFile( target ,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if( 0==hFile ) return(-1); // ファイルがない場合
GetFileTime( hFile, NULL, NULL, &ftbefore);
CloseHandle( hFile );

//対象ディレクトリ名を作成して監視対象にする
_splitpath(target, sDrive, sDir, sFile, sExt);
if(0==strlen(sDrive)+strlen(sDir)) strcpy(sDir, ".\\");
sprintf(tDir, "%s%s", sDrive, sDir);
hFFCN = FindFirstChangeNotification(
tDir,FALSE,FILE_NOTIFY_CHANGE_LAST_WRITE);
if(INVALID_HANDLE_VALUE==hFFCN) return(-1);

while(1){
//Dir更新待ち
b = FindNextChangeNotification(hFFCN);
if(b==0)return(-2);
//検出事象
d = WaitForSingleObject(hFFCN,INFINITE);
if(d==WAIT_OBJECT_0){
Sleep(50);
// ディレクトリ更新を検出
hFile = CreateFile( target ,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if( 0!=hFile ){ // ファイルがある場合だけ検査
GetFileTime( hFile, NULL, NULL, &ftafter);
CloseHandle( hFile );
if( 0 != CompareFileTime(&ftafter,&ftbefore) ){
// 更新されたのが指定ファイルである
break;
}
}
}else if(d==WAIT_TIMEOUT){ return(-11); // 時間切れ
}else if(d==WAIT_ABANDONED){ return(-12); // 異常終了
}else if(d==WAIT_FAILED){ return(-13); // 異常終了
}else{
return(-21); // 不明なエラー
}
}

b = FindCloseChangeNotification(hFFCN);
if(b==0) return(-3);

return(0);
}
posted by JUD at 01:42| Comment(0) | TrackBack(0) | プログラミング