0

I have to edit an add-in that was written in visual studio in the vb.net language. What I need is a way to get a list of all the currently selected files from the active windows explorer window so that I can pass this to another function within the program. I'm not super experienced in visual studio (most of my experience has been in VBA which uses VB 6.0) so I'm looking for some advice before I spend too much time going down the wrong path.

I was thinking of using the Windows Shell object. I've found some examples written in C++ and I've spent some time reading through the MSDN, but before I invest a ton of time in this I wanted to reach out here to more experienced VB.Net/VS users. I know .Net has a lot of built in options for dealing with file/folder objects under the system.io namespace, but I haven't found anything yet that would allow me to see what are the currently selected items in an explorer window.

I'm just wondering if there is something native within .Net that would do what I need?
If not, is using the Windows Shell object the best way to go?

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
CBRF23
  • 1,340
  • 1
  • 16
  • 44
  • Check this out: http://stackoverflow.com/questions/8292953/get-current-selection-in-windowsexplorer-from-a-c-sharp-application – Pedro Isaaco Jun 22 '15 at 21:32
  • @Piters that is one of the examples I found searching this site that was leading me towards the Windows Shell Object. Are you saying this is definitely the recommended way to go? I just haven't found a lot of VB specific stuff, so wasn't sure if there was another way people go about this in VB.Net vs other languages. – CBRF23 Jun 22 '15 at 21:47

1 Answers1

2

This is just a minor revision of this answer. Rather than work off the focused item as the linked answer does, get the selected items from the ShellFolderView. System.IO wont do you much good because the File/Folder related classes have to do with the file system - the files have no idea if Explorer has them selected.

First, add reference to Microsoft Shell Controls and Automation and Microsoft Internet Controls (see the above link).

Imports Shell32
Imports SHDocVw

Private Function GetExplorerSelectedFiles() As String()
    Dim ExplorerFiles As New List(Of String)

    Dim exShell As New Shell


    For Each window As ShellBrowserWindow In DirectCast(exShell.Windows, IShellWindows)
        ' check both for either interface to work
        '    add an Exit for to just work the first explorer window 
        If TryCast(window.Document, IShellFolderViewDual) IsNot Nothing Then
            For Each fi As FolderItem In DirectCast(window.Document, IShellFolderViewDual).SelectedItems
                ExplorerFiles.Add(fi.Path)
            Next

        ElseIf TryCast(window.Document, ShellFolderView) IsNot Nothing Then
            For Each fi As FolderItem In DirectCast(window.Document, ShellFolderView).SelectedItems
                ExplorerFiles.Add(fi.Path)
            Next

        End If
    Next

    Return ExplorerFiles.ToArray
End Function

Usage (in a button click):

Dim files = GetExplorerSelectedFiles()
lbFiles.Items.AddRange(files)

enter image description hereenter image description here


Modified to work on either IShellFolderViewDual or ShellFolderView

Community
  • 1
  • 1
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • I haven't had a chance to test your code, but at first look it appears to me it would get all the selected files from all explorer windows, regardless if the window is active or not. I think we need to keep `If SFV.FocusedItem IsNot Nothing Then` from the linked answer, no? – CBRF23 Jun 23 '15 at 12:07
  • it works fine as is, but does get all selected files form Explorer (there is only one Explorer instance, but there can be multiple explorer windows/views). The "active" explorer window is transient - if your app has the input focus there are no active explorer windows. You might need a preliminary step to select a window. – Ňɏssa Pøngjǣrdenlarp Jun 23 '15 at 12:27
  • This is a "windows forms application" project so I'm thinking I can create a string variable at the startup event (before the form loads) and get the selected files from the active window before the application takes focus. – CBRF23 Jun 23 '15 at 12:32
  • thats very brittle - you have no guarantee that an Explorer viewer will be the active window when starting. It might be better to offer the user all the selected files you find and let them select which ones; or offer them a list of all explorer paths to pick from (e.g. `long path name... (3 files)`, `path name 2... (17 files)` and even omit the ones with no selected files – Ňɏssa Pøngjǣrdenlarp Jun 23 '15 at 12:37
  • the way the application is launched is from windows explorer. The user selects a file (or files) and right-clicks on selected file(s) and chooses to launch the application. So it will never be started unless explorer is the active window and at least one file is selected. I want to capture what they have selected when they choose to launch the app, I don't want to show any additional forms or ask them to re-select the files. – CBRF23 Jun 23 '15 at 13:08
  • exactly *how* does the app launch? as a shell extension? from a context menu? as a result of file association? Something else? In some cases, the exact files ought to be on the command line obviating the need to look for the files. – Ňɏssa Pøngjǣrdenlarp Jun 23 '15 at 13:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/81296/discussion-between-cbrf23-and-plutonix). – CBRF23 Jun 23 '15 at 14:19
  • Received an error message on the line `SFV=Ctype(...`. An unhandled exception of type 'System.InvalidCastException' occurred in LaunchTemplateEPDM.exe Additional information: Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.ShellFolderView'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{29EC8E6C-46D3-411F-BAAA-611A6C9CAC66}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)). – CBRF23 Jun 23 '15 at 20:20
  • are you using Windows 8? are you sure you added the references? – Ňɏssa Pøngjǣrdenlarp Jun 23 '15 at 20:52
  • Windows 7 Pro 64 bit, working in visual studio express 2013. – CBRF23 Jun 23 '15 at 21:07
  • Should work fine as x86 or 64bit Winforms App. Failing on the cast seems weird... – Ňɏssa Pøngjǣrdenlarp Jun 23 '15 at 21:26
  • Not sure what the problem is then. I found an [article](http://blogs.msdn.com/b/smondal/archive/2012/10/02/unable-to-cast-com-object-of-type-system-comobject-to-interface-type-microsoft-visualstudio-ole-interop-iserviceprovider.aspx) discussing a similar problem. I tried to register the shdocvw.dll file and got an error message: "[Window Title] RegSvr32 [Content] The module "C:\Windows\System32\shdocvw.dll" was loaded but the entry-point DllRegisterServer was not found. Make sure that "C:\Windows\System32\shdocvw.dll" is a valid DLL or OCX file and then try again. [OK]" – CBRF23 Jun 24 '15 at 13:22
  • You should not have to register either import if you added them as described [in the link provided](http://stackoverflow.com/a/29513938/1070452). They should show up as COM components and if they do, they are registered – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 13:30
  • Yes, I added both references for "Microsoft Internet Controls" and "Microsoft Shell Controls and Automation" from the "COM" type library in reference manager. Not sure why it is failing on my machine. Before the typecast, if I query the `typename` in the immediate window it says "_ComObject". [Here](http://i.imgur.com/lnV8QxC.png?1) is a screenshot of what I get from quick watch on the `window` object. If I try to quick watch on `window.document` it says `'Document' is not declared. It may be inaccessible due to its protection level`. I wonder if this is why the typecast fails? – CBRF23 Jun 24 '15 at 13:51
  • Just a thought, what framework are you using? I'm using .Net 4.0 as that is the latest framework supported by the program that uses this add-in. – CBRF23 Jun 24 '15 at 15:35
  • I've started a [new question](http://stackoverflow.com/q/31034683/4106771) for troubleshooting this solution as it is way off the original topic. – CBRF23 Jun 24 '15 at 18:54