示例#1
0
        /// <summary>
        /// Synchronously scanns some FS folder, filling Items list of item passed
        /// </summary>
        /// <param name="item">A PowerItem that represents an FS folder, special folder or a Windows Library</param>
        /// <param name="basePath">If item passed represents folder under Start Menu, place here corresponding 
        /// (Common or User) special folder path. Empty string otherwise. See AddSubItem for details.</param>
        /// <param name="recoursive">True to scan subdirectories.</param>
        private static void ScanFolderSync(PowerItem item, string basePath, bool recoursive)
        {
            //Obtain full fs path to current location
            var curDir = basePath + (item.Argument ?? Util.ResolveSpecialFolder(item.SpecialFolderId));
            try
            {
                Log.Raw("In: " + curDir, item.ToString());
                //Parse child directories and recoursively call the ScanFolderSync
                foreach (var directory in item.IsLibrary ? GetLibraryDirectories(curDir) : Directory.GetDirectories(curDir))
                {//Skip hidden directories
                    if ((File.GetAttributes(directory).HasFlag(FileAttributes.Hidden)))
                    {
                        Log.Raw("Skipped because item appears to be hidden");
                        continue;
                    }
                    //Otherwise add the directory item to this PowerItem
                    var subitem = AddSubItem(item, basePath, directory, true, autoExpand: !recoursive);
                    if (recoursive)
                        ScanFolderSync(subitem, basePath, true);
                }
                if (item.IsLibrary)//Since Libraries are actually files, but were already parsed as folders, we shan't continue...
                    return;
                //Proceed with files
                var resources = new Dictionary<string, string>();
                var dsktp = curDir + "\\desktop.ini";
                if (File.Exists(dsktp)) //Let's parse Desktop.ini if it exists
                {
                    using (var reader = new StreamReader(dsktp, System.Text.Encoding.Default, true))
                    {
                        string str; //TODO: rewrite!!! Currently elements located after LFN section aren't parsed!
                        while ((str = reader.ReadLine()) != null && !str.Contains("[LocalizedFileNames]"))
                        {
                            if (str.StartsWith("IconFile=") || str.StartsWith("IconResource="))
                            {
                                Util.Post(() =>
                                {
                                    item.NonCachedIcon = true;
                                    item.Icon = null;
                                });
                            }
                            if (str.StartsWith("LocalizedResourceName="))
                            {
                                item.ResourceIdString = str.Substring(22);
                            }
                        }
                        while ((str = reader.ReadLine()) != null && str.Contains("="))
                        {
                            var pair = str.Split(new[] {'='}, 2);
                            resources.Add(pair[0], pair[1]);
                        }
                    }
                }
                //Let's scan files now
                foreach (var file in Directory.GetFiles(curDir))
                {
                    if ((File.GetAttributes(file).HasFlag(FileAttributes.Hidden)))
                        continue; //Skip hidden files

                    var fn = Path.GetFileName(file);
                    var fileIsLib = (Path.GetExtension(file) ?? "")
                        .Equals(".library-ms", StringComparison.InvariantCultureIgnoreCase);
                    AddSubItem(item, basePath, file, fileIsLib,
                               fn != null && resources.ContainsKey(fn) ? resources[fn] : null,
                               fileIsLib);
                }
            }
            catch (UnauthorizedAccessException)
            {Log.Raw("UnauthorizedAccessException");} //Don't care if user is not allowed to access fileor directory or it's contents
            catch (IOException)
            {Log.Raw("IOException");} //Don't care as well if file was deleted on-the-fly, watcher will notify list
            catch (ArgumentException)
            {Log.Raw("ArgumentException");} //This usually happens to removable drives
            finally
            {  //Explicitly set marker showing that enumeration operations may occur on Items from this moment
                item.AutoExpandIsPending = false;
            }
        }
示例#2
0
 /// <summary>
 /// For the given parent PowerItem, searches child for given parameters, or creates a new one
 /// if search is unsuccessful or cannot be executed, and returns the child obtained.
 /// Thread-safe, UI-thread-safe.
 /// </summary>
 /// <param name="item">parent PowerItem, typically a filesystem folder, a Library or a special folder</param>
 /// <param name="basePath">if 'item' represents a folder under Start menu (and so has relative Argument),
 /// pass here a full-qualified path to a User or Common Start Menu (the one under which a folder is 
 /// actually located). Use PathRoot and PathCommonRoot fields to simpolify the task. Empty string otherwise.</param>
 /// <param name="fsObject">Non-virtual non-junction file system object (file or folder), not null, not empty
 /// (this is the most meaningful parameter). If you need to add a virtual item (e.g. Computer element), use
 /// direct access to proprties (parent.Items.Add(child); child.Parent=parent;) with respect to 
 /// IsAutoExpandPending property. Child search parameter.</param>
 /// <param name="isFolder">Sets child's IsFolder property to a value passed. Child search parameter.</param>
 /// <param name="resourceId">Localized resource identifier in a standard "[@]Library,-resId[__varData*]" form.
 /// Null by default. Since 0.4 can be set to a required string directly, but in this case it is recommended to 
 /// set FriendlyName explicitly</param>
 /// <param name="autoExpand">True to mark the item as deferred-expandable. This means it's children won't be enumerated
 /// synchronously and will be loaded automatically later, when requested by the user. False by default.</param>
 private static PowerItem AddSubItem(PowerItem item, string basePath, string fsObject, bool isFolder, string resourceId = null, bool autoExpand = false)
 {
     var argStr = fsObject.Substring(basePath.Length); //Expected relative argument in case of Start Menu item
     Log.Raw("In: " + fsObject, item.ToString());
     var child = autoExpand || item.AutoExpandIsPending //Searching...
             ? null
             : item.Items.FirstOrDefault(i =>
                         string.Equals(i.Argument, argStr, StringComparison.CurrentCultureIgnoreCase)
                         && i.IsFolder == isFolder);
     Log.Raw("child: " + (child == null ? "null" : child.ToString()), item.ToString());
     if(child == null) //Generating...
     {
         child = new PowerItem
                     {
                         Argument = argStr,
                         Parent = item,
                         IsFolder = isFolder,
                         ResourceIdString = resourceId,
                         AutoExpand = autoExpand
                     };
         Util.Send(() => item.Items.Add(child)); //Synchronously add item in UI thread
     }
     return child;
 }