How do I programmatically add a folder to my Documents library?


Today's Little Program adds a folder to the Documents library. Remember that Little Programs do little to no error checking.

Today's smart pointer library is… (rolls dice)… nothing! We're going with raw pointers.

#define STRICT
#include <windows.h>
#include <ole2.h>
#include <shlobj.h>

int __cdecl wmain(int argc, wchar_t** argv)
{
  CoInitialize(nullptr);
  IShellLibrary* library;
  SHLoadLibraryFromKnownFolder(FOLDERID_DocumentsLibrary,
                               STGM_READWRITE, IID_PPV_ARGS(&library));
  for (int i = 1; i < argc; i++) {
    SHAddFolderPathToLibrary(library, argv[i]);
  }
  library->Release();
  CoUninitialize();
  return 0;
}

This program uses some helper functions for manipulating libraries. The SH­Load­Library­From­Known­Folder function is a shorthand for Co­Create­Instance(CLSID_Shell­Library) followed by IShell­Library::Load­Library­From­Known­Folder, and the SH­Add­Folder­Path­To­Library function is a shorthand for SH­Create­Item­From­Parsing­Name followed by IShell­Library::Add­Folder.

Run this program with the full path (or paths) to the folders you want to add to the Documents Library, and… nothing happens.

Ah, because there's a gotcha with libraries: After you make a change to a library, you need to commit your changes. So let's fix that:

#define STRICT
#include <windows.h>
#include <ole2.h>
#include <shlobj.h>

int __cdecl wmain(int argc, wchar_t** argv)
{
  CoInitialize(nullptr);
  IShellLibrary* library;
  SHLoadLibraryFromKnownFolder(FOLDERID_DocumentsLibrary,
                               STGM_READWRITE, IID_PPV_ARGS(&library));
  for (int i = 1; i < argc; i++) {
    SHAddFolderPathToLibrary(library, argv[i]);
  }
  library->Commit(); // add this line
  library->Release();
  CoUninitialize();
  return 0;
}

Okay, let's try it again. Run this program with the full path (or paths) to the folders you want to add to the Documents Library, and hooray! the folders are added to the Documents Library.

Comments (15)
  1. Erik says:

    Makes one wonder. Is there a sane use-case where one would want to AddFolderPathsToLibrary, but not commit afterwards?

    1. I think the Commit is a performance thing. Rebuilding the library after each individual Add would create wasted work if you were adding more than one.

      1. Erik says:

        Ah, makes sense. Thanks!

      2. poizan42 says:

        Well, they could commit on the final release, but doing important work when cleaning up is bad design.

  2. pc says:

    Somebody totally needs to actually create a Smart Pointer Library Die to give to Raymond for Christmas.

    1. Psst. Here’s a secret: The dice are loaded.

      1. Joshua says:

        That just means we need to make an easy way to weight them.

    2. SimonRev says:

      I would totally buy some for my coworkers for Christmas, if any of them read this blog.

    3. ZLB says:

      I’m pretty much certain that the last place I worked at actually had a ‘Delimiter of the day’ dice…

      …and no. Chr(0) is NOT a good choice for joining strings! (I wish I was joking!)

      1. JDG says:

        There is plenty of precedence for using ‘\0’ to separate strings, such as environment blocks and REG_MULTI_SZ. It’s actually not particularly inconvenient in C with C-style strings.

  3. Yukkuri says:

    I love the pointer dice roll (even if no actual dice are involved).

    1. Ian Yates says:

      Same. Unfortunately it’s one of those things I enjoy that if I tried to show and explain it to anyone else I know they’d think I was weird.

  4. Someone says:

    Why is this API available? Only the user himself (through Explorer) should be able to organize the Libraries, by exactly the argument as for the pin-to-taskbar feature.

  5. bickerdyke says:

    Speaking of sane use-cases…. what would be the use case for a software (most likely during the installation process) to create document storage outside the user profiles document directory and adding that to the library instead of creating a directory INSIDE the users regular documents folder?

    Wouldn’t this circumvent all of windows’ profile management? Like, those additional directories would not be backuped along with the rest of the users profile*, it would not be moved to a data partition if a user tries to split up his system in a OS and data partition**

    Where would be a suggested location for an additional application data directory that could be added to the document library? (in a safe and clean way)

    * if not specified separately
    ** assuming as somehow sane that some user data will always be stored within the OS partition

    1. Andrew Cook says:

      OneDrive, Dropbox, and SharePoint document libraries come to mind. You don’t really want them to roam with a user’s profile because, hey, they already roam a different way, and if you have a greedy synchronization stack (“up to date even before you log in!”) you don’t want them to invalidate a user’s profile. You may even want a different set of permissions (to line up with permissions on the remote site) that wouldn’t be reset by an overzealous “fix” to the user’s profile folder.

      Granted, you could easily accomplish all this and more with a shell namespace extension, but COM is hard, so let’s just create an icon overlay and go shopping!

Comments are closed.

Skip to main content