0

Looking for help trying to figure out why this typecast is not working on my machine.
This code was provided as an answer to another question I had and it's not working for me. It works for the answer poster on their machine, but I'm get a an exception on the line trying to typecast from ShellBrowserWindow to ShellFolderView.

I am using Visual Studio Express 2013, running on Windows 7 Pro X64 Sp1. The target framework for the project is .Net Framework 4. I've added references to Microsoft Internet Controls and Microsoft Shell Controls and Automation and I've added the Imports statements for Shell32 and SHDocVw. DLL versions are as follows: shell32.dll = 6.1.7601.18517 and shdocvw.dll = 6.1.7601.1822 I'm not sure what I could be missing.

The code looks like this. (This code is in a form object)

     Imports EdmLib
     Imports Shell32
     Imports SHDocVw
     Public Class BlankForm   
         Private Sub BlankForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load

             Dim bar As String() = GetExplorerSelectedFiles()
             Exit Sub        
             'The rest of my program is below this line - I'm just trying to test this one function right now...

         End Sub

         'Uses the windows shell to get the files selected in explorer
         Public Function GetExplorerSelectedFiles() As String()
             Dim ExplorerFiles As New List(Of String)
             Dim exShell As New Shell32.Shell
             Dim SFV As Shell32.ShellFolderView


             For Each window As SHDocVw.ShellBrowserWindow In DirectCast(exShell.Windows, SHDocVw.IShellWindows)
                 If (window.Document).GetType.Name <> "HTMLDocumentClass" Then
                     SFV = CType(window.Document, ShellFolderView) '<--This is where it fails!!
                     For Each fi As FolderItem In SFV.SelectedItems
                         ExplorerFiles.Add(fi.Path)
                     Next
                 End If
             Next

             Return ExplorerFiles.ToArray
         End Function
 End Class

The line SFV = CType(window.Document, ShellFolderView) results in the following message:

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)).

I've taken a screenshot of a quickwatch on the window object. A quickwatch on the window.document object shows an error saying it's either undefined or inaccessible.

Quickwatch on "window" object Quickwatch on "window.document"

I ran the query Microsoft.VisualBasic.Information.TypeName(window.document) and it returns "IShellFolderViewDual3".

Community
  • 1
  • 1
CBRF23
  • 1,340
  • 1
  • 16
  • 44
  • It shows the same on mine, but if you drill into the `window` var, it shows that it knows it is `Shell32.ShellFolderView` type: http://i.imgur.com/wYyar3Y.jpg – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 19:22
  • Ah, so there is a breakdown somewhere on my machine, as when I try to dig-down into the document property as you have I get an error "No children available". http://i.imgur.com/jg73s3T.png – CBRF23 Jun 24 '15 at 19:25
  • you have something else at play - note the `IWebBrowser2` type at the top (and `ShellBrowserWindow`). Is it possible that you are trying to get selected files from from *Internet* Explorer rather than Windows Explorer or that the file is not local? – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 19:28
  • Strange, if I drill down into it the same way you did, I get the following (which is still not the type we're hoping for): http://i.imgur.com/3OWhOee.png?1 – CBRF23 Jun 24 '15 at 19:29
  • The "name" property of the `window` object says "Windows Explorer" so I believe it is correct - but I don't know how I would tell otherwise. – CBRF23 Jun 24 '15 at 19:31
  • http://imgur.com/nh9I0iq – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 19:32
  • Hmm.... http://i.imgur.com/NafiyyC.png – CBRF23 Jun 24 '15 at 19:35
  • Maybe check your DLL versions, or get a friend to test a minimal compiled example. That same approach is here a number of times with minor variations - this is the first time I have heard of it failing. Try using the full name: `SFV = CType(window.Document, Shell32.ShellFolderView)` also see if it will let you just declare a var: `Dim test As Shell32.ShellFolderView` – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 19:37
  • I've actually tried both of those options :) Might have noticed in my screenshot the Directcast method is commented out...I currently have it as `Dim ShellWindows As SHDocVw.IShellWindows = exShell.Windows` I'll have to see what DLL versions I have. I did run a system file check from command line and that said everything was good (0 issues found). – CBRF23 Jun 24 '15 at 19:44
  • Another test - I did a query as `Microsoft.VisualBasic.Information.TypeName(window.document)` and it returns "IShellFolderViewDual3" – CBRF23 Jun 24 '15 at 19:46
  • DLL versions are as follows. **shell32.dll = 6.1.7601.18517** and **shdocvw.dll = 6.1.7601.1822** – CBRF23 Jun 24 '15 at 19:56
  • No problem using `Dim test As New Shell32.ShellFolderView`.... http://i.imgur.com/HyjKvRr.png?1 – CBRF23 Jun 24 '15 at 20:06
  • According to [this answer](http://stackoverflow.com/a/2417658/4106771) it appears the expected return *is* an "IShellFolderViewDual" object. However, I can't seem to find this anywhere in the object browser and intellitype doens't recognize it either, so I'm not sure how to use it... – CBRF23 Jun 24 '15 at 20:34
  • Try using it in place of `ShellFolderView` - either one works fine on mine – Ňɏssa Pøngjǣrdenlarp Jun 24 '15 at 21:40

1 Answers1

0

I fixed it. Not sure why this happens on my system and not yours. What I found was that GetType.Name always just returns "System.__ComObject", regardless of whether the object is of type ShellFolderView, HTMLDocumentClass or something else. So what was happening was no matter what the actual type of the object was, it was passing the <>"HTMLDocumentClass" test because it was always evaluating to "System.__ComObject". Then when we tried to run the CType function on an object that didn't implement the ShellFolderView interface, it would throw that exception.

I eventually stumbled upon this article which led me to experiment with the TypeName Function which seems to return the actual type, and so I ended up with the working code below:

Public Function GetExplorerSelectedFiles() As String()
    Dim ExplorerFiles As New List(Of String)
    Dim exShell As New Shell32.Shell

    For Each window As SHDocVw.ShellBrowserWindow In DirectCast(exShell.Windows, SHDocVw.IShellWindows)

        If TypeName(window.Document) Like "IShellFolderViewDual*" 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
CBRF23
  • 1,340
  • 1
  • 16
  • 44