简体   繁体   English

如何在C#中浏览本地虚拟文件夹?

[英]How can I browse a local virtual folder in C#?

In my C# program I have to browse directories. 在我的C#程序中,我必须浏览目录。 So I use the method System.IO.Directory.GetFiles(directory) and it works well when directory is a real directory like "C:\\Program File" but when it's a virtual directory (eg: librairie directory), directory value looks like this : "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\\Pictures.library-ms" and I don't know how to browse it. 所以我使用方法System.IO.Directory.GetFiles(directory) ,当目录是一个真实的目录,如“C:\\ Program File”,但当它是一个虚拟目录(例如:librairie目录)时,它运行良好,目录值看起来像这个:“:: {031E4825-7B94-4dc3-B131-E946B44C8DD5} \\ Pictures.library-ms”我不知道如何浏览它。

You need to translate the virtual path into a physical one, try: 您需要将虚拟路径转换为物理路径,尝试:

DirectoryInfo directoryInfo = new DirectoryInfo(Server.MapPath("your virtual folder here"));

You might want to read up on DirectoryInfo . 您可能想要阅读DirectoryInfo If that's no use, give this a try this instead: 如果这没用,请试试这个:

DirectoryInfo info = new DirectoryInfo("virtual folder here");
FileInfo[] files = info.GetFiles("*.*", SearchOption.AllDirectories);

I know this is crazy old, but in case someone wants the solution, here is what I have figured out over the past half-day looking into this. 我知道这很疯狂,但如果有人想要解决方案,这就是我在过去半天看到的这个问题。 There are several solutions out there that can get you the folder names if you give it the path to the Virtual Folder's XML location , but nothing I have seen gets you there from ::{031E4825-....} . 有几个解决方案可以为你提供文件夹名称,如果你给它提供虚拟文件夹的XML位置的路径 ,但我见过的任何东西都没有从::{031E4825-....} There was a hint in another question's answer to use the WindowsAPICodePack's KnownFoldersBrowser example. 在使用WindowsAPICodePack的KnownFoldersBrowser示例的另一个问题的答案中有一个提示 So I read through the source code in that and have come up with the following: 所以我通读了源代码,并提出了以下内容:

Here is the DialogBox I was using to get folders, and I have enabled it for AllowNonFileSystemItems, which allows Library folder selections: 这是我用来获取文件夹的DialogBox,我已经为AllowNonFileSystemItems启用了它,它允许选择库文件夹:

Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog dlg = new Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog();
dlg.Title = "Pick Folder";
dlg.IsFolderPicker = true;
dlg.InitialDirectory = Environment.SpecialFolder.Personal.ToString();  // If default setting does not exist, pick the Personal folder

dlg.AddToMostRecentlyUsedList = false;
dlg.AllowNonFileSystemItems = true;
dlg.DefaultDirectory = dlg.InitialDirectory;
dlg.EnsurePathExists = true;
dlg.EnsureFileExists = false;
dlg.EnsureReadOnly = false;
dlg.EnsureValidNames = true;
dlg.Multiselect = true;
dlg.ShowPlacesList = true;

if (dlg.ShowDialog() == Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult.Ok)
{
    foreach ( string dirname in dlg.FileNames )
    {
        var libFolders = ExpandFolderPath(dirname);
        if ( libFolders == null )
        {
            MessageBox.Show("Could not add '" + dirname + "', please try another.");
        }
        else
        {
            foreach ( string libfolder in libFolders )
            {
                DoWork(libfolder);
            }
        }
    }
}

I then iterate over allSpecialFolders to find this same ::{031E4825-...} which is the ParsingName for the SpecialFolder (yeah, probably a more elegant way). 然后我遍历allSpecialFolders以找到同样的::{031E4825-...} ,它是SpecialFolder的ParsingName(是的,可能是更优雅的方式)。 After that, use the XML reading from other solutions ( I used a CodeProject example that did the same thing ) to get the folders in that library folder: 之后,使用来自其他解决方案的XML读取( 我使用了做同样事情的CodeProject示例 )来获取该库文件夹中的文件夹:

    /// <summary>Gets the folders associated with a path</summary>
    /// <param name="libname"></param>
    /// <returns>Folder, or List of folders in library, and null if there was an issue</string></returns>
    public List<string> ExpandFolderPath(string foldername)
    {
        List<string> dirList = new List<string> { };
        // If the foldername is an existing directory, just return that
        if ( System.IO.Directory.Exists(foldername) )
        {
            dirList.Add(foldername);
            return dirList;
        }

        // It's not a directory, so check if it's a GUID Library folder
        ICollection<IKnownFolder> allSpecialFolders = Microsoft.WindowsAPICodePack.Shell.KnownFolders.All;
        Regex libguid = new Regex(@"\b([A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12})\b");
        var match = libguid.Match(foldername);
        if ( match == null )
            return null;

        string fpath = "";
        // Iterate over each folder and find the one we want
        foreach ( var folder in allSpecialFolders )
        {
            if ( folder.ParsingName == foldername )
            {
                // We now have access to the xml path
                fpath = folder.Path;
                break;
            }
        }
        if ( fpath == "" )
        {
            // Could not find it exactly, so find one with the same prefix, and
            // replace the filename
            foreach ( var folder in allSpecialFolders )
            {
                if ( folder.ParsingName.Contains(match.Groups[1].Value) )
                {
                    string sameDir = System.IO.Path.GetDirectoryName(folder.Path);
                    string newPath = System.IO.Path.Combine(sameDir, match.Groups[2].Value);
                    if ( System.IO.File.Exists(newPath) )
                        fpath = newPath;
                    break;
                }
            }
        }

        if ( fpath == "" )
            return null;

        var intFolders = GetLibraryInternalFolders(fpath);

        return intFolders.Folders.ToList();

    }


    /// <summary>
    /// Represents an instance of a Windows 7 Library
    /// </summary>
    public class Win7Library
    {
        public Win7Library()
        {

        }

        public string Name { get; set; }

        public string[] Folders { get; set; }
    }

    [DllImport("shell32.dll")]
    static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath );

    //Handles call to SHGetKnownFolderPath
    public static string getpathKnown( Guid rfid )
    {
        IntPtr pPath;
        if ( SHGetKnownFolderPath(rfid, 0, IntPtr.Zero, out pPath) == 0 )
        {
            string s = System.Runtime.InteropServices.Marshal.PtrToStringUni(pPath);
            System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath);

            return s;
        }
        else return string.Empty;
    }

    private static string ResolveStandardKnownFolders( string knowID )
    {
        if ( knowID.StartsWith("knownfolder:") )
        {
            return getpathKnown(new Guid(knowID.Substring(12)));
        }
        else
        {
            return knowID;
        }
    }

    private static Win7Library GetLibraryInternalFolders( string libraryXmlPath )
    {
        Win7Library newLibrary = new Win7Library();
        //The Name of a Library is just its file name without the extension
        newLibrary.Name = System.IO.Path.GetFileNameWithoutExtension(libraryXmlPath);

        List<string> folderpaths = new List<string>();

        System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); //* create an xml document object.
        xmlDoc.Load(libraryXmlPath); //* load the library as an xml doc.

        //Grab all the URL tags in the document, 
        //these point toward the folders contained in the library.
        System.Xml.XmlNodeList directories = xmlDoc.GetElementsByTagName("url");

        foreach ( System.Xml.XmlNode x in directories )
        {
            //Special folders use windows7 Know folders GUIDs instead 
            //of full file paths, so we have to resolve them
            folderpaths.Add(ResolveStandardKnownFolders(x.InnerText));
        }

        newLibrary.Folders = folderpaths.ToArray();
        return newLibrary;
    }

Hope this helps someone in future! 希望这有助于将来的某些人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM