【VC++】メールスロットで単方向プロセス間通信を行う

0

    <機能>

    (1)メールスロットクライアントとサーバを作成します

    (2)メールスロットを使って2つのexe間でプロセス間通信を行います

    (3)クライアントは[送信]ボタン押下によりメッセージを送付します

    (4)サーバは受信メッセージをリストボックスに表示します

    (5)クライアント起動時にサーバも起動します

     (サーバからクライアントの起動ななし)

     

    <実行イメージ>

    上の実行ファイルはメールスロットクライアント(MFCApplication1)

    下の実行ファイルはメールスロットサーバ(MFCApplication2)

    MFC,VisualStudio,MailSlot,実行サンプル,
     

    <動作検証&開発環境>
    Visual Studio Community 2017

     

    <使い方>

    1.MFCApplication1プロジェクトを作成します

    2.MFCApplication1ソリューションにMFCApplication2プロジェクトを追加します

     (どちらもダイアログベースです)

     

    サンプルのソリューション構成

    MFCApplication1(ソリューションフォルダ)

     Debug

     MFCApplication1(プロジェクトフォルダ)

     MFCApplication2(プロジェクトフォルダ)

     Release

     MFCApplication1.sln

     

    3.コントロールを追加

    MFCApplication1

    MFC,VisualStudio,MailSlot,送信,
     

    MFCApplication2

    MFC,VisualStudio,MailSlot,受信,
     

    4.メンバ変数を追加

    MFCApplication1

     IDC_EDIT1:

    MFC,VisualStudio,MailSlot,送信,メンバ変数追加,クラスウィザード,
     

    MFCApplication2

     IDC_LIST1:

    MFC,VisualStudio,MailSlot,受信,メンバ変数追加,クラスウィザード,
     

    5.MFCApplication2にイベントを追加

     WM_TIMER(タイマーイベントでメッセージを受信)

     WM_DESTROY(画面終了イベントでメールスロットとタイマー停止)

    MFC,VisualStudio,MailSlot,受信,イベント追加,クラスウィザード,
     

    5.ソースを追加

     

    MFCApplication1(クライアント「送信」側アプリ)

     

    MFCApplication1Dlg.h

    class CMFCApplication1Dlg : public CDialog
    {
    //〜省略〜
    // 実装
    protected:
        HICON m_hIcon;
        // 生成された、メッセージ割り当て関数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    private:
        CString m_sendEdt;
        HANDLE m_mailSlot;
    public:
        afx_msg void OnBnClickedButton1();
    };

     

    MFCApplication1Dlg.cpp

     

    BOOL CMFCApplication1Dlg::OnInitDialog()

    {
        //〜省略〜〜
        //受信側(MFCApplication2.exe)も一緒に起動する
        //※本サンプルでは受信側と送信側が同一フォルダに出力されているものとしますが実行環境に合わせて修正してください

        TCHAR buf[2048];
        ZeroMemory(&buf, sizeof(buf));
        GetModuleFileName(NULL, buf, sizeof(buf));
        size_t ichi = wcslen(buf) - wcslen(L"MFCApplication1.exe");
        //送信側(MFCApplication1.exe)実行ファイル名を受信側(MFCApplication2.exe)に置換
        wmemcpy_s(&buf[ichi],wcslen(buf), L"MFCApplication2.exe", wcslen(L"MFCApplication2.exe")*2);
        //受信側(MFCApplication2.exe)を起動
        ShellExecute(NULL, L"open", buf, NULL, NULL, SW_HIDE);
        //エディットボックスを初期化
        m_sendEdt = L"";
        UpdateData(FALSE);
        return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }
     
    /*************************************************
    関数名 OnBnClickedButton1
    機能   送信ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedButton1()
    {
        CString csError;
        TCHAR cName[256];
        ZeroMemory(&cName,sizeof(cName));
        //エディットボックスの入力値を取得
        UpdateData(TRUE);
        m_sendEdt = m_sendEdt.Trim();
        //メッセージが未入力ならエラーとする
        if (m_sendEdt.IsEmpty())
        {
            AfxMessageBox(L"送信文字列を入力してください",MB_ICONERROR);
            return;
        }
        //コンピュータ名を取得
        //※本サンプルでは同一コンピュータに送信する

        DWORD wksize = sizeof(cName);
        if (!GetComputerName(cName, &wksize))
        {
            AfxMessageBox(L"コンピューター名の取得に失敗しました", MB_ICONERROR);
            return;
        }
        //メールスロットを作成
        //メールスロットの名前は ¥¥mailslot¥¥MailSlot とする

        //詳細はMSDN参照
        CString csSlot;
        csSlot.Format(L"¥¥¥¥%s¥¥mailslot¥¥MailSlot", cName);
        HANDLE hSlot = CreateFile(csSlot, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ,
                                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hSlot == INVALID_HANDLE_VALUE)
        {
            csError.Format(L"MailSlotの作成に失敗しました(ErrorCode=%d)¥r¥n%s",GetLastError(),csSlot);
            AfxMessageBox(csError, MB_ICONERROR);
            return;
        }
        //メッセージの送信
        LPTSTR cMsg = new TCHAR[2048];
        DWORD dwSize;
        DWORD dwWrite;
        BOOL bResult;
        //dwSize = wcslen(cMsg);
        dwSize = wsprintf(cMsg, L"%s", m_sendEdt);
        bResult = WriteFile(hSlot, cMsg, dwSize * 2, &dwWrite, NULL);
        if (!bResult) {
            csError.Format(L"MailSlotの送信に失敗しました(ErrorCode=%d)¥r¥n%s", GetLastError(), csSlot);
            AfxMessageBox(csError, MB_ICONERROR);
        }
        CloseHandle(hSlot);
        delete cMsg;
    }

     

    MFCApplication2(サーバ「受信」側アプリ)

     

    MFCApplication2Dlg.h
    class CMFCApplication2Dlg : public CDialog
    {
    //〜省略〜〜
    // 実装
    protected:
        HICON m_hIcon;
        // 生成された、メッセージ割り当て関数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    private:
        HANDLE m_Slot;
    public:
        afx_msg void OnTimer(UINT_PTR nIDEvent);
        afx_msg void OnDestroy();
    private:
        CListBox m_recvList;
    };
     
    MFCApplication2Dlg.cpp
    BOOL CMFCApplication2Dlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
       
        //〜省略〜〜
       
        //メールスロットを作成
        //メールスロットの名前は ¥¥mailslot¥¥MailSlot とする
        //メッセージの最大長(バイト数):0(任意サイズ)
        //メッセージ読み取りタイムアウト値(ms)
        //詳細はMSDN参照

        m_Slot = CreateMailslot(L"¥¥¥¥.¥¥mailslot¥¥MailSlot", 0, 1000, NULL);
        if (m_Slot == INVALID_HANDLE_VALUE)
        {
            CString csError;
            csError.Format(L"メールスロット作成に失敗しました(ErrorCode=%d)", GetLastError());
            AfxMessageBox(csError, MB_ICONERROR);
            return FALSE;
        }
        //タイマースタート
        //1000(ms)ごとにチェック
        //コールバック関数なし

        SetTimer(DTIMER_ID, 1000, NULL);
        return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }
    /*************************************************
    関数名 OnTimer
    機能   タイマーイベントで受信をチェック
    *************************************************/

    void CMFCApplication2Dlg::OnTimer(UINT_PTR nIDEvent)
    {
        TCHAR cMsg[2048];
        DWORD dwRead;
        BOOL bResult;
        CString csMsg;
       
        //タイマー停止
        KillTimer(DTIMER_ID);
        //メッセージがあれば処理する
        MSG msg;
        while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
       
        //メッセージの読み取り
        //詳細はMSDN参照

        ZeroMemory(&cMsg, sizeof(cMsg));
        bResult = ReadFile(m_Slot, cMsg, sizeof(cMsg), &dwRead, NULL);
        if(bResult)
        {
            //リストボックスに表示
            CTime ct;
            ct = CTime::GetCurrentTime();
            csMsg.Format(L"%04d/%02d/%02d %02d:%02d:%02d : %s", ct.GetYear(), ct.GetMonth(),
                ct.GetDay(), ct.GetHour(), ct.GetMinute(), ct.GetSecond(), cMsg);
            m_recvList.InsertString(-1, csMsg);
            UpdateData(FALSE);
        }else
        {
            LRESULT lrlt = GetLastError();
            if ((lrlt == ERROR_SEM_TIMEOUT) || (lrlt == ERROR_ACCESS_DENIED)) {
                //メッセージがタイムアウトのときエラーを出さない
                //別のエラーが出るようならエラーコードを追加する

            }
            else {
                csMsg.Format(L"MailSlotのメッセージ読み取りに失敗しました(ErrorCode=%d)", lrlt);
                AfxMessageBox(csMsg, MB_ICONERROR);
                SetTimer(DTIMER_ID, 1000, NULL);
            }
        }
        //タイマー起動
        SetTimer(DTIMER_ID, 1000, NULL);
        CDialog::OnTimer(nIDEvent);
    }
     
    /*************************************************
    関数名 OnDestroy
    機能   アプリケーションの終了処理
    *************************************************/

    void CMFCApplication2Dlg::OnDestroy()
    {
        CDialog::OnDestroy();
        //タイマー停止
        KillTimer(DTIMER_ID);
        //メールスロットを閉じる
        if (m_Slot != INVALID_HANDLE_VALUE)
        {
            CloseHandle(m_Slot);
        }
    }
     

    よろしければポチッと押してください

    プログラマー ブログランキングへ

     



    calendar

    S M T W T F S
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
    << September 2018 >>

    profile

    others

    mobile

    qrcode         スマホ表示に戻す