여기가 마침내!
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의 대답과 동일 나는 상호 운용성을 통해 갈 필요가 없습니다했다는 사실에도 불구하고, :
미래 연구원 '를 위해서
거의 다 ... 내 사용자 폴더 아래에 "내 비디오"폴더 (및 해당 하위 디렉터리)를 반환합니다. 이 미디어 디렉토리는 여기에 없습니다 ... – everton
"Fileses"와 "Series"폴더는 반환하지 않고 "Vídeos"폴더 만 반환합니다. 그게 맞습니까? –
실제로 아닙니다. "비디오"라이브러리에서 "내 비디오"폴더를 제거했습니다. – everton