2011-08-05 22 views
0

他のプロセスに新しいメニューを挿入したいと思います。しかし、私はエラーを取得する:ボタンのWindows APIのInsertMenuItemヘルプが必要です

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

コード:InsertMenuItemため

Mmenuhandle = GetMenu(mainhandle) 
    Mmenucount = GetMenuItemCount(Mmenuhandle) 
    Smenuhandle = GetSubMenu(Mmenuhandle, 0) 
    Smenucount = GetMenuItemCount(Smenuhandle) 
    With mii 
     .cbSize = Len(mii) 
     .fMask = MIIM_STATE Or MIIM_ID Or MIIM_STRING Or MIIM_FTYPE 
     .fType = MFT_STRING 
     .fState = MFS_ENABLED 
     .wID = MENUID 
     .dwTypeData = "My Menu" 
     .cch = Len(.dwTypeData) 
    End With 
    InsertMenuItem(Smenuhandle, Smenucount + 1, True, mii) ' ERROR here 
    DrawMenuBar(mainhandle) 

が宣言:MENUITEMINFOため

Private Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" _ 
    (ByVal hMenu As Integer, ByVal uItem As Integer, ByVal fByPosition As Boolean, ByVal lpmii As MENUITEMINFO) As Integer 

が宣言:

Public Structure MENUITEMINFO 
    Public cbSize As Integer 
    Public fMask As Integer 
    Public fType As Integer 
    Public fState As Integer 
    Public wID As Integer 
    Public hSubMenu As Integer 
    Public hbmpChecked As Integer 
    Public hbmpUnchecked As Integer 
    Public dwItemData As Integer 
    Public dwTypeData As String 
    Public cch As Integer 
    Public a As Integer 
End Structure 

私はどのように修正すればよいですティsのエラー?

+0

他のプロセスのコンテキストに実行するためにフックを使用していますか? –

+0

↑初心者です – sozai

答えて

3

P/Invokeコードが正しくない ... VB 6ソースからコピーされているように見えます。同等の名前のデータ型は、VB.NETではVB 6とは意味が大きく異なります。

さらに、ハンドル/ポインタは固定整数型を使用して宣言されていますが、64ビット環境では正しく機能しません。これらのタイプの値は、この目的のために特別に設計されたIntPtrタイプを使用して常に宣言する必要があります。

また、構造体へのポインタはVB.NETでByRefに渡す必要があります。それらを渡すことはできませんByVal

System.Runtime.InteropServices namespaceにあるツールと.NETマーシャラーを使用して手助けをする必要があります。

これは、オンラインで見つかったコードを、それが意味するものとその意味を理解せずにコピー&ペーストするだけでは決してありません。

宣言は次のようになります。

Imports System.Runtime.InteropServices 

Public NotInheritable Class NativeMethods 

    Public Const MIIM_STATE As Integer = &H1 
    Public Const MIIM_ID As Integer = &H2 
    Public Const MIIM_STRING As Integer = &H40 
    Public Const MIIM_BITMAP As Integer = &H80 
    Public Const MIIM_FTYPE As Integer = &H100 

    Public Const MFT_STRING As Integer = &H0 

    Public Const MFS_ENABLED As Integer = &H0 

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ 
    Public Structure MENUITEMINFO 
     Public cbSize As Integer 
     Public fMask As Integer 
     Public fType As Integer 
     Public fState As Integer 
     Public wID As Integer 
     Public hSubMenu As IntPtr 
     Public hbmpChecked As IntPtr 
     Public hbmpUnchecked As IntPtr 
     Public dwItemData As IntPtr 
     <MarshalAs(UnmanagedType.LPTStr)> Public dwTypeData As String 
     Public cch As Integer 
     Public hbmpItem As IntPtr 
    End Structure 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _ 
    Public Shared Function GetMenu(ByVal hWnd As IntPtr) As IntPtr 
    End Function 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ 
    Public Shared Function GetMenuItemCount(ByVal hMenu As IntPtr) As Integer 
    End Function 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _ 
    Public Shared Function GetSubMenu(ByVal hMenu As IntPtr, ByVal nPos As Integer) As IntPtr 
    End Function 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ 
    Public Shared Function InsertMenuItem(ByVal hMenu As IntPtr, 
             ByVal uItem As Integer, 
             <MarshalAs(UnmanagedType.Bool)> fByPosition As Boolean, 
             ByRef lpmii As MENUITEMINFO) _ 
            As <MarshalAs(UnmanagedType.Bool)> Boolean 
    End Function 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ 
    Public Shared Function DrawMenuBar(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean 
    End Function 

End Class 

次に、あなたは(一致するように再書き込みしてコード)このような関数を使用することができます。

' Get a handle to the menu assigned to a window (in this case, your form) 
    Dim hMenu As IntPtr = NativeMethods.GetMenu(Me.Handle) 

    ' Get a count of the total items in that menu 
    Dim menuItemCount As Integer = NativeMethods.GetMenuItemCount(hMenu) 

    ' Get a handle to the sub-menu at index 0 
    Dim hSubMenu As IntPtr = NativeMethods.GetSubMenu(hMenu, 0) 

    ' Get a count of the total items in that sub-menu 
    Dim subMenuItemCount As Integer = NativeMethods.GetMenuItemCount(hSubMenu) 

    ' Create and fill in a MENUITEMINFO structure, describing the menu item to add 
    Dim mii As New NativeMethods.MENUITEMINFO 
    With mii 
    .cbSize = Marshal.SizeOf(mii) ' prefer Marshal.SizeOf over the VB 6 Len() function 
    .fMask = NativeMethods.MIIM_FTYPE Or NativeMethods.MIIM_STATE Or NativeMethods.MIIM_ID Or NativeMethods.MIIM_STRING 
    .fType = NativeMethods.MFT_STRING 
    .fState = NativeMethods.MFS_ENABLED 
    .wID = 0      ' your custom menu item ID here 
    .hSubMenu = IntPtr.Zero 
    .hbmpChecked = IntPtr.Zero 
    .hbmpUnchecked = IntPtr.Zero 
    .dwItemData = IntPtr.Zero 
    .dwTypeData = "My Menu Item" ' the name of your custom menu item 
    End With 

    ' Insert the menu item described by the above structure 
    ' (notice that we're passing the structure by reference in the P/Invoke definition!) 
    NativeMethods.InsertMenuItem(hSubMenu, subMenuItemCount + 1, True, mii) 

    ' Force an update of the window's menu bar (again, in this case, your form) 
    NativeMethods.DrawMenuBar(Me.Handle) 

期待通りにすべてが、少なくとも、作品同じプロセス内でP/Invokeは非常に難しい話題であり、VB.NETだけでなくWin32 APIも正しく理解する必要があります。オンラインで見つかったコードをコピーして貼り付けることは、本質的に危険な命題です。ほとんどの場合、動作しません。残りの時間は、セキュリティリスクの可能性があります。残念ながら、スタックオーバーフローに関する答え以外にも、それがどのように機能するかを説明する必要があります。

編集:実際には、上記のコードはプロセス間で問題なく機能します。特別な努力は必要ありません。私はメモ帳の実行中のインスタンスでメニューを使ってモンキーを試してみましたが、すべてうまくいきました。 非常に理由なしでこれを行うことをお勧めしません...

関連する問題