Copyright© 1998-2021 Web Technology Corp.
Copyright© CRI Middleware Co., Ltd.
拡張モジュールとは、EXEpressの自己解凍実行ファイルまたはEXEpressアンインストーラの動作を拡張することができる、ユーザー開発のDLLファイルを指します。
本ドキュメントでは、拡張モジュールDLLファイルを開発するための技術資料を提供しています。
後述の仕様に従ってDLLを作成します。64bit版の自己解凍実行ファイルで使用するためには、64bitのDLLとして作成する必要があります。
拡張モジュールが自由に使えるパラメータファイル extparam.dat(ファイル名自由)を用意します。パラメータファイルを使わない場合は不要です。
拡張モジュールの実行時には、このパラメータファイルはテンポラリフォルダに置かれた別名のファイルとなっていますので注意してください(変更されたファイル名はパラメータとして渡されます)。
DLLファイル、パラメータファイルそれぞれを自己解凍化する書庫ファイルに格納し、EXEpressの「拡張モジュール」ページにおいてファイル名として指定してください。
なお、拡張モジュールのDLLファイルおよびパラメータファイルは、解凍先フォルダには解凍されません。ただし、後述するアンインストーラ用の拡張モジュールを自己解凍実行ファイル用と同一のDLLファイルとして利用する場合は、DLLファイルについては解凍先フォルダへの解凍が行われます。
DLLファイルを自己解凍化する書庫ファイルに格納し、EXEpressの「EXEpressアンインストーラの設定」においてファイル名として指定してください。
拡張モジュールはWin32 DLL形式ファイルとして開発する必要があるため、DLLの開発に対応した開発環境が必要です。
本SDKのヘッダファイル、サンプルソースは、以下の推奨開発環境を前提としています。
拡張モジュールはC言語、または、C++言語を使用して開発します。拡張モジュールの作成に必要なAPIや各種の定義は、添付ヘッダファイル(ep_ext.h)に記載されています。
拡張モジュールのDLLは、自己解凍実行ファイルの起動直後に、それ単体がテンポラリフォルダにコピーされてからロードされます。このため、開発に使用したランタイムライブラリ(CRT、ATL、MFCなど)などを動的にリンクしていると、ファイル不足でDLLのロードが正常に行えなくなる場合があります。
この問題を避けるためには、拡張モジュールのDLLが必要とする、すべてのランタイムライブラリを静的にリンクするようにしてください。
アンインストーラの拡張モジュールは、インストール先フォルダ上のファイルが直接ロードされ、実行されます。必要なデータがある場合は、書庫ファイルにデータファイルとして含めておき、DLLのロード時またはEPEXT_UNINST_INITIALIZE
の時点で読み込みを行ってください。
解凍先フォルダの他のファイルがすべて削除された後に拡張モジュールのコールバックが呼び出される場合(EPEXT_UNINST_FINALIZE
)もありますので、必要なデータを読み込むタイミングには注意が必要です。
また、解凍先フォルダのパスが必要な場合は、自分自身の置かれているフォルダを検出するか、EXEpressの「インストール先を次のレジストリに保存し、次回以降に解凍先フォルダとして使用する」機能を用いてレジストリに解凍先フォルダを記録しておき、それを読み取って使用することもできます。
EXEpress拡張モジュールで必要となる、DLLがエクスポートするAPIはひとつだけです。以下のどちらかを実装・エクスポートしてください。
INT WINAPI EXEpressExtension(EXEPRESSEXTENSION_INFO* lpInfo);
INT WINAPI EXEpressExtensionW(EXEPRESSEXTENSION_INFOW* lpInfo);
EXEpressExtension()
はANSI文字列バージョン、EXEpressExtensionW()
はUnicode文字列バージョンとなります。
lpInfoは本体から与えられるパラメータです。
C++言語の場合は、extern "C"
を付加し、C言語形式関数としてエクスポートしてください。
また、拡張モジュールとしての処理は、すべてこのAPIの内部で行ってください。DLLのDllMain()
関数内で拡張モジュールとしての特殊な処理を行うことは避けてください。
EXEPRESSEXTENSION_INFO構造体とEXEPRESSEXTENSION_INFOW構造体は、文字列型がANSIかUnicodeかという点以外に違いはありません。
typedef struct
{
DWORD dwSize;
INT nPhase;
HWND hWnd;
LPCSTR lpszDialogTitle;
LPCSTR lpszExeFile;
LPCSTR lpszInfoFile;
LPARAM lParam1;
LPARAM lParam2;
LPARAM lParam3;
LPARAM lParam4;
LPARAM lUserParam;
EXEPRESS_EXTRACTFILE lpfnExtractFile;
EXEPRESS_REGISTERINSTALLEDFILE lpfnRegisterInstalledFile;
} EXEPRESSEXTENSION_INFO;
typedef struct
{
DWORD dwSize;
INT nPhase;
HWND hWnd;
LPCWSTR lpszDialogTitle;
LPCWSTR lpszExeFile;
LPCWSTR lpszInfoFile;
LPARAM lParam1;
LPARAM lParam2;
LPARAM lParam3;
LPARAM lParam4;
LPARAM lUserParam;
EXEPRESS_EXTRACTFILEW lpfnExtractFile;
EXEPRESS_REGISTERINSTALLEDFILEW lpfnRegisterInstalledFile;
} EXEPRESSEXTENSION_INFOW;
構造体のサイズが格納されています。将来のバージョンではサイズが増加する可能性がありますので、サイズチェックを行ってバージョンの判断を行うことができます。
このメンバを参照することで「今何をやっているところか」を判断することができます。
必要に応じてlParam1~lParam4のパラメータが使用されます(特記されていない場合はいずれも使用しません)。
自己解凍実行ファイルの起動時、ウィザード表示前に1回だけ呼ばれます。
自己解凍実行ファイルのウィザードの最初のページが表示され、「次へ」を押した後に呼ばれます。ユーザーが「戻る」・「次へ」した場合は複数回呼び出されることになります。
「ウィザード無し」を指定した自己解凍実行ファイルの場合は呼び出されません。
「解凍先フォルダ」を入力して「次へ」を押した直後。解凍先パスが確定した状態で呼ばれます。ユーザーが「戻る」で解凍先フォルダを再設定した場合、複数回呼び出されることになります。
「解凍先フォルダをユーザーが選択できるようにする」が有効化されていない自己解凍実行ファイルや、「ウィザード無し」を指定した自己解凍実行ファイルの場合は、もともと設定されていた解凍先フォルダがセットされた状態で呼び出されます。
lParam1はLPCSTR(LPCWSTR)形式で、解凍先フォルダのフルパスが格納されています。
自己解凍実行ファイルの各格納ファイルの解凍前。ファイルごとに呼ばれます。
lParam1はLPCSTR(LPCWSTR)形式で、解凍しようとしているファイル名(解凍後フルパス)が格納されています。
lParam2はLPCSTR(LPCWSTR)形式で、解凍しようとしているファイル名(アーカイブ内)が格納されています。
自己解凍実行ファイルの各格納ファイルの解凍後。
lParam1はLPCSTR(LPCWSTR)形式で、解凍したファイル名(解凍後フルパス)が格納されています。
lParam2はLPCSTR(LPCWSTR)形式で、解凍したファイル名(アーカイブ内)が格納されています。
全ファイルの解凍が完了し、スタートメニュー項目登録やアンインストーラ情報ファイルの生成が開始される前のタイミングで1回だけ呼ばれます。
自己解凍終了時、Windowsの再起動が必要かどうかの問い合わせとして1回だけ呼ばれます。
lParam1は数値で、この値が0以外の場合、EXEpress側では再起動を必要としている状態(ファイルの上書きに失敗したなど)であることを示します。
この呼び出しに対し、EPEXTRET_NEEDREBOOT
を返却すると、自己解凍実行ファイルはユーザーに対してWindowsの再起動要求を出します。EPEXTRET_NONEEDREBOOT
を返すと再起動要求は行われません。
EXEpress自身が再起動を必要としている状態(lParam1が0以外)であっても、EPEXTRET_NONEEDREBOOT
を返すと再起動要求が出なくなるので注意してください。
それ以外の値を返した場合は、再起動要求の表示・非表示への影響はありません。
自己解凍実行ファイルの全処理が完了し、後処理プログラムが起動する直前に1回だけ呼ばれます。
処理途中に何らかの原因で処理が中断したことを示します。
lParam1は数値で、エラーコードが格納されています。エラーコードはep_ext.hに定義された「EP_ABORT_***
」の定数のいずれかとなります。
lParam2はLPCSTR形式で、エラーの詳細を含むメッセージ(実行環境に応じて、日本語または英語のいずれか)の文字列が格納されています。
lParam3はBOOL*(BOOL型へのポインタ)型で、このBOOL値にTRUEを格納すると実際にエラーメッセージの表示を行い、FALSEを格納するとエラーメッセージの表示が行われません(この関数の呼び出し時には自動的にTRUEがセットされています)。
この呼び出しがユーザーのキャンセル処理に起因する場合(lParam1がEP_ABORT_USERCANCEL
)は、lParam3の内容に関わらずメッセージの表示は行われません。
アンインストーラの起動時、「アンインストールを実行しますか?」の問い合わせが終わり、アンインストール状況表示ウィンドウが表示される前に1回だけ呼ばれます。
ファイル削除の開始直前。ユーザーへのアンインストールの実行確認を行った後に1回だけ呼ばれます。この段階以降、ユーザーによる処理キャンセルが発生することはありません。
ファイルの削除前に行いたい、追加のアンインストール処理(例:ライセンス認証の解除処理など)がある場合は、この段階で行ってください。
アンインストーラ終了時、Windowsの再起動が必要かどうかの問い合わせとして1回だけ呼ばれます。
lParam1は数値で、この値が0以外の場合、EXEpressアンインストーラ側では再起動を必要としている状態(ファイルの削除に失敗したなど)であることを示します。
この呼び出しに対し、EPEXTRET_NEEDREBOOT
を返却すると、自己解凍実行ファイルはユーザーに対してWindowsの再起動要求を出します。EPEXTRET_NONEEDREBOOT
を返すと再起動要求は行われません。
EXEpressアンインストーラ自身が再起動を必要としている状態(lParam1が0以外)であっても、EPEXTRET_NONEEDREBOOT
を返すと再起動要求が出なくなるので注意してください。
それ以外の値を返した場合は、再起動要求の表示・非表示への影響はありません。
アンインストーラのアンインストール処理がすべて完了(他のファイルの削除が完了)した段階で1回だけ呼ばれます。
レジストリやファイルの削除はこの段階ですでに行われており、残存していません。それ以外に追加で行いたいアンインストール処理があれば、ここで行うことができます。
hWndメンバには、EXEpressの自己解凍実行ファイルまたはアンインストーラの画面のウィンドウハンドルが格納されています。ウィザード無しとした場合や、ウィザード終了後に呼び出される処理など、ウィンドウが存在しない場合はNULLとなります。
ダイアログボックスやメッセージボックスを表示する場合は、このウィンドウハンドルを親としてモーダル表示するようにしてください。
なお、hWndを利用するなどして、EXEpress自己解凍実行ファイルまたはアンインストーラのウィンドウデザインやボタンの動作の改変や、EXEpressにより作成されていることを隠匿するような改変を行うことは、一切禁止いたします。
このメンバは、EXEpressの自己解凍実行ファイルを作成する際に、ウィンドウタイトルとして設定された文字列が格納されています。
自己解凍実行ファイルの表示するメッセージ類とユーザーインターフェースを統一するためには、拡張モジュールがメッセージボックスを表示する場合にも、この文字列をタイトルバー文字列として設定するようにしてください。
このメンバは、「アンインストーラ登録情報」の「登録名」に設定された文字列が格納されています。
アンインストーラの表示するメッセージ類とユーザーインターフェースを統一するためには、拡張モジュールがメッセージボックスを表示する場合にも、この文字列をタイトルバー文字列として設定するようにしてください。
このメンバは、自己解凍実行ファイル(自己解凍実行ファイル用の場合)/アンインストーラ実行ファイル(アンインストーラ用の場合)のフルパス・ファイル名が格納されています。
このメンバは、自己解凍実行ファイル作成時に「拡張モジュール」ページで指定したパラメータファイルの、実行時のフルパス・ファイル名です。
このファイルは自己解凍実行ファイルによって解凍され、テンポラリファイルとなっています。このため、実際のファイル名は自己解凍実行ファイルを作成した時の設定で指定したファイル名とは異なっている点に注意してください。
拡張モジュールはこのファイルを開いて中身を自由に参照・変更することができますが、削除はしないでください。また、処理が完了した際にファイルハンドルを必ず閉じておいてください。自己解凍実行ファイルの終了時に自動的に削除されます。
このパラメータは、拡張モジュール側が自由に使用することができます。初期値は0となっています。
このパラメータにセットされた値は常に保持されており、EXEpressExtension()
のすべての呼び出し段階において自由に読み書きを行うことができます。
EXEpressの自己解凍実行ファイル側は、この値を変更することはありません。
このメンバは本体提供の「ファイル解凍関数」です。自己解凍内の任意のファイルを展開し、HGLOBAL形式で得ることができます。
typedef HGLOBAL (WINAPI *EXEPRESS_EXTRACTFILE)(LPCSTR);
※EXEPRESSEXTENSION_INFO構造体の場合
typedef HGLOBAL (WINAPI *EXEPRESS_EXTRACTFILEW)(LPCWSTR);
※EXEPRESSEXTENSION_INFOW構造体の場合
引数は文字列型で、解凍したいファイルの書庫内パスを指定します。
解凍処理に失敗した場合、戻り値はNULLとなります。
成功した場合、戻り値はHGLOBAL型です。GMEM_FIXED形式でメモリブロックを確保するため、この値を直接ポインタにキャストして内容にアクセスすることができます。メモリブロックのサイズが知りたい場合は、GlobalSize()
APIを使用します。
メモリブロックの解放はWindows APIのGlobalFree()
で行います。呼び出し側(拡張モジュール側)が責任を持って解放してください。
このメンバは本体提供の「アンインストール対象への登録関数」です。拡張モジュールが独自にコピー・生成などしたファイルを、EXEpress Uninstaller実行時のアンインストール(ファイル削除)対象に加えることができます。
この関数は、nPhase
がEPEXT_EXTRACT_COMPLETE
である場合のみ動作します。それ以外で呼んだ場合の動作は未定義です。
typedef BOOL (WINAPI *EXEPRESS_REGISTERINSTALLEDFILE)(LPCSTR);
※EXEPRESSEXTENSION_INFO構造体の場合
typedef BOOL (WINAPI *EXEPRESS_REGISTERINSTALLEDFILEW)(LPCWSTR)
※EXEPRESSEXTENSION_INFOW構造体の場合
引数は文字列型で、登録したいファイルのフルパスを指定します。
処理に失敗した場合、戻り値はFALSEとなります。成功した場合、戻り値はTRUEです。
nPhaseによって示されるいずれの段階の場合でも、EPEXTRET_NOERROR
が正常終了、EPEXTRET_ERROR
がエラーになります。
専用のエラーコードEPEXTRET_EXECUTESILENT
を利用可能です。これを返すと、ウィザード画面を表示しない、サイレントモードでの解凍を行うようになります。EXEpressの「詳細設定」-「デザイン」ページで「ウィザード無し」を指定したのと同じ動作です。逆に、もともと「ウイザード無し」を指定していた場合は、「新スタイル」のウィザードを表示します。
専用のエラーコードEPEXTRET_RETRY
を利用可能です。これを返すと、ウィザードの最初のページから次へ進むことができません。シリアルキー入力をさせる、などの処理に利用できます。
専用のエラーコードEPEXTRET_SKIP
を利用可能です。これを返すと、当該ファイルは解凍されずスキップされます。
専用のエラーコードEPEXTRET_NEEDREBOOT
およびEPEXTRET_NONEEDREBOOT
を利用可能です。
詳細はEPEXT_QUERYREBOOT
またはEPEXT_UNINST_QUERYREBOOT
それぞれの解説を参照してください。
nPhaseの段階ごとに解説しています。
この段階では、「自己解凍を起動してもよいか」のチェックを行うことができます。EPEXTRET_NOERROR以外を返すと、自己解凍実行ファイルは何もエラーメッセージを表示せずに終了します。
エラーが発生した場合など、ユーザーに対してのメッセージを表示したい場合は、エラーコードを返す前に拡張モジュール側で行ってください。
また、この段階で何らかの処理(ファイルのコピーやレジストリへの書き込み)を行う場合は、必ずメッセージボックスなどでユーザーに問い合わせを行い、同意が得られる場合のみ実行するようにしてください。
この段階では、解凍処理を始める前に必要な追加情報の収集を行うことができます。
EPEXTRET_RETRYを返すと、次のページに進むことができません。シリアルキーを入力させてチェックする、などに利用できます。
EPEXTRET_NOERROR以外(EPEXTRET_RETRY除く)のエラーコードを返すと、処理が中止されます。
この段階では、実際の解凍処理で個々のファイルを解凍する前に処理を行うことができます。
lParam1には解凍後のフルパスファイル名、lParam2には書庫内のファイル名がLPCSTR型で格納されています。
EPEXTRET_SKIPを返すと当該ファイルは解凍されません。ただし、そのファイルをlpfnExtractFileコールバック関数で解凍して得ることができます。これを利用することで、特定のファイルを解凍せずに取り出すことができます。
EPEXTRET_NOERROR以外(EPEXTRET_SKIP除く)のエラーコードを返すと、解凍処理が中止されます。
この段階では、個々のファイルが解凍された後の処理を行うことができます。
lParam1には解凍後のフルパスファイル名、lParam2には書庫内のファイル名がLPCSTR型で格納されています。
この時点で、実際に解凍先フォルダに解凍されたファイルの内容を読み書きすることが可能です。
EPEXTRET_NOERROR以外のエラーコードを返すと、解凍処理が中止されます。
この段階では、すべての解凍処理が完了し、「終了後自動実行」が開始される前に処理を行うことができます。
特別な「お疲れ様でした」メッセージの表示を行うなどの処理を行うことができます。
自動実行機能を使わない場合、この処理が終わった後に「解凍が完了しました」のページが表示されます。
EPEXTRET_NOERROR以外のエラーコードを返すと、解凍処理をキャンセルしたものとみなされます。
この段階では、アンインストーラを実行するかどうかのチェックを行うことができます。EPEXTRET_NOERROR以外を返すと、アンインストーラは何もエラーメッセージを表示せずに終了します。
エラーが発生した場合など、ユーザーに対してのメッセージを表示したい場合は、エラーコードを返す前に拡張モジュール側で行ってください。
EPEXT_UNINST_INITIALIZEは、アンインストーラが「アンインストールを実行しますか?」の問い合わせにユーザーが「はい」と答えた場合のみ呼び出されます。このため、実際に何かファイルやデータの削除を行う場合は、ユーザーへの問い合わせをあらためて行う必要はありません。
ただし、ユーザーが作成したデータファイルなど、削除するかどうかを個別に選択したいようなファイルまたはデータがある場合には、ユーザーへの問い合わせを行うこともできます。
添付されているサンプル拡張モジュールは、イベントが発生した際にメッセージを表示するだけの単純な動作を行うものです。
自己解凍実行ファイル用とアンインストーラ用の拡張モジュールは、いずれも同じ構造体・同じAPI名を使用しており、コールバックに渡される定数(nPhase)が両者で明確に分離されています。
このため、定数の識別をしっかりと行うことで、ひとつのDLLファイル中に、自己解凍実行ファイル用とアンインストーラ用の拡張モジュール機能を両方まとめて実装することができます。
EXEpressの自己解凍実行ファイルは、通常、自己解凍実行ファイル用の拡張モジュール用DLLファイルをインストール先フォルダに解凍しません。しかし、アンインストーラ用拡張モジュールファイルとして同じファイルを指定した場合に限り、その拡張モジュールファイルをインストール先フォルダに解凍します。