This works for me (test in C:\Temp folder) =>
Dim sPath As String = "C:\Temp"
Dim pItemIDL As IntPtr = ILCreateFromPath(sPath)
Dim pContextMenu As IContextMenu = Nothing
Dim CLSID_NewMenu As New Guid("D969A300-E7FF-11d0-A93B-00A0C90F2719")
Dim NewMenuType As Type = Type.GetTypeFromCLSID(CLSID_NewMenu, True)
Dim NewMenu As Object = Activator.CreateInstance(NewMenuType)
pContextMenu = DirectCast(NewMenu, IContextMenu)
If pContextMenu IsNot Nothing Then
pContextMenu2 = CType(pContextMenu, IContextMenu2)
Dim hMenu As IntPtr = CreatePopupMenu()
Dim hr As HRESULT = pContextMenu.QueryContextMenu(hMenu, 0, 1, 256, 0)
If (hr = HRESULT.S_OK) Then
Dim psei As IShellExtInit = Nothing
psei = DirectCast(pContextMenu, IShellExtInit)
hr = psei.Initialize(pItemIDL, Nothing, IntPtr.Zero)
If (hr = HRESULT.S_OK) Then
Dim nX As Integer = Cursor.Position.X, nY = Cursor.Position.Y
Dim hPopupMenu As IntPtr = GetSubMenu(hMenu, 0)
Dim nCmd As UInteger = TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN Or TPM_LEFTBUTTON Or TPM_RIGHTBUTTON Or TPM_RETURNCMD, nX, nY, 0, Me.Handle, IntPtr.Zero)
If (nCmd <> 0) Then
Dim cmi As CMINVOKECOMMANDINFO = New CMINVOKECOMMANDINFO()
cmi.cbSize = Marshal.SizeOf(GetType(CMINVOKECOMMANDINFO))
cmi.fMask = 0
cmi.hwnd = Me.Handle
cmi.lpVerb = CType((nCmd - 1), IntPtr)
cmi.lpParameters = IntPtr.Zero
cmi.lpDirectory = IntPtr.Zero
cmi.nShow = SW_SHOWNORMAL
cmi.dwHotKey = 0
cmi.hIcon = IntPtr.Zero
hr = pContextMenu.InvokeCommand(cmi)
End If
pContextMenu2 = Nothing
End If
End If
Marshal.ReleaseComObject(pContextMenu)
DestroyMenu(hMenu)
End If
If (pItemIDL <> IntPtr.Zero) Then ILFree(pItemIDL)
HandleMenuMsg to build the context menu :
Public pContextMenu2 As IContextMenu2 = Nothing
Public Const WM_INITMENUPOPUP As Integer = &H117
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_INITMENUPOPUP Then
If pContextMenu2 IsNot Nothing Then pContextMenu2.HandleMenuMsg(CUInt(m.Msg), CInt(m.WParam), m.LParam)
Return
Else
MyBase.WndProc(m)
End If
End Sub
Declarations :
Public Enum HRESULT As Integer
S_OK = 0
S_FALSE = 1
E_NOINTERFACE = &H80004002
E_NOTIMPL = &H80004001
E_FAIL = &H80004005
E_UNEXPECTED = &H8000FFFF
E_OUTOFMEMORY = &H8007000E
End Enum
<DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function ILCreateFromPath(<MarshalAs(UnmanagedType.LPWStr)> pszPath As String) As IntPtr
End Function
<DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Sub ILFree(pidl As IntPtr)
End Sub
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function CreatePopupMenu() As IntPtr
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function TrackPopupMenu(hMenu As IntPtr, uFlags As UInteger, x As Integer, y As Integer, nReserved As Integer, hWnd As IntPtr, prcRect As IntPtr) As UInteger
End Function
Public Const TPM_LEFTBUTTON As Integer = &H0
Public Const TPM_RIGHTBUTTON As Integer = &H2
Public Const TPM_LEFTALIGN As Integer = &H0
Public Const TPM_CENTERALIGN As Integer = &H4
Public Const TPM_RIGHTALIGN As Integer = &H8
Public Const TPM_TOPALIGN As Integer = &H0
Public Const TPM_VCENTERALIGN As Integer = &H10
Public Const TPM_BOTTOMALIGN As Integer = &H20
Public Const TPM_HORIZONTAL As Integer = &H0
Public Const TPM_VERTICAL As Integer = &H40
Public Const TPM_NONOTIFY As Integer = &H80
Public Const TPM_RETURNCMD As Integer = &H100
Public Const TPM_RECURSE As Integer = &H1
Public Const TPM_HORPOSANIMATION As Integer = &H400
Public Const TPM_HORNEGANIMATION As Integer = &H800
Public Const TPM_VERPOSANIMATION As Integer = &H1000
Public Const TPM_VERNEGANIMATION As Integer = &H2000
Public Const TPM_NOANIMATION As Integer = &H4000
Public Const TPM_LAYOUTRTL As Integer = &H8000
Public Const TPM_WORKAREA As Integer = &H10000
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function GetSubMenu(hMenu As IntPtr, nPos As Integer) As IntPtr
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function GetMenuItemCount(hMenu As IntPtr) As Integer
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function DestroyMenu(hMenu As IntPtr) As Boolean
End Function
<ComImport>
<Guid("000214e4-0000-0000-c000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IContextMenu
Function QueryContextMenu(hmenu As IntPtr, indexMenu As UInteger, idCmdFirst As UInteger, idCmdLast As UInteger, uFlags As UInteger) As HRESULT
<PreserveSig()>
Function InvokeCommand(ByRef pici As CMINVOKECOMMANDINFO) As HRESULT
<PreserveSig()>
Function GetCommandString(idCmd As UInteger, uType As UInteger, pReserved As IntPtr, pszName As StringBuilder, cchMax As UInteger) As HRESULT
End Interface
<ComImport>
<Guid("000214f4-0000-0000-c000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IContextMenu2
Inherits IContextMenu
Overloads Function QueryContextMenu(hmenu As IntPtr, indexMenu As UInteger, idCmdFirst As UInteger, idCmdLast As UInteger, uFlags As UInteger) As HRESULT
<PreserveSig()>
Overloads Function InvokeCommand(ByRef pici As CMINVOKECOMMANDINFO) As HRESULT
<PreserveSig()>
Overloads Function GetCommandString(idCmd As UInteger, uType As UInteger, pReserved As IntPtr, pszName As StringBuilder, cchMax As UInteger) As HRESULT
<PreserveSig()>
Function HandleMenuMsg(uMsg As UInteger, wParam As Integer, lParam As IntPtr) As HRESULT
End Interface
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure CMINVOKECOMMANDINFO
Public cbSize As Integer
Public fMask As Integer
Public hwnd As IntPtr
Public lpVerb As IntPtr
Public lpParameters As IntPtr
Public lpDirectory As IntPtr
Public nShow As Integer
Public dwHotKey As Integer
Public hIcon As IntPtr
End Structure
Public Const CMF_NORMAL As Integer = &H0
Public Const CMF_DEFAULTONLY As Integer = &H1
Public Const CMF_VERBSONLY As Integer = &H2
Public Const CMF_EXPLORE As Integer = &H4
Public Const CMF_NOVERBS As Integer = &H8
Public Const CMF_CANRENAME As Integer = &H10
Public Const CMF_NODEFAULT As Integer = &H20
Public Const CMF_INCLUDESTATIC As Integer = &H40
Public Const CMF_ITEMMENU As Integer = &H80
Public Const CMF_EXTENDEDVERBS As Integer = &H100
Public Const CMF_DISABLEDVERBS As Integer = &H200
Public Const CMF_ASYNCVERBSTATE As Integer = &H400
Public Const CMF_OPTIMIZEFORINVOKE As Integer = &H800
Public Const CMF_SYNCCASCADEMENU As Integer = &H1000
Public Const CMF_DONOTPICKDEFAULT As Integer = &H2000
Public Const CMF_RESERVED As Integer = &HFFFF0000
Public Const SW_SHOWNORMAL As Integer = 1
Public Const GCS_VERBA As Integer = &H0
Public Const GCS_HELPTEXTA As Integer = &H1
Public Const GCS_VALIDATEA As Integer = &H2
Public Const GCS_VERBW As Integer = &H4
Public Const GCS_HELPTEXTW As Integer = &H5
Public Const GCS_VALIDATEW As Integer = &H6
Public Const GCS_VERBICONW As Integer = &H14
Public Const GCS_UNICODE As Integer = &H4
<ComImport>
<Guid("000214E8-0000-0000-C000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IShellExtInit
Function Initialize(pidlFolder As IntPtr, pdtobj As IDataObject, hkeyProgID As IntPtr) As HRESULT
End Interface