Shell Hell for VBA 64 bits

Microsoft, Non classé, Software

One of the useful uses of the Windows API, back in the old days of 32 bits programming, was to use the shell’s standard dialogs for browsing for a folder or picking a file. VB/VBA didn’t have a way to do that, whereas today, modern VB, I mean VBA7 of course (today’s “Visual Basic” denomination being attributed to the VB.NET treacherous brother), has beautiful means to do that; just install some megabytes of Office and there you go.

So there is the 32 bits code I use for browsing for a folder:

Now, I couldn’t find a way to make this work in 64 bits, and frankly, Internet has a lot of bugged code for you to try to. Many claim to have something working, I couldn’t find the correct declarations and calls to avoid GPFing. The crashes occur when invoking SHGetPathFromIDList.

Here’s how to do it in modern VBA (got it on developpez.net), and in classic VB5/VB6; note that we don’t need a port anymore as there’s is no 64 bits VB/VBA, thanks Microsoft, we always knew you wouldn’t let us down:

So, SHxxx or Shell functions are indeed hell-ish! As another example, it took me quite some time to port to 64 bits the damned SHGetSpecialFolderLocation function.

Again, hard to find any truly working code on the net.
So, let’s go for mine if you don’t mind. Here’s how I declare it:

And there’s how I make it work without crashing:

Hey, hope I spared you some head banging guys !

Time to post a decent comment (“Woaw”, “You suck” are ok too), fellow VB/A developpers.
I need to be a bit encouraged; then I’ll post my solution for another piece, the API way of using the clipboard (getdata/setdata with text), 32 and 64 bits compatible, a working one again.

Cheers 😉

Comments on this entry are closed.

  • Eijaz Sheikh

    Hi,

    I want to select the folder from a dialog. How do i do that? I dont need specialfolders.

    • franchsesko

      In VB5/8 you can call the BrowseForFolder() function, like in this snippet:

      Dim SelectedFolderName as String
      SelectedFolderName = BrowseForFolder(0&, “Pick a folder”)
      Debug.Print “The selected folder is named: “; SelectedFolderName

      But today, if you’re on VBA (Access, Excel, Word, etc..), you can now use the built-in Application FileDialog object, as in this example where I wrap it in a SelectDir function:

      Public Function SelectDir(ByVal psTitle As String) As String
      On Error Resume Next
      With Application.FileDialog(msoFileDialogFolderPicker)
      .Title = psTitle
      If .Show() Then
      SelectDir = .SelectedItems(1)
      End If
      End With
      End Function

      And then use it like that:

      Dim SelectedFolderName as String
      SelectedFolderName = SelectDir(0&, “Pick a folder”)
      Debug.Print “The selected folder is named: “; SelectedFolderName

      Cheers

  • jmerichards

    Nice work! Thanks!

  • WOW !!

  • TITEMIDLIST = ITEMIDLIST, the “T” was intentionally added when I was messing with all this stuff, I didn’t care to take it off after, but to be consistent with the API definitions it should be. You’re right (as is jpk-ads.com, which is by the way also a great source, thanks), the return value should also be declared as boolean for the sake of consistency with the API. I do not remember why I got from LongPtr to Any for the PIDL. They may probably end up to be equivalent in that case. Anyway, as both versions make sense I’m keeping the version with which I tested for that one. I’m updating the post. Happy coding 😉

  • Carol

    Awesome, your code DID save me lots of time. And, I liked how you also made the function for both 32- and 64-bit by using Enum. The only thing I changed was “TITEMIDLIST” to “ITEMIDLIST.” Was it an intentional misspelling? I also used the declares listed at http://www.jkp-ads.com/articles/apideclarations.asp. The SHGetPathFromIDList is declared as a boolean, with the pidl handle set to longptr and long.