2

PostMessage でウィンドウにキーを送信しようとしています。しかし、プログラムがキーを送信した後、デバッグ ウィンドウにエラーが表示されます。

発生するエラーは次のとおりです: PInvoke スタックの不均衡が検出されました。

私はDLLを間違って呼んでいると思います:

[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, Int64 lParam);
4

2 に答える 2

5

メソッドの署名がエラーになっています。これを試して:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

あなたは 32 ビット マシンを使用してInt64おり、問題のタイプが正しくありません。pinvoke.netを参照

于 2012-08-11T11:54:45.440 に答える
5

発生するエラーは次のとおりです: PInvoke スタックの不均衡が検出されました。

あなたが見るものの背後にあるほんの少しの背景、Riaの答えはあなたの問題を解決します. これは実際にはエラーではなく、MDA によって生成される警告です。Managed Debugging Assistant は、CLR、フレームワーク、およびデバッガーに追加される追加のコードであり、意図しない実行時の問題を監視し、デバッガーで実行するときにアクティブ化されます。使用可能な MDA を確認し、Debug + Exceptions を使用して、[Managed Debugging Assistants] ノードを展開してそれらを確認できます。それらの多くは、ノイズが多い傾向があるか、誤った警告を生成する傾向があるか、後で既に例外を生成する傾向があるため、デフォルトで無効になっています。pInvokeStackImbalance MDA は実際にはそこにリストされていないことに注意してください。オフにできないため、特別です。

MDA の完全なリストは、こちらに記載されています。pInvokeStackImbalance の説明には、検出された問題の原因に関する適切な説明が含まれています。

プラットフォーム呼び出し呼び出しのマネージド シグネチャは、呼び出されるメソッドのアンマネージド シグネチャと一致しない場合があります。この不一致は、マネージド シグネチャが正しい数のパラメーターを宣言していないか、パラメーターの適切なサイズを指定していないことが原因である可能性があります。DllImportAttribute 属性で指定されている可能性がある呼び出し規約がアンマネージ呼び出し規約と一致しないため、MDA がアクティブ化されることもあります。

あなたの場合の真の理由を強調しました.lParam引数の型が間違っています。wParam タイプも間違っていますが、たまたま正しいサイズになっています。この種のアクシデントは、コードが 64 ビット オペレーティング システムで実行されている場合に発生する傾向があります。

これは単なる警告であり、無視して実行を続けるとコードは正常に実行されているように見えますが、スタックの不均衡は非常に深刻な実行時の問題です。障害モードは予測できません。デバッグ ビルドでは問題なく動作する可能性がありますが、リリース ビルドでは不可解な例外でプログラムが爆撃される可能性があります。ここでの具体的な問題は、メソッドを呼び出すときにスタックにプッシュするデータが多すぎて、Windows がスタックから十分にポップしないことです。頻繁に呼び出すと、このサイトの名前でプログラムが爆撃される可能性があります。C# メソッドから戻るとスタックのバランスが再調整されるため、問題は隠されがちです。リリース モードでジッター オプティマイザーがメソッドをインライン化すると、すべてのベットがオフになります。これは、デバッガーが接続されていない場合にのみ行われ、診断しようとする最悪の種類のバグです。

適切な pinvoke 宣言を見つけるのは特に簡単ではありません。それらを宣言する方法は複数あり、関数をピンボークしやすくするために、宣言について意図的な「嘘」を見つけることがよくあります。pinvoke.net サイトは、宣言を過度に指定する傾向がありますが、かなり適切なソースです。Ria の例のように、 [return:] 属性は不要です。なぜなら、それはすでに bool のデフォルトのマーシャリングになっているからです。また、ウィンドウ ハンドルを所有していない場合、HandleRef はあまり意味がありません。しかし、それはうまく機能します。もう 1 つのかなり適切なソースは、Pinvoke Interop Assistant です。これは、ここで見つけることができるツールです。自動生成された宣言を生成しますが、それらはきれいではありません。

最後になりましたが、PostMessage を使用してキーストロークを別のプロセスのウィンドウに確実に突っ込むことはできません。プロセスのキーボードの状態、特に Shift、Alt、および Ctrl キーを正確にする必要がある場合、問題が発生します。また、Alt+Gr のようなデッド キーは、特に分音記号が多い言語や大きなアルファベットを含む言語の場合、レイアウトが異なるキーボードに存在します。入力キーを突くには、代わりに WM_CHAR を優先する必要があります。

于 2012-08-11T13:14:14.913 に答える