Everton Agner Everton Agner - 11 months ago 64
C# Question

Get directories list from windows media libraries

Is there any way to programatically lookup the list of directories currently setup on Windows' Media Libraries?

E.g.: Supposing I have the following libraries (I apologize for the portuguese, but you'll get the idea):

enter image description here

How can I get programatically these three directories paths listed on the Video library?


This question almost got me there, but its not exactly what I want. So far, my alternative is trying to look that up directly from the Windows Registry.

Answer Source

Here it is, finally!

 using System.Runtime.InteropServices;
 using System.Diagnostics;
 using System.IO;
 using System.Xml;

 private static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, ref IntPtr ppszPath);

 public void GetVideoLibraryFolders()
     var pathPtr = default(IntPtr);
     var videoLibGuid = new Guid("491E922F-5643-4AF4-A7EB-4E7A138D8174");
     SHGetKnownFolderPath(videoLibGuid, 0, IntPtr.Zero, ref pathPtr);

     string path = Marshal.PtrToStringUni(pathPtr);
     List<string> foldersInLibrary = new List<string>();

     using (XmlReader reader = XmlReader.Create(path))
         while (reader.ReadToFollowing("simpleLocation"))

     for (int i = 0; i < foldersInLibrary.Count; i++)
         if (foldersInLibrary[i].Contains("knownfolder"))
             foldersInLibrary[i] = foldersInLibrary[i].Replace("knownfolder:{", "");
             foldersInLibrary[i] = foldersInLibrary[i].Replace("}", "");

             SHGetKnownFolderPath(new Guid(foldersInLibrary[i]), 0, IntPtr.Zero, ref pathPtr);
             foldersInLibrary[i] = Marshal.PtrToStringUni(pathPtr);

    // foldersInLibrary now contains the path to all folders in the Videos Library


So, how did I do it?

First off, there's this function SHGetKnownFolderPath in the shell32.dll library, which returns the path of a folder provided its GUID (documentation). And there's also a list of GUIDs for each Known Folder on Windows.

"491E922F-5643-4AF4-A7EB-4E7A138D8174" is the ID for the Videos_Library folder.

But there's one problem! That function will return this path: %appdata%\Microsoft\Windows\Libraries\Videos.library-ms

If you try to access that folder with methods like Directory.GetDirectories you will get a DirectoryNotFoundException. What's wrong? Well, the problem is: Videos.library-ms isn't a folder! It's a XML file. If you open it with some text editor, you'll see.

After discovering that it was a XML file, then all I had to do was to read it and we would have the path to the directories. If you open the xml, you'll see that all the folders in a Library are under <simpleLocation> elements. So you simply have to read all the <simpleLocation> XML Elements and then their child element <url>, which content contains the path for the folder itself.

Although that could be the end, I luckily noticed that not every folder path is described as an usual path in the .library-ms file; some of them are described with GUID's (yes, those same I linked previously), and those have the knownfolder attribute in them. Thus, in the last for, I search for elements in the List of directories which have the knownfolder attribute in them. For each one found, I then replace their value with the correct one, by searching all over again to which path that GUID points using SHGetKnownFolderPath.

So, that's it!