前回取り敢えず動く形にしましたが、リソース情報リスト処理を(将来ウィンドウズプログラムに移すので)それをエントリーポイント関数(現在はコンソールプログラムなのでmain()関数)から切り離し、ResourceListという関数に外出ししてみます。
以下は前回のResourceList01.cppからResourceList関数を外出ししたResourceList02.cppの主要変更点を抜粋したものです。
【ResourceList02.cpp】(抜粋)
//関数プロトタイプ宣言
bool ResourceList(LPCTSTR, HANDLE*); //解説:コールバック関数の宣言は止め、外出し関数のみとした。
//外部変数
TCHAR g_FileName[MAX_PATH]; //リソースを取得するEXEファイル名
HANDLE g_hFile; //リソースファイルのグローバルハンドル
/* 解説:ローカル変数化-解説:前回外部変数であった以下の変数はResouceList関数のローカル関数に移行しました。
TCHAR g_ResFileName[MAX_PATH]; //リソースファイル名(拡張子前g_FileName + "_resinfo.txt")
HMODULE g_hExe; //EXEファイルのハンドル
TCHAR szBuffer[MAX_PATH]; //infoファイル用プリントバッファ
DWORD cbWritten; //resource infoファイルへの書き込みサイズ
size_t cbString; //szBufferの文字列長
HRESULT hResult;
*/
//解説:処理を外出ししたのでmain関数はさっぱりしました。
//main関数(エントリーポイント)
int main() {
//対象ファイル名の指定
//lstrcpy(g_FileName, TEXT("C:\\Users\\(省略)\\TextToSpeech\\Debug\\TextToSpeech.exe"));
lstrcpy(g_FileName, TEXT("C:\\Users\\(省略)\\ResourceList\\Debug\\ResourceList02.exe"));
ResourceList(g_FileName, &g_hFile);
getch(); //コンソールを閉じない為
return 0;
}
/*コールバック関数の順を呼び出し逆順とする
解説:CやC++では、自分より後に宣言される関数は予めプロトタイプを宣言することが必要です。前回はコールバック変数すべてを宣言していましたが、EnumTypesFuncを呼び出すResourceList関数が最後尾に移動したので、その上にEnumTypesFunc、それがEnumNamesFuncを予備すので、その上にEnumNamesFunc、それがEnumLangsFuncを呼び出すので、EnumLangsFuncは更にその上に配置しました。
//リソース言語取得用コールバック関数EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG)
BOOL EnumLangsFunc(HMODULE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wLang, LONG lParam)
↑
//リソース名取得用コールバック関数
//EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG)
BOOL EnumNamesFunc(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam)
↑
//リソース種類取得用コールバック関数
//EnumTypesFunc(HANDLE, LPSTR, LONG)
BOOL EnumTypesFunc(HMODULE hModule, LPTSTR lpType, LONG lParam)
↑
ResourceList(LPCTSTR, HANDLE*)
*/
//コンソール版リソースリスト関数
//ResourceList(LPCTSTR, HANDLE*)
//解説:最後に外出ししたResourceList関数が来ます。
bool ResourceList(LPCTSTR FileName, HANDLE* ptFile) {
//解説:引数はロードする実行可能ファイル名とグローバル変数のファイルハンドルです。後者はグローバル変数で引数にする必要はないのですが、可読性を高め、呼び出し側のローカル変数でも対応できるようより汎用性を持たすべく(参照渡しに準じる)ポインター渡しにしています。
HMODULE hExe; //EXEファイルのハンドル
TCHAR ResFileName[MAX_PATH]; //リソースファイル名(拡張子前FileName + "_resinfo.txt")
TCHAR szBuffer[MAX_PATH]; //infoファイル用プリントバッファ
DWORD cbWritten; //resource infoファイルへの書き込みサイズ
size_t cbString; //szBufferの文字列長
HRESULT hResult;
//リソースを列挙するEXEファイルをロードする
hExe = LoadLibrary(TEXT(FileName));
if(hExe == NULL) {
printf("実行可能ファイルを読み込めません。");
getch(); //コンソールを閉じない為
return FALSE;
}
//リソース情報を収容するファイルを開く
lstrcpyn(TEXT(ResFileName), TEXT(FileName), lstrlen(TEXT(FileName)) - 3); //".exe"は4文字だが、lstrcpynはNULLを含むので(-4 + 1)となる
lstrcat(TEXT(ResFileName), TEXT("_resinfo.txt"));
*ptFile = CreateFile(TEXT(TEXT(ResFileName)), //リソースファイル名
GENERIC_READ | GENERIC_WRITE, //アクセスモード
0, //シェアモード
(LPSECURITY_ATTRIBUTES) NULL, //デフォルトセキュリティ
CREATE_ALWAYS, //フラグの作成
FILE_ATTRIBUTE_NORMAL, //ファイルアトリビュート
(HANDLE) NULL); //テンプレート無し
if(*ptFile == INVALID_HANDLE_VALUE) {
printf(TEXT("リソース情報ファイルを作成できませんでした。"));
getch(); //コンソールを閉じない為
return FALSE;
}
//ロードされたファイルのすべてのリソースを読み込む
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR),
TEXT("%s\r\nのファイルには以下のリソースがあります。\r\n"), FileName);
if(FAILED(hResult)) {
//(読み込み失敗時の処理を記述)
printf("実行可能ファイルのリソースを読み込めません。");
getch(); //コンソールを閉じない為
return FALSE;
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), &cbString);
if(FAILED(hResult)) {
//(読み込み失敗時の処理を記述)
printf("文字列が指定した長さを超えました。");
getch(); //コンソールを閉じない為
return FALSE;
}
WriteFile(*ptFile, //resource infoを書き込むファイルハンドル
szBuffer, //書き込みバッファー
(DWORD)cbString, //szBufferの書き込みサイズ
&cbWritten, //書き込みバイト数
NULL); //オーバーラップドI/Oは無し
EnumResourceTypes(hExe, //読み込みモジュールのハンドル
(ENUMRESTYPEPROC)EnumTypesFunc, //コールバックファンクションアドレス
0); //補足パラメーター
//ロードして、リソースを列挙したた実行可能ファイルをアンロードし、リソース情報ファイルを閉じる。
FreeLibrary(hExe);
CloseHandle(*ptFile);
printf("リソース情報ファイルを書き出しました。");
return TRUE;
}