2014-12-14 3 views
2

Windows Media 라이브러리에서 현재 설치되어있는 디렉터리 목록을 프로그래밍 방식으로 조회하는 방법이 있습니까?Windows 미디어 라이브러리에서 디렉터리 목록 가져 오기

예 : 어떻게 프로그래밍 방식가 나열이 세 개의 디렉토리 경로를 얻을 수 있습니다

enter image description here

: 나는 다음과 같은 라이브러리를 (필자는 포르투갈어 죄송합니다,하지만 당신은 아이디어를 얻을 수 있습니다)이 가정하면 비디오 라이브러리?

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

This question 지금까지, 내 ​​대안은 직접 Windows 레지스트리에서 직접 찾으려고합니다.

답변

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 

} 

그래서 어떻게 했습니까?

먼저이 GUID (documentation)가 제공된 폴더의 경로를 반환하는 라이브러리에 SHGetKnownFolderPath이있는이 함수가 있습니다. Windows의 각 알려진 폴더에 대해 GUID가 list 개 있습니다.

"491E922F-5643-4AF4-A7EB-4E7A138D8174"Videos_Library 폴더의 ID입니다.

하지만 한 가지 문제가 있습니다. 이 함수는 다음 경로를 반환합니다. %appdata%\Microsoft\Windows\Libraries\Videos.library-ms

Directory.GetDirectories과 같은 방법으로 해당 폴더에 액세스하려고 시도하면 DirectoryNotFoundException이 표시됩니다. 뭐가 문제 야? 글쎄, 문제는 : Videos.library-ms은 폴더가 아닙니다! 그것은 XML 파일입니다. 일부 텍스트 편집기로 열면 볼 수 있습니다.

XML 파일이라는 사실을 알게 된 다음에는 XML 파일을 읽는 것만으로 디렉터리를 찾을 수있었습니다. xml을 열면 라이브러리의 모든 폴더가 <simpleLocation> 요소 아래에 있음을 알 수 있습니다. 따라서 모든 <simpleLocation> XML 요소와 그 하위 요소 인 <url>을 읽으면됩니다. 콘텐츠에는 폴더 자체의 경로가 들어 있습니다.

그게 끝날 수도 있지만, 모든 폴더 경로가 .library-ms 파일의 일반적인 경로로 표시되는 것은 아닙니다. 그들 중 일부는 GUID (예, 이전에 링크 된 것과 동일)로 설명되어 있으며 그 중 일부는 knownfolder 속성을 가지고 있습니다. 따라서 마지막으로 for에서 나는 knownfolder 속성이있는 디렉토리 목록에서 요소를 검색합니다. 발견 된 각각에 대해 GUID가 가리키는 경로를 다시 검색하여 SHGetKnownFolderPath을 사용하여 올바른 값으로 바꿉니다.

그럼, 그게 전부입니다!

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의 대답과 동일 나는 상호 운용성을 통해 갈 필요가 없습니다했다는 사실에도 불구하고, :

미래 연구원 '를 위해서
+0

거의 다 ... 내 사용자 폴더 아래에 "내 비디오"폴더 (및 해당 하위 디렉터리)를 반환합니다. 이 미디어 디렉토리는 여기에 없습니다 ... – everton

+0

"Fileses"와 "Series"폴더는 반환하지 않고 "Vídeos"폴더 만 반환합니다. 그게 맞습니까? –

+0

실제로 아닙니다. "비디오"라이브러리에서 "내 비디오"폴더를 제거했습니다. – everton

2

, 여기에 내가뿐만 아니라 해낸 코드는 .

기본적으로, 나는 라이브러리 폴더의 경로를 구성 한 후 비디오 라이브러리 XML의 파일 이름을 추가. 그 후에는 단지 Linq2XML 마술입니다.

+0

니스! 'knownfolder'가 있는지 확인하는 것을 잊지 마십시오. Windows 8에서 Documents 라이브러리에는 기본적으로 SkyDrive의 Documents 폴더가 포함되어 있습니다.이 폴더는 알려진 폴더이므로 Documents.library-ms에 GUID (해당 주소가 아닌)로 표시됩니다. –

+0

알아두면 좋지만 지금은 동영상 라이브러리 만 나와 관련이 있습니다. Btw, 이건 다음과 같습니다. https://subsync.codeplex.com – everton

+1

나는 당신이 의미하는 바를 얻었습니다. 비디오 라이브러리의 경우에도 Windows는 GUID를 사용하여 기본 비디오 폴더를 설정합니다. 내가 그들을 확인하는 코드를 사용해야합니다 :) – everton

관련 문제