C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: キーボード・フック時のエラーについて


(過去ログ 169 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■97520 / inTopicNo.1)  キーボード・フック時のエラーについて
  
□投稿者/ KenPin (1回)-(2021/06/02(Wed) 11:28:03)

分類:[.NET 全般] 

開発環境
OS:Win10 Pro(20H2)
VisualStdio2012 VisualBasic、Framework4.5

PrintScreenを無効化する処理があり、以前は正常に動作していましたが、
VisualStdio2005、Framework2.0からVisualStdio2012、Framework4.5へコンバージョンしたところ、
キーボード入力時に以下のエラーメッセージが発生するようになりました。
*******
PlnvokeStacklmbalanceが検出されました。
CallNextHookExがスタックを不安定にしています。
Plnvokeシグネチャがアンマネージターゲットシグネチャに一致していないことが原因として
考えられます。呼び出し規約、およびPlnvokeシグネチャのパラメータがターゲットのアンマネージシグネチャに一致していることを確認してください。
*******

解決方法をご存知の方いらっしゃいましたら教えて頂けませんでしょうか?
宜しくお願い致します。

ソースの一部は以下となります
Public Declare Function SetWindowsHookEx Lib "user32" _
  Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
  ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, _
  ByVal dwThreadId As Integer) As Integer

Private Declare Function CallNextHookEx Lib "user32" _
  (ByVal hHook As Integer, _
  ByVal nCode As Integer, _
  ByVal wParam As Integer, _
  ByVal lParam As KBDLLHOOKSTRUCT) As Integer

Public Structure KBDLLHOOKSTRUCT
    Public vkCode As Integer
    Public scanCode As Integer
    Public flags As Integer
    Public time As Integer
    Public dwExtraInfo As Integer
End Structure


'メイン処理
Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Call HookKeyboard()
End Sub

Public Sub HookKeyboard()
    callback = New KeyboardHookDelegate(AddressOf KeyboardCallback)

    KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, callback, Marshal.GetHINSTANCE( _
      [Assembly].GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
End Sub

Public Function KeyboardCallback(ByVal Code As Integer, _
  ByVal wParam As Integer, _
  ByRef lParam As KBDLLHOOKSTRUCT) As Integer

    If (Code = HC_ACTION) Then
        If (IsHooked(lParam)) Then
            Return 1
        End If

    End If

    Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam) '←ここでエラー

End Function

Public Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean

    'プリントスクリーン無効
    If (Hookstruct.vkCode = Keys.PrintScreen) Then
        Return True
    End If

    Return False
End Function

引用返信 編集キー/
■97521 / inTopicNo.2)  Re[1]: キーボード・フック時のエラーについて
□投稿者/ Hongliang (1178回)-(2021/06/02(Wed) 11:34:22)
SetWindowsHookEx
・ByVal hmod As Integer
・返値

CallNextHookEx
・ByVal hHook As Integer
・ByVal wParam As Integer

KBDLLHOOKSTRUCT
・Public dwExtraInfo As Integer

これらはいずれもIntegerではなくIntPtrで扱う必要があります。

また、

CallNextHookEx
・ByVal lParam As KBDLLHOOKSTRUCT

これはByRefで渡す必要があります。
引用返信 編集キー/
■97525 / inTopicNo.3)  Re[1]: キーボード・フック時のエラーについて
□投稿者/ 魔界の仮面弁士 (3113回)-(2021/06/02(Wed) 12:51:53)
No97520 (KenPin さん) に返信
> VisualStdio2005、Framework2.0からVisualStdio2012、Framework4.5へコンバージョンしたところ、
> キーボード入力時に以下のエラーメッセージが発生するようになりました。

移植元となっている .NET Framework 2.0 は 32bit 版専用でしたが、
移植先となる .NET Framework 4.5 では、32bit/64bit の両環境があります。

そのため、Hongliang さんが指摘されたような誤りが、
新環境ではより顕在化しやすくなっています。


> OS:Win10 Pro(20H2)
> VisualStdio2012 VisualBasic、Framework4.5

.NET Framework 4.5/4.5.1 は、2016/01/12 時点でサポート期限が終了しています。
(4.5 を標準搭載していた OS は、Win7 および Server 2012 の 2 種のみ)

Win10 19H1/19H2/20H1/20H2 には .NET Framework 4.8 が標準搭載されていますし、
ターゲットフレームワークを 4.5 にしておく必要性は薄いのではないでしょうか。

それに Windows 10 は、初版でさえ .NET Framework 4.6 が搭載されているため、
4.5 をダウングレード インストールすることはできません。

4.5 を搭載可能な OS … Vista/7/8, Server2008/2008R2/2012
4.5.2を搭載可能な OS … Vista/7/8/8.1, Server2008/2008R2/2012
4.7.2を搭載可能な OS … 7/8.1/10(1607以上1903未満), Server2008/2008R2/2012/2012R2/2016/2019
4.8 を搭載可能な OS … 7/8.1/10(1607以上のすべて※LTSB,LTSCを除く), Server 2008R2/2012/2012R2/2016/2019

一部の新機能をオプトアウトするために、インストールされているランタイムバージョンよりも
意図的にターゲットフレームワークを下げておき、下位バージョンの互換動作で運用させるケースも稀にありますが…。
https://docs.microsoft.com/ja-jp/dotnet/framework/migration-guide/application-compatibility
引用返信 編集キー/
■97562 / inTopicNo.4)  Re[2]: キーボード・フック時のエラーについて
□投稿者/ KenPin (2回)-(2021/06/07(Mon) 11:25:32)
No97521 (Hongliang さん) に返信
> これらはいずれもIntegerではなくIntPtrで扱う必要があります。

教えて頂いたように修正したところ正常に起動するようになりました。
ありがとうございました。
引用返信 編集キー/
■97563 / inTopicNo.5)  Re[2]: キーボード・フック時のエラーについて
□投稿者/ KenPin (3回)-(2021/06/07(Mon) 11:30:19)
No97525 (魔界の仮面弁士 さん) に返信
> 移植元となっている .NET Framework 2.0 は 32bit 版専用でしたが、
> 移植先となる .NET Framework 4.5 では、32bit/64bit の両環境があります。
>
> そのため、Hongliang さんが指摘されたような誤りが、
> 新環境ではより顕在化しやすくなっています。

ご指摘頂いた環境の違いを考えず安易に変更してしましました。
大変勉強になりました。

> .NET Framework 4.5/4.5.1 は、2016/01/12 時点でサポート期限が終了しています。
> (4.5 を標準搭載していた OS は、Win7 および Server 2012 の 2 種のみ)
>
> Win10 19H1/19H2/20H1/20H2 には .NET Framework 4.8 が標準搭載されていますし、
> ターゲットフレームワークを 4.5 にしておく必要性は薄いのではないでしょうか。

.NET Framework 4.5にしておく必要性は確かにありませんでした。
既にある別システムが4.5なので一緒にしただけでした。
サポート期限切れについてもご指摘頂きありがとうございます。
.NET Framework 4.8にするよう検討したいと思います。

この度はありがとうございました。

解決済み
引用返信 編集キー/
■97565 / inTopicNo.6)  Re[3]: キーボード・フック時のエラーについて
□投稿者/ 魔界の仮面弁士 (3121回)-(2021/06/07(Mon) 14:29:37)
No97563 (KenPin さん) に返信
>>移植元となっている .NET Framework 2.0 は 32bit 版専用でしたが、
>>移植先となる .NET Framework 4.5 では、32bit/64bit の両環境があります。
> ご指摘頂いた環境の違いを考えず安易に変更してしましました。
> 大変勉強になりました。

済みません。
32bit 向けだったのは .NET Framework 1.x でしたね。訂正させてください。

.NET Framework 2.0 から 64bit に対応するようになっていて、
 32ビット環境 (x86, WOW64)
 64ビット環境 ( IA-64 および x64 )
を選択できたはずです。

おそらくは既定の AnyCPU 設定でコンパイルされていたものと推察しますが、
当時は 32bit OS が多かったので、『As Integer』のままで動いていたのではないでしょうか。
(あるいは、意図的に x86 向けに設定してビルドしていたとか)


ターゲット CPU の設定については、
DLL プロジェクトの場合、既定で AnyCPU 設定となっていますが、
EXE プロジェクトの方は、VSバージョンによって既定値が変化しています。

VS2005/2008 の EXE プロジェクトは、既定で AnyCPU 設定。

VS2010 では、EXE プロジェクトの既定が x86 設定に変更されました。

VS2012 以降は、もう少し細かくなり、
 .NET 4.5 以降なら、EXE プロジェクトの既定は AnyCPU32bitPreferred 設定。
 .NET 4.0 以下なら、EXE プロジェクトの既定は AnyCPU 設定。
という感じです。


なお、新規にプロジェクトを作成するのでは無く、既存プロジェクトから
コンバートした場合や、プロジェクト作成後にターゲット フレームワークを
変更した場合には、ターゲット CPU の設定は上記の既定値ではなく、
変更前の既定値を引き継ぐことになります。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -