从Windows媒体库获取目录列表

时间:2014-12-14 00:57:42

标签: c# .net windows

有没有办法以编程方式查找当前在Windows上设置的目录列表'媒体图书馆?

例如:假设我有以下图书馆(我为葡萄牙语道歉,但你会得到这个想法):

enter image description here

如何以编程方式获取视频库上列出的三个目录路径

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

This question几乎把我带到了那里,但这并不是我想要的。到目前为止,我的替代方案是尝试直接从 Windows注册表

查找

2 个答案:

答案 0 :(得分:4)

终于来了!

 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

 }

那么,我是怎么做到的?

首先,SHGetKnownFolderPath库中有此函数shell32.dll,它返回提供GUID(documentation)的文件夹的路径。 此外,Windows上的每个已知文件夹还有list个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属性。因此,在最后for中,我搜索列表中具有knownfolder属性的元素。对于找到的每一个,然后我用正确的值替换它们的值,通过再次搜索GUID指向哪个路径SHGetKnownFolderPath

所以,那就是它!

答案 1 :(得分:2)

对于未来的研究人员来说,这里也是我提出的代码:

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文件夹编写了路径,然后添加了视频库XML 的文件名。在那之后,它只是Linq2XML魔术。