Win 環境で 2 重起動の禁止

投稿日 by Iwao

ライブラリとして提供されている部分を,他のコードと分離するためコンソール AP(変換 exe)として作成.
テスト用にそれを呼出す部分も別のコンソール AP(呼出 exe)として作成.
変換 exe は,aaa.dat を aaa.txt の様に異なる形式に変換する機能.
呼出 exe は,::ShellExecute(…,”変換.exe aaa.dat”,…) の様に呼出し aaa.txt を処理する.
データにより変換(*.dat から *.txt へ)時間は数秒から数時間.
変換できたかどうかをチェックしている部分は次の様なコード.

for (size_t index=0 ; index<1000 ; index++) {
	::Sleep(100) ;
	if (::File_IsExist(g3d_name))	{	break ;		}
	}

データが悪いのか,ライブラリの問題なのかは不明たが,変換 exe の中でエラーになってしまうことがある.
エラーを軽減する方法はわかっているが,それでも完全ではない.
同じデータでも通る時とそうでないことがあり不安定.
そのため,変換後データが存在しない時に,変換中でなければ「変換 exe」を再起動させなければならない.


2021/03/09
ここまでの部分を単体のコードとして作成.
t_call.cpp
t_conv.cpp
T_mtex_2021_03_09.zip
変換 exe 呼出し 単体テスト
これらのコードでの問題は,
* 異常終了が判断できない.
* 変換に時間がかかる時,複数回呼んでしまう.


起動しているかどうかは Mutex を使えば良さそう.
変換 exe が起動している間,::CreateMutex (…,”入力ファイル名”) で作成したものを保持する.
呼出 exe のループでは,その Mutex が存在するかチェック.
なくなった時に,出力ファイルが存在している時はループを抜ける.
出力ファイルが存在していない時は,もう一度「変換 exe」を呼出す.


今まで作成の Mutex を使用したコード.
Prevent2.hxx Prevent2.cxx
ExclusS.hxx


t_conv.cpp

bool	test	(const tstring& name_in_)
{
	tstring	f_name = ::Path_GetName(name_in_) ; 
	HANDLE	hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; 
	time_t	now = ::time(NULL) ;
	if ((now % 3) == 0) {
		::Sleep(3000) ;
		tstring	name_out = name_in_ + _T(".out") ;
		tstring	name_uni = ::Get_unique_name(name_out) ;
		::File_CreateEmpty(name_uni) ;
		}
	else {
		::Sleep(500) ;
		}
	::CloseHandle(hMutex) ; 
	return	true ;
	}

t_call.cpp

bool	t_call	(c_tstring& in_name_)
{
	tstring	name_in_ = in_name_ ;
	{
		tstring	f_name = ::Path_GetName(name_in_) ; 
		HANDLE	hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; 
		DWORD	error  = ::GetLastError() ; 
		::CloseHandle(hMutex) ; 
		if (error == ERROR_ALREADY_EXISTS) { 
			return	true ; 
			} 
		}
	tstring	this_exe = ::i_GetModuleFileName() ;
	tstring	conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ;
	    	name_in_ = ::QuotM_Add_Auto(name_in_) ;
	//	...
	//	変換 exe を起動
	//	...
	return	true ;
	}

Mutex で exe の起動を管理


2021/03/10 更にクラスに.W_mutex.hxx
次の様にできる.

bool	test	(const tstring& name_in_)
{
	W_mutex	mutex(::Path_GetName(name_in_).c_str()) ; 
	time_t	now = ::time(NULL) ;
	if ((now % 3) == 0) {
		::Sleep(3000) ;
		tstring	name_out = name_in_ + _T(".out") ;
		tstring	name_uni = ::Get_unique_name(name_out) ;
		::File_CreateEmpty(name_uni) ;
		}
	else {
		::Sleep(500) ;
		}
	return	true ;
	}

bool	t_call	(c_tstring& in_name_)
{
	tstring	name_in_ = in_name_ ;
	{
		W_mutex	mutex(::Path_GetName(name_in_).c_str()) ; 
		if (mutex.Is_exist())	{	return	true ;	} 
		}
	tstring	this_exe = ::i_GetModuleFileName() ;
	tstring	conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ;
	    	name_in_ = ::QuotM_Add_Auto(name_in_) ;
	//	...
	return	true ;
	}
この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ



コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください