none
How to access and direct the "shell" in Windows? RRS feed

  • Question

  • I tried starting Windows Explorer windows - and then controlling them (eg, by stopping them or closing the windows) with the Process facility. That doesn't seem to work very well. But I believe there is another way -- the Windows "Shell". But I don't know how to get access to the Shell in my program. What "reference" do I have to include in my program that will give me access to it?

    Robert Homes

    Saturday, October 14, 2017 2:04 AM

Answers

  • You can embed Explorer inside a Form with IExplorerBrowser

    A basic sample  =>

    (I did not test all the functions of the interface, some could be wrong, I just copied them from C++)

    Imports System.Runtime.InteropServices
    Public Class Form1
        Public Enum HRESULT As Integer
            DRAGDROP_S_CANCEL = &H40101
            DRAGDROP_S_DROP = &H40100
            DRAGDROP_S_USEDEFAULTCURSORS = &H40102
            DATA_S_SAMEFORMATETC = &H40130
            S_OK = 0
            S_FALSE = 1
            E_NOINTERFACE = &H80004002
            E_NOTIMPL = &H80004001
            OLE_E_ADVISENOTSUPPORTED = &H80040003
            E_FAIL = &H80004005
            MK_E_NOOBJECT = &H800401E5
        End Enum
    
        Public Enum EXPLORER_BROWSER_OPTIONS As Integer
            EBO_NONE = 0
            EBO_NAVIGATEONCE = &H1
            EBO_SHOWFRAMES = &H2
            EBO_ALWAYSNAVIGATE = &H4
            EBO_NOTRAVELLOG = &H8
            EBO_NOWRAPPERWINDOW = &H10
            EBO_HTMLSHAREPOINTVIEW = &H20
            EBO_NOBORDER = &H40
            EBO_NOPERSISTVIEWSTATE = &H80
        End Enum
    
        Public Enum EXPLORER_BROWSER_FILL_FLAGS As Integer
            EBF_NONE = 0
            EBF_SELECTFROMDATAOBJECT = &H100
            EBF_NODROPTARGET = &H200
        End Enum
    
        Public Structure RECT
            Public Left As Integer
            Public Top As Integer
            Public Right As Integer
            Public Bottom As Integer
        End Structure
    
        Public Enum FOLDERVIEWMODE As Integer
            FVM_AUTO = -1
            FVM_FIRST = 1
            FVM_ICON = 1
            FVM_SMALLICON = 2
            FVM_LIST = 3
            FVM_DETAILS = 4
            FVM_THUMBNAIL = 5
            FVM_TILE = 6
            FVM_THUMBSTRIP = 7
            FVM_CONTENT = 8
            FVM_LAST = 8
        End Enum
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure FOLDERSETTINGS
            Public ViewMode As UInteger
            Public fFlags As UInteger
        End Structure
    
        <ComImport>
        <Guid("dfd3b6b5-c10c-4be9-85f6-a66969f402f6")>
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Public Interface IExplorerBrowser
            Function Initialize(hwndParent As IntPtr, ByRef prc As RECT, ByRef pfs As FOLDERSETTINGS) As HRESULT
            Function Destroy() As HRESULT
            Function SetRect(ByRef phdwp As IntPtr, rcBrowser As RECT) As HRESULT
            Function SetPropertyBag(pszPropertyBag As String) As HRESULT
            Function SetEmptyText(pszEmptyText As String) As HRESULT
            Function SetFolderSettings(pfs As FOLDERSETTINGS) As HRESULT
    
            'IExplorerBrowserEvents *psbe
            Function Advise(psbe As IntPtr, ByRef pdwCookie As Integer) As HRESULT
            Function Unadvise(dwCookie As Integer) As HRESULT
            Function SetOptions(dwFlag As EXPLORER_BROWSER_OPTIONS) As HRESULT
            Function GetOptions(ByRef pdwFlag As EXPLORER_BROWSER_OPTIONS) As HRESULT
            Function BrowseToIDList(pidl As IntPtr, uFlags As UInteger) As HRESULT
    
            'IUnknown *punk,
            Function BrowseToObject(punk As IntPtr, uFlags As UInteger) As HRESULT
            Function FillFromObject(punk As IntPtr, dwFlags As EXPLORER_BROWSER_FILL_FLAGS) As HRESULT
            Function RemoveAll() As HRESULT
            Function GetCurrentView(ByRef riid As Guid, ByRef ppv As IntPtr) As HRESULT
        End Interface
    
        Public Const SBSP_ABSOLUTE = &H0
    
        <DllImport("User32.dll", SetLastError:=True)>
        Public Shared Function GetClientRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
        End Function
    
        <DllImport("User32.dll", SetLastError:=True)>
        Private Shared Function MoveWindow(hWnd As IntPtr, X As Integer, Y As Integer, nWidth As Integer, nHeight As Integer, bRepaint As Boolean) As Boolean
        End Function
    
        <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True)>
        Public Shared Function SHGetKnownFolderIDList(ByRef rfid As Guid, dwFlags As Integer, hToken As IntPtr, ByRef ppidl As IntPtr) As HRESULT
        End Function
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim CLSID_ExplorerBrowser As New Guid("71f96385-ddd6-48d3-a0c1-ae06e8b055fb")
            Dim ExplorerBrowserType As Type = Type.GetTypeFromCLSID(CLSID_ExplorerBrowser, True)
            Dim ExplorerBrowser As Object = Activator.CreateInstance(ExplorerBrowserType)
            Dim pExplorerBrowser As IExplorerBrowser = DirectCast(ExplorerBrowser, IExplorerBrowser)
    
            Dim fs As FOLDERSETTINGS
            fs.ViewMode = FOLDERVIEWMODE.FVM_DETAILS
            fs.fFlags = 0
            Dim rc As RECT
            GetClientRect(Me.Handle, rc)
            Dim hr As HRESULT = pExplorerBrowser.Initialize(Me.Handle, rc, fs)
            If (hr = HRESULT.S_OK) Then
                pExplorerBrowser.SetOptions(EXPLORER_BROWSER_OPTIONS.EBO_SHOWFRAMES Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_ALWAYSNAVIGATE Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOTRAVELLOG Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOWRAPPERWINDOW Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_HTMLSHAREPOINTVIEW Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOBORDER Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOPERSISTVIEWSTATE)
                Dim pidlInit As IntPtr
                Dim FOLDERID_ComputerFolder As New Guid("0AC0837C-BBF8-452A-850D-79D08E667CA7")
                SHGetKnownFolderIDList(FOLDERID_ComputerFolder, 0, IntPtr.Zero, pidlInit)
                pExplorerBrowser.BrowseToIDList(pidlInit, SBSP_ABSOLUTE)
            End If
        End Sub
    
        Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Dim hWndBrowserControl As IntPtr = FindWindowEx(Me.Handle, IntPtr.Zero, "ExplorerBrowserControl", Nothing)
            MoveWindow(hWndBrowserControl, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, True)
        End Sub
    End Class



    • Edited by Castorix31 Saturday, October 14, 2017 2:44 PM
    • Marked as answer by Robert Homes Sunday, October 15, 2017 2:33 PM
    Saturday, October 14, 2017 2:26 PM

All replies

  • See Developing with Windows Explorer

    Basically, it's about instantiating the COM objects and using the interfaces that are provided by the shell. I do all my shell-related work in native C++ so I'm not familiar enough with VB .Net framework classes to advise if there are any managed equivalents.


    • Edited by RLWA32 Saturday, October 14, 2017 2:30 AM
    Saturday, October 14, 2017 2:29 AM
  • You can embed Explorer inside a Form with IExplorerBrowser

    A basic sample  =>

    (I did not test all the functions of the interface, some could be wrong, I just copied them from C++)

    Imports System.Runtime.InteropServices
    Public Class Form1
        Public Enum HRESULT As Integer
            DRAGDROP_S_CANCEL = &H40101
            DRAGDROP_S_DROP = &H40100
            DRAGDROP_S_USEDEFAULTCURSORS = &H40102
            DATA_S_SAMEFORMATETC = &H40130
            S_OK = 0
            S_FALSE = 1
            E_NOINTERFACE = &H80004002
            E_NOTIMPL = &H80004001
            OLE_E_ADVISENOTSUPPORTED = &H80040003
            E_FAIL = &H80004005
            MK_E_NOOBJECT = &H800401E5
        End Enum
    
        Public Enum EXPLORER_BROWSER_OPTIONS As Integer
            EBO_NONE = 0
            EBO_NAVIGATEONCE = &H1
            EBO_SHOWFRAMES = &H2
            EBO_ALWAYSNAVIGATE = &H4
            EBO_NOTRAVELLOG = &H8
            EBO_NOWRAPPERWINDOW = &H10
            EBO_HTMLSHAREPOINTVIEW = &H20
            EBO_NOBORDER = &H40
            EBO_NOPERSISTVIEWSTATE = &H80
        End Enum
    
        Public Enum EXPLORER_BROWSER_FILL_FLAGS As Integer
            EBF_NONE = 0
            EBF_SELECTFROMDATAOBJECT = &H100
            EBF_NODROPTARGET = &H200
        End Enum
    
        Public Structure RECT
            Public Left As Integer
            Public Top As Integer
            Public Right As Integer
            Public Bottom As Integer
        End Structure
    
        Public Enum FOLDERVIEWMODE As Integer
            FVM_AUTO = -1
            FVM_FIRST = 1
            FVM_ICON = 1
            FVM_SMALLICON = 2
            FVM_LIST = 3
            FVM_DETAILS = 4
            FVM_THUMBNAIL = 5
            FVM_TILE = 6
            FVM_THUMBSTRIP = 7
            FVM_CONTENT = 8
            FVM_LAST = 8
        End Enum
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure FOLDERSETTINGS
            Public ViewMode As UInteger
            Public fFlags As UInteger
        End Structure
    
        <ComImport>
        <Guid("dfd3b6b5-c10c-4be9-85f6-a66969f402f6")>
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Public Interface IExplorerBrowser
            Function Initialize(hwndParent As IntPtr, ByRef prc As RECT, ByRef pfs As FOLDERSETTINGS) As HRESULT
            Function Destroy() As HRESULT
            Function SetRect(ByRef phdwp As IntPtr, rcBrowser As RECT) As HRESULT
            Function SetPropertyBag(pszPropertyBag As String) As HRESULT
            Function SetEmptyText(pszEmptyText As String) As HRESULT
            Function SetFolderSettings(pfs As FOLDERSETTINGS) As HRESULT
    
            'IExplorerBrowserEvents *psbe
            Function Advise(psbe As IntPtr, ByRef pdwCookie As Integer) As HRESULT
            Function Unadvise(dwCookie As Integer) As HRESULT
            Function SetOptions(dwFlag As EXPLORER_BROWSER_OPTIONS) As HRESULT
            Function GetOptions(ByRef pdwFlag As EXPLORER_BROWSER_OPTIONS) As HRESULT
            Function BrowseToIDList(pidl As IntPtr, uFlags As UInteger) As HRESULT
    
            'IUnknown *punk,
            Function BrowseToObject(punk As IntPtr, uFlags As UInteger) As HRESULT
            Function FillFromObject(punk As IntPtr, dwFlags As EXPLORER_BROWSER_FILL_FLAGS) As HRESULT
            Function RemoveAll() As HRESULT
            Function GetCurrentView(ByRef riid As Guid, ByRef ppv As IntPtr) As HRESULT
        End Interface
    
        Public Const SBSP_ABSOLUTE = &H0
    
        <DllImport("User32.dll", SetLastError:=True)>
        Public Shared Function GetClientRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
        End Function
    
        <DllImport("User32.dll", SetLastError:=True)>
        Private Shared Function MoveWindow(hWnd As IntPtr, X As Integer, Y As Integer, nWidth As Integer, nHeight As Integer, bRepaint As Boolean) As Boolean
        End Function
    
        <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True)>
        Public Shared Function SHGetKnownFolderIDList(ByRef rfid As Guid, dwFlags As Integer, hToken As IntPtr, ByRef ppidl As IntPtr) As HRESULT
        End Function
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim CLSID_ExplorerBrowser As New Guid("71f96385-ddd6-48d3-a0c1-ae06e8b055fb")
            Dim ExplorerBrowserType As Type = Type.GetTypeFromCLSID(CLSID_ExplorerBrowser, True)
            Dim ExplorerBrowser As Object = Activator.CreateInstance(ExplorerBrowserType)
            Dim pExplorerBrowser As IExplorerBrowser = DirectCast(ExplorerBrowser, IExplorerBrowser)
    
            Dim fs As FOLDERSETTINGS
            fs.ViewMode = FOLDERVIEWMODE.FVM_DETAILS
            fs.fFlags = 0
            Dim rc As RECT
            GetClientRect(Me.Handle, rc)
            Dim hr As HRESULT = pExplorerBrowser.Initialize(Me.Handle, rc, fs)
            If (hr = HRESULT.S_OK) Then
                pExplorerBrowser.SetOptions(EXPLORER_BROWSER_OPTIONS.EBO_SHOWFRAMES Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_ALWAYSNAVIGATE Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOTRAVELLOG Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOWRAPPERWINDOW Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_HTMLSHAREPOINTVIEW Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOBORDER Or
                                  EXPLORER_BROWSER_OPTIONS.EBO_NOPERSISTVIEWSTATE)
                Dim pidlInit As IntPtr
                Dim FOLDERID_ComputerFolder As New Guid("0AC0837C-BBF8-452A-850D-79D08E667CA7")
                SHGetKnownFolderIDList(FOLDERID_ComputerFolder, 0, IntPtr.Zero, pidlInit)
                pExplorerBrowser.BrowseToIDList(pidlInit, SBSP_ABSOLUTE)
            End If
        End Sub
    
        Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Dim hWndBrowserControl As IntPtr = FindWindowEx(Me.Handle, IntPtr.Zero, "ExplorerBrowserControl", Nothing)
            MoveWindow(hWndBrowserControl, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, True)
        End Sub
    End Class



    • Edited by Castorix31 Saturday, October 14, 2017 2:44 PM
    • Marked as answer by Robert Homes Sunday, October 15, 2017 2:33 PM
    Saturday, October 14, 2017 2:26 PM
  • Kudos to Castorix31 for doing the heavy lifting to create the interop code!
    Saturday, October 14, 2017 2:49 PM
  • @Castorix

    Good job there.

    I have tried the code you posted with some success.

    I started a new project with Form1 and Form2

    Put the posted code into Form2.

    In Form1 I added 2 buttons for Open/Close and the following code.

    Option Strict On
    Option Explicit On
    Public Class Form1
        Dim fb As New Form2
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            fb.Show()
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            fb.Dispose()
            fb = New Form2
        End Sub
    End Class

    This enable a 'file browser' to be opened/closed. Had to be slightly convoluted as the 'normal' expected behaviour with form close/hide/dispose was 'strange'.

    *

    However:

    How to navigate to a desired folder on 'start up' of browser?

    How to store the 'current folder' view into a variable for reuse?

    and no doubt, several as yet unknown questions will surface.


    Regards Les, Livingston, Scotland

    Saturday, October 14, 2017 4:00 PM
  • How to navigate to a desired folder on 'start up' of browser?

    How to store the 'current folder' view into a variable for reuse?

    You navigate to a folder by getting its pidl from the path (then pExplorerBrowser.BrowseToIDList()

    For example with

    <DllImport("Shell32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SHILCreateFromPath(<MarshalAs(UnmanagedType.LPWStr)> pszPath As String, ByRef ppIdl As IntPtr, ByRef rgflnOut As UInteger) As HRESULT
        End Function

    You store the current view with :

    Dim pFolderView2Ptr As IntPtr
    Dim IID_IFolderView2 As New Guid("1af3a467-214f-4298-908e-06b03e0b39f9")
    hr = pExplorerBrowser.GetCurrentView(IID_IFolderView2, pFolderView2Ptr)

    You restore it with :

    hr = pExplorerBrowser.BrowseToObject(pFolderView2Ptr, 0)


    • Edited by Castorix31 Saturday, October 14, 2017 8:43 PM
    Saturday, October 14, 2017 8:43 PM
  • Wow! That looks nice, but I feel it's too complicated for me. I'm trying to keep things simple (impossible, right?!). If you know of a simpler approach let me know. Meanwhile, I'll get back to you if other methods I'm trying fail. Thanks.

    Robert Homes

    Sunday, October 15, 2017 2:29 PM
  • Great! Thanks for this.

    Robert Homes

    Sunday, October 15, 2017 2:33 PM
  • Hi, great job! A little complicated for me. Can you help with a few suggestions on usage?

    1. Can (and how to) set the explorer form before opening/showing it to not show the navigation bar.

    2. How to set the particular folder to open before opening it?

    3. If I close the explorer window, I can't reopen it due to error: Can't display a disposed object. I provided a close button in my main form and set that to simply hide the explorer window, but that didn't help.

    Thanks.


    Robert Homes


    Sunday, October 15, 2017 3:18 PM
  • Hi

    As per another comment I made in another of your threads. Please let the readers understand what/who you are replying to.

    Also, as Tommy mentioned, you will need to post code to illustrate the points you raise.


    Regards Les, Livingston, Scotland

    Sunday, October 15, 2017 4:14 PM