从Windows媒体库获取目录列表

有没有什么办法可以编程查找目前在Windows媒体库上设置的目录列表?

例如:假设我有以下图书馆(我为葡萄牙语道歉,但你会明白):

在这里输入图像说明

如何以编程方式获取video库中列出的这三个目录path

D:\Filmes D:\Series D:\Videos 

这个问题几乎让我在那里,但它不完全是我想要的。 到目前为止,我的select是试图直接从Windowsregistry中查找。

这是最后的!

  using System.Runtime.InteropServices; using System.Diagnostics; using System.IO; using System.Xml; [DllImport("shell32.dll")] 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); Marshal.FreeCoTaskMem(pathPtr); List<string> foldersInLibrary = new List<string>(); using (XmlReader reader = XmlReader.Create(path)) { while (reader.ReadToFollowing("simpleLocation")) { reader.ReadToFollowing("url"); foldersInLibrary.Add(reader.ReadElementContentAsString()); } } 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); Marshal.FreeCoTaskMem(pathPtr); } } // foldersInLibrary now contains the path to all folders in the Videos Library } 

那么,我是怎么做到的?

首先, shell32.dll库中有SHGetKnownFolderPath函数,它返回提供GUID( 文档 )的文件夹的路径。 还有Windows上每个已知文件夹的GUID 列表 。

"491E922F-5643-4AF4-A7EB-4E7A138D8174"Videos_Library文件夹的ID。

但是有一个问题! 该函数将返回此路径: %appdata%\Microsoft\Windows\Libraries\Videos.library-ms

如果您尝试使用Directory.GetDirectories方法访问该文件夹,您将得到一个DirectoryNotFoundException 。 怎么了? 那么,问题是: Videos.library-ms不是一个文件夹! 这是一个XML文件。 如果你用一些文本编辑器打开它,你会看到。

在发现它是一个XML文件后,我所要做的只是读取它,我们将有路径到目录。 如果你打开xml,你会发现库中的所有文件夹都在<simpleLocation>元素之下。 所以你只需要读取所有的<simpleLocation> XML元素,然后读取它们的子元素<url> ,其中的内容包含文件夹本身的路径。

虽然这可能是结束,我幸运地注意到,不是每个文件夹路径被描述为.library-ms文件中的通常路径; 其中一些是用GUID(是的,我之前链接的那些)描述的,那些文件中有knownfolder属性。 因此,最后,我搜索目录列表中具有knownfolder属性的元素。 对于找到的每一个,我然后用正确的替换它们的值,通过使用SHGetKnownFolderPath再次搜索GUID指向哪个路径。

就是这样了!

对于未来研究人员的缘故,下面是我提出的代码:

 public class MediaLibraries { private static readonly string LibrariesFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Libraries"; private static readonly string VideosLibraryFileName = "Videos.library-ms"; private static IEnumerable<DirectoryInfo> _videosDirectories; public static IEnumerable<DirectoryInfo> VideosDirectories { get { if (_videosDirectories != null) return _videosDirectories; _videosDirectories = new HashSet<DirectoryInfo>(); var videosLibraryXmlFilePath = Path.Combine(LibrariesFolderPath, VideosLibraryFileName); if (!File.Exists(videosLibraryXmlFilePath)) return _videosDirectories; XDocument videosLibraryXml = XDocument.Load(File.OpenRead(videosLibraryXmlFilePath)); XNamespace ns = videosLibraryXml.Root.Name.Namespace; string[] videoFoldersPaths = videosLibraryXml.Root .Element(ns + "searchConnectorDescriptionList") .Elements(ns + "searchConnectorDescription") .Select(scd => scd.Element(ns + "simpleLocation").Element(ns + "url").Value) .ToArray(); _videosDirectories = videoFoldersPaths.Select(v => new DirectoryInfo(v)).AsEnumerable(); return _videosDirectories; } } } 

这个想法和AndreSilva的答案是一样的,尽管事实上我不需要经过互操作。

基本上,我已经编写了Libraries文件夹的路径,然后为Video Libraries XML添加了文件名。 之后,这只是Linq2XML魔力。