Search code examples
vb.net64-bitdllimportshellexecuteexshell32.dll

ShellExecuteEx to open file properties on x64 not work


I use the following VB.net (Framework 4) code to open file properties.
This works fine when target is set to x86.

<StructLayout(LayoutKind.Sequential)> _
Public Structure SHELLEXECUTEINFO
    Public cbSize As Integer
    Public fMask As UInteger
    Public hwnd As IntPtr
    Public lpVerb As [String]
    Public lpFile As [String]
    Public lpParameters As [String]
    Public lpDirectory As [String]
    Public nShow As Integer
    Public hInstApp As Integer
    Public lpIDList As Integer
    Public lpClass As [String]
    Public hkeyClass As Integer
    Public dwHotKey As UInteger
    Public hIcon As Integer
    Public hProcess As Integer
End Structure

Private Const SW_SHOW As Integer = 5
Private Const SEE_MASK_INVOKEIDLIST As UInteger = 12 ' 0x0000000C

<DllImport("shell32.dll")> _
Private Shared Function ShellExecuteEx(ByRef lpExecInfo As SHELLEXECUTEINFO) As Boolean
End Function

Public Shared Sub ShowProperties(ByVal path As String)
    Dim fi As New IO.FileInfo(path)
    Dim info As New SHELLEXECUTEINFO()
    info.cbSize = Marshal.SizeOf(info)
    info.lpVerb = "properties"
    info.lpFile = fi.Name
    info.lpDirectory = fi.DirectoryName
    info.nShow = SW_SHOW
    info.fMask = SEE_MASK_INVOKEIDLIST
    ShellExecuteEx(info)       
End Sub

Now I need the x64 target for my project and the code above does not work anymore. :(
GetLastError returns 0 and there is no exception or error message.
I searched two days and tried something but I found no solutiuon. Are here any ideas?

Thanks for help!


Solution

  •   Public hInstApp As Integer
    

    You have several mistakes in the structure declaration, handles and pointers are IntPtr, not Integer like you declared them. Works in 32-bit code, not in 64-bit code since these fields now take 8 bytes. Use the declaration that's available on the pinvoke.net web site.

    It also shows you why Marshal.GetLastError() didn't give you a proper error code, you forgot to use the SetLastError property in the [DllImport] attribute. You should also use CharSet:=CharSet.Auto in both the structure and the function declaration to benefit from Unicode.