WindowsのMessengerサービスを使って別のパソコンにメッセージを送る方法。

Windows2000/XPの機能であるMessengerサービスを使えばLANを経由して別のパソコンにメッセージを送りポップアップダイアログを表示することができる。

同じ事はコマンドライン

net send アドレス メッセージ

を実行することで実現できる。
これと同じことをAPI関数で行うには、NetMessageBufferSendを使う。この関数はWindows2000/XPで使える(Vistaで有効かどうかは知らない)。ただし、あらかじめ送信側でWindowsのMessengerサービスを起動しておく必要がある。

メッセージの送信コードは以下。

/*!
@brief  WindowsのMessengerサービスを利用してメッセージを送信する
@param[in]  szAddress  送信先のIPアドレスまたはドメイン名
@param[in]  szMessage  送信メッセージ
*/
void Send(const char* szAddress, const char* szMessage)
{
    WCHAR *address = NULL;
    WCHAR* msg = NULL;

    try {
        int len;

        //ワイド文字列に変換
        len = strlen(szAddress) + 1;
        address = new WCHAR[len];       
        MultiByteToWideChar(GetACP(),MB_PRECOMPOSED,szAddress,-1,address,sizeof(WCHAR) * len);

        len = strlen(szMessage) + 1;
        msg = new WCHAR[len];
        MultiByteToWideChar(GetACP(),MB_PRECOMPOSED,szMessage,-1,msg,sizeof(WCHAR) * len);

        //送信
        NET_API_STATUS Ret = NetMessageBufferSend(NULL,address,NULL,(BYTE *)msg,sizeof(WCHAR) * lstrlenW(msg));
        /*
        Ret の値
        NERR_Success             送信成功
        ERROR_ACCESS_DENIED      ユーザーには、要求した情報へのアクセス権がありません。
        ERROR_INVALID_PARAMETER  指定されたパラメータは無効です。
        ERROR_NOT_SUPPORTED      このネットワークリクエストはサポートされていません。
        NERR_NameNotFound        ユーザー名が見つかりませんでした。
        NERR_NetworkError        ネットワークハードウェアの一般的な障害が発生しました。
        */

    } __finally {       //C++Builderの拡張文法。
        delete[] address;
        delete[] msg;
    }
}


ちなみにMessengerサービスの状態を確認するコードは

/*!
@brief  WindowsのMessengerサービスが使えるかどうかを調べる
@retval true   有効
@retval false  無効 
*/
bool readMessangerServiceStatus(void)
{
    SC_HANDLE scmHandle = ::OpenSCManager( NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE );
    if (scmHandle == NULL) {
        ::GetLastError();
        return FALSE;
    }

    SC_HANDLE hService = ::OpenService(scmHandle, "Messenger", GENERIC_READ);
    if (hService == NULL) {
        ::GetLastError();
        ::CloseServiceHandle( scmHandle );
        return FALSE;
    }

    SERVICE_STATUS status;
    QueryServiceStatus(hService, &status);

    ::CloseServiceHandle( hService );
    ::CloseServiceHandle( scmHandle );

    /*
    SERVICE_STOPPED:           // 停止
    SERVICE_START_PENDING:     // 起動中
    SERVICE_STOP_PENDING:      // 停止中
    SERVICE_RUNNING:           // 実行中
    SERVICE_CONTINUE_PENDING:  // 継続中
    SERVICE_PAUSE_PENDING:     // 一時停止中
    SERVICE_PAUSED:            // 一時停止
    */

    if (SERVICE_RUNNING == status.dwCurrentState) {
        return TRUE;
    }

    return FALSE;
}