【问题标题】:How can I browse a local virtual folder in C#?如何在 C# 中浏览本地虚拟文件夹?
【发布时间】:2012-06-22 10:02:23
【问题描述】:

在我的 C# 程序中,我必须浏览目录。 所以我使用方法 System.IO.Directory.GetFiles(directory) 当目录是像“C:\Program File”这样的真实目录但它是虚拟目录(例如:librairie 目录)时,它工作得很好,目录值看起来像这样:“::{031E4825-7B94-4dc3- B131-E946B44C8DD5}\Pictures.library-ms" 不知道怎么浏览。

【问题讨论】:

    标签: c# virtual directory


    【解决方案1】:

    我知道这已经很老了,但如果有人想要解决方案,这就是我在过去半天的调查中发现的。有几种解决方案可以让你得到the folder names if you give it the path to the Virtual Folder's XML location,但我没有看到任何东西可以让你从::{031E4825-....} 那里得到你。有一个hint in another question's answer 可以使用 WindowsAPICodePack 的 KnownFoldersBrowser 示例。所以我通读了其中的源代码并提出了以下内容:

    这是我用来获取文件夹的对话框,我已为 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);
                }
            }
        }
    }
    

    然后我遍历allSpecialFolders 以找到相同的::{031E4825-...},它是SpecialFolder 的ParsingName(是的,可能是一种更优雅的方式)。之后,使用从其他解决方案 (I used a CodeProject example that did the same thing) 读取的 XML 来获取该库文件夹中的文件夹:

        /// <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;
        }
    

    希望这对将来的人有所帮助!

    【讨论】:

    【解决方案2】:

    你需要把虚拟路径翻译成物理路径,试试:

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

    您可能想阅读DirectoryInfo。如果这没有用,试试这个吧:

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

    【讨论】:

    • 什么是“Server.MapPath”?我可以为 MapPath 找到的 MSDN 引用都在 System.Web 中... OP 没有指定这是一个 Web 应用程序,此外,从描述来看,它看起来一点也不像 Web。
    • OP did not specify this was a web application。他没有具体说明它不是……
    • 你是对的,他没有,但他给出的具体例子是一个系统库的虚拟路径,这与网络有关......
    • 其实我尝试浏览本地虚拟文件夹
    • @user1343257 你从哪里得到这个虚拟路径?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2013-01-17
    • 2014-04-27
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多