EXEサーバ - コマンドラインの解析

いちごパック > COM/ActiveXの解説 > EXEサーバ - コマンドラインの解析

コマンドラインの解析

EXEサーバはウィンドウアプリケーションであればWinMain()、 コンソールアプリケーションであればmain()から開始します。 ここではWinMain()を例として説明します。 WinMain()の形は次の通りです。
EXTERN_C int APIENTRY WinMain(
        HINSTANCE hinstEXE, HINSTANCE hinstNull,
        LPSTR lpCmdLine, int nCmdShow );
コマンドラインはlpCmdLineに与えられますので、これを解析します。 次の例では、まずどのコマンドラインが与えられてもCOMシステムが利用できるように、 CoInitialize()を呼び出します。 その後、コマンドラインを解析し、指定された機能を呼び出しています。
    HRESULT hr;
    hr = CoInitialize(NULL);
    if ( FAILED(hr) ) {
        MessageBoxW( NULL, L"CoInitialize()", L"IchigoCom2", MB_OK );
        return 1;
    }
    const char* pcommand;
    bool invalid_command = false;
    pcommand = strchr(lpCmdLine, '/');
    if ( pcommand == NULL ) {
        pcommand = strchr(lpCmdLine, '-');
    }
    if ( pcommand == NULL ) {
        invalid_command = true;
    }
    if ( pcommand != NULL ) {
        char* ptoken = _strdup(pcommand + 1);
        if ( ptoken == NULL ) {
            hr = E_OUTOFMEMORY;
        } else {
            strtok( ptoken, " \t\r\n" );
            if ( _stricmp(ptoken, "embedding") == 0 ) {
                hr = RunEmbedding( hinstEXE );
            } else if ( _stricmp(ptoken, "regserver") == 0 ) {
                hr = RunRegisterServer( hinstEXE, false );
            } else if ( _stricmp(ptoken, "regserverperuser") == 0 ) {
                hr = RunRegisterServer( hinstEXE, true );
            } else if ( _stricmp(ptoken, "unregserver") == 0 ) {
                hr = RunUnregisterServer( false );
            } else if ( _stricmp(ptoken, "unregserverperuser") == 0 ) {
                hr = RunUnregisterServer( true );
            } else {
                invalid_command = true;
            }
            free(ptoken);
        }
    }
    CoUninitialize();
    if ( invalid_command ) {
        ... コマンドラインエラー処理 ...
    }
strchrで'/'または'-'を探し、strtok()で文字列を切り出したうえで、 _stricmp()により大文字小文字を区別せずに文字列を比較しています。 この例で使っているstrtok()はコマンドラインを書き換えてしまうので、 コマンドラインを他の用途にも利用する場合は、 別の方法でコマンドラインをチェックしたほうが良いかもしれません。

レジストリへの登録

DLLサーバはInprocServer32に登録しましたが、EXEサーバはLocalServer32に登録します。 また、モジュールの名前はDLLファイルではなくEXEファイルの名前になります。 それ以外の部分はDLLサーバと同じです。
HRESULT RunRegisterServer( HINSTANCE hinstEXE,
                           bool per_user_flag ) throw()
{
    try {
        std::wstring    wstrName = suppGetModuleFileName( hinstEXE );
        HKEY    hkeyRoot;
        std::wstring    wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag,
                                     CLSID_Ichigo2, L"LocalServer32" );
        LONG    regerr;
        if ( wstrSubkey.empty() || wstrName.empty() ) {
            return E_FAIL;
        }
        regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), NULL,
                                   wstrName.c_str() );
        if ( regerr != ERROR_SUCCESS ) {
            return SELFREG_E_CLASS;
        }
    } catch ( const std::exception& ) {
        return E_FAIL;
    }
    return S_OK;
}
登録解除についてはDLLサーバとほとんど同じ内容ですので、省略します。 suppではじまるヘルパ関数については別ページでまとめていますので、 サンプルで用いたヘルパ関数をご覧ください。

関連ページ

  • COM/ActiveXの解説ページ 目次
  • 前の項目: サーバ処理の流れ
  • 次の項目: EXEサーバ利用状態の管理