Toshichan4
@Toshichan4

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

WM_COPYDATA を使用したプロセス間通信が VSCode でうまくいかない

解決したいこと

C#で、WM_COPYDATA を使用したプロセス間通信を行おうとしています。
ネット上に出ている記事を参考にVisual studio 2022 community で
作成したものは無事通信ができました。
しかしながら、事情があって Visual studio code に 上の
通信成功したソースを持ってきてこれを実行してみましたが
通信ができません。

調べてみると、受信側に WM_COPYDATA のメッセージが届いて
いないように見受けられます(受信側フォームの オーバライドした WndProc で
case WM_COPYDATA 内に設定したブレークポイントが引っかからない)。
何か考えられる原因はあるでしょうか。ご教示いただければ幸いです。

Visual studio 2022 comunity で作成した 送信側フォームと
Visual studio code で作成した 受信側フォームとを組み合わせて
みましたが、やはり通信できません。
その逆(送信側 vscode, 受信側 community)も同様でした。

ちなみに、csproj を見てみると、TargetFramework は
Visual studio 2022 comunity 側は
  v4.7.2
Visual studio code 側は
  net8.0-windows
となっています。

自分で試したこと

送信側のフォーム上で、受信側のフォームID は正しく取得できている。
送信側でMarshal.StringToHGlobalAnsiでCOPYDATASTRUCT32 の lpData には
それらしい数値が設定される。

(ソースコードは、ほぼ https://note.com/marupeke296/n/n5e126185f628
ものを使用しましたので、ここへの記載は控えておきます。)

0

6Answer

WM_COPYDATAをpost/sendMessageするときの、相手のウィンドウハンドルは正しいのでしょうか?
Spy++で確認できます。。。

0Like

早速ご回答いただきありがとうございます。

相手のウィンドウハンドルは正しいのでしょうか?

はい。
送受両方のプログラムにおいて、下のようなコードでウインドウハンドルの確認を行い、
送り側で認識している受け側のウインドウハンドルと、
受け側で認識している自分のウインドウハンドルが
一致していることは確認できています。

    // 指定のウィンドウを検索
    var sourceWindowHandle = new IntPtr( 0 );
    var destWindowHandle = new IntPtr( 0 );
    foreach ( var process in Process.GetProcesses() ) {
        if ( process.MainWindowTitle == 送信側ウインドウタイトル ) {
            sourceWindowHandle = process.MainWindowHandle;
            //break;
        }
        if ( process.MainWindowTitle == 受信側ウインドウタイトル ) {
            destWindowHandle = process.MainWindowHandle;
            rcvFormIdTextBox.Text = destWindowHandle.ToString();
            //break;
        }
        if (sourceWindowHandle != 0 && destWindowHandle != 0) {

            // デバッグ用 メッセージ    
            string debugMessage = "送信側フォーム Id = " + sourceWindowHandle +
                                    "\n受信側フォーム Id = " + destWindowHandle;
            MessageBox.Show(debugMessage,
            "到達  DebugMsg",
            MessageBoxButtons.OK);

            break;
        }
    }

送信側のフォーム上で、受信側のフォームID は正しく取得できている。
⇒ 正しくは フォームIDではなく、ウインドウハンドルでした。
  失礼しました。

0Like

Comments

  1. ウインドウハンドルは正しいとすると、COPYDATASTRUCT構造体が怪しいです。
    先頭メンバdwDataのサイズを確認してください。64bitアプリですか?

  2. struct COPYDATASTRUCT{
    public IntPtr dwData;
    public UInt32 cbData;
    public IntPtr lpData;
    }
    でいいのでは。FieldOffsetはいらない。
    (64bitのばあい、アラインメントがあるので、lpDataは 16byte開始になる。)
    vscodeとvsの違いはたぶんビルドで「32bitを選ぶ」がついているかいないかで片方64bit、片方32bitになるからとはおもうけど。

COPYDATASTRUCT構造体が怪しいです。
先頭メンバdwDataのサイズを確認してください。64bitアプリですか?

64bit アプリです。私が参考にしたWeb上の記事にも
64bit アプリでは dwData のサイズが 8バイトとの記事があったので

struct COPYDATASTRUCT32 {
    //[FieldOffset( 0 )] public UInt32 dwData;
    //[FieldOffset( 4 )] public UInt32 cbData;
    //[FieldOffset( 8 )] public IntPtr lpData;
    [FieldOffset( 0 )] public UInt64 dwData;
    [FieldOffset( 8 )] public UInt32 cbData;
    [FieldOffset( 12 )] public IntPtr lpData;
    //[FieldOffset( 0 )] public UInt64 dwData;
    //[FieldOffset( 8 )] public UInt64 cbData;
    //[FieldOffset( 16 )] public IntPtr lpData;
}

と、3通り試してみましたが、いずれも同じ症状でした。
また、同じPC上で、

struct COPYDATASTRUCT32 {
    [FieldOffset( 0 )] public UInt32 dwData;
    [FieldOffset( 4 )] public UInt32 cbData;
    /FieldOffset( 8 )] public IntPtr lpData;
}

として Visual studio 2022 community でビルドしたものは動作し、
VSCodeでビルドしたものは動作しませんでした。

0Like

Comments

  1. Visual studio 2022 community で作成したものは無事通信ができました。
    Visual studio code に 上の通信成功したソースを持ってきてこれを実行してみましたが通信ができません。

    問題を整理するために、次の組み合わせで動作させることは可能でしょうか?

    (a)Visual studio 2022 community で作成した送信側プログラム
    (b)Visual studio 2022 community で作成した受信側プログラム
    (c)Visual studio code で作成した送信側プログラム
    (d)Visual studio code で作成した受信側プログラム

    (a)→(b) OKを確認したプログラムを用いいて、
    (c)→(b) を試す
    (a)→(d) を試す


    すみません、このサイトに不慣れで、回答場所を間違えたようです。

    回答は削除や編集ができます。

すみません、このサイトに不慣れで、回答場所を間違えたようです。

COPYDATASTRUCT構造体が怪しいです。
先頭メンバdwDataのサイズを確認してください。64bitアプリですか?

64bit アプリです。私が参考にしたWeb上の記事にも
64bit アプリでは dwData のサイズが 8バイトとの記事があったので

struct COPYDATASTRUCT32 {
//[FieldOffset( 0 )] public UInt32 dwData;
//[FieldOffset( 4 )] public UInt32 cbData;
//[FieldOffset( 8 )] public IntPtr lpData;
[FieldOffset( 0 )] public UInt64 dwData;
[FieldOffset( 8 )] public UInt32 cbData;
[FieldOffset( 12 )] public IntPtr lpData;
//[FieldOffset( 0 )] public UInt64 dwData;
//[FieldOffset( 8 )] public UInt64 cbData;
//[FieldOffset( 16 )] public IntPtr lpData;
}
と、3通り試してみましたが、いずれも同じ症状でした。
また、同じPC上で、

struct COPYDATASTRUCT32 {
[FieldOffset( 0 )] public UInt32 dwData;
[FieldOffset( 4 )] public UInt32 cbData;
[FieldOffset( 8 )] public IntPtr lpData;
}
として Visual studio 2022 community でビルドしたものは動作し、
VSCodeでビルドしたものは動作しませんでし

0Like

【1】

問題を整理するために、次の組み合わせで動作させることは可能でしょうか?

(a)Visual studio 2022 community で作成した送信側プログラム
(b)Visual studio 2022 community で作成した受信側プログラム
(c)Visual studio code で作成した送信側プログラム
(d)Visual studio code で作成した受信側プログラム

(a)→(b) OKを確認したプログラムを用いいて、
(c)→(b) を試す
(a)→(d) を試す

⇒ これは、最初の質問時に述べましたように確認済みで
(a)→(b) は OK、 (c)→(b)、(a)→(d) ともに NG でした

Visual studio 2022 community で作成した 送信側フォームと
Visual studio code で作成した 受信側フォームとを組み合わせて
みましたが、やはり通信できません。
その逆(送信側 vscode, 受信側 community)も同様でした。

【2】

struct COPYDATASTRUCT{
public IntPtr dwData;
public UInt32 cbData;
public IntPtr lpData;
}
でいいのでは。FieldOffsetはいらない。

⇒ 事情があって今すぐには試行できませんが、可能になったら
  試してみて報告します。ありがとうございます。

ところで、COPYDATASTRUCT について ネット上に詳しい資料はありますか。
64bit, 32bit でdwDATA のサイズが違うという情報があったので
詳しく見てみたいと思い、ネット上を探してみたのですが
見つかりませんでした。

【3】

vscodeとvsの違いはたぶんビルドで「32bitを選ぶ」がついているかいないかで片方>> 64bit、片方32bitになるからとはおもうけど。

⇒ .sln に自動生成される
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
のことでしょうか。
ここで、Any CPU の代わりに、x86 や x64 と明示すればよいですか?
(これも、今すぐには試行できないので後ほど試してみて報告します。)
(ただ、Visual studio community でも Any CPU となっていたと思います。)

0Like

Comments

  1. ⇒ これは、最初の質問時に述べましたように確認済みで
    (a)→(b) は OK、 (c)→(b)、(a)→(d) ともに NG でした

    失礼しました。読み取れていませんでした。
    やはりCOPYDATASTRUCT構造体が怪しいです。
    @jzkey さんが指摘された、バウンダリの問題のように思います。


    ところで、COPYDATASTRUCT について ネット上に詳しい資料はありますか。

    海外サイトも探してみましたが、https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-copydatastruct以外で、それ自身を説明した情報は見つかりませんでした。

struct COPYDATASTRUCT{
public IntPtr dwData;
public UInt32 cbData;
public IntPtr lpData;
}
でいいのでは。FieldOffsetはいらない。

通信に成功しました。ありがとうございます。

先に下のような定義で失敗していました。
アライメントが分かっていなかったのですね。
反省です。

[StructLayout(LayoutKind.Explicit)]
struct COPYDATASTRUCT32 {
    [FieldOffset( 0 )] public IntPtr dwData;
    [FieldOffset( 8 )] public UInt32 cbData;
    [FieldOffset( 12 )] public IntPtr lpData;
 }

Explicit するなら

[StructLayout(LayoutKind.Explicit)]
struct COPYDATASTRUCT32 {
    [FieldOffset( 0 )] public IntPtr dwData;
    [FieldOffset( 8 )] public UInt32 cbData;
    [FieldOffset( 16 )] public IntPtr lpData;
 }

でなければいけませんでした。

みなさんお世話になりました。

0Like

Your answer might help someone💌