couldn't scan folder with whitespace and special chars like $

fihovi

Member
Joined
Nov 26, 2019
Messages
7
Programming Experience
Beginner
Hello,

I want to scan drive in my app, but I can't scan $Recyclebin and folders with whitespace in name.

I can't find any resolution for these errors, I tried to find NuGet packages for resolving this issues for me.
I'm using System.IO

Program.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace FileHandler
{
    class Program
    {
        private static void Main(string[] args)
        {
            GetAllFilesFromFolder(@"E:\", true);
        }

        private static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders)
        {
            Queue<string> folders = new Queue<string>();
            List<string> folderCount = new List<string>();
            List<string> files = new List<string>();
            folders.Enqueue(root);
            while (folders.Count != 0){
                string currentFolder = folders.Dequeue();
                try {
                    string[] filesInCurrent = Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly);
                    files.AddRange(filesInCurrent);
                }
                catch
                {
                    //Console.WriteLine("Error: " + currentFolder);
                    // Do Nothing
                }
                try{
                    if (searchSubfolders){
                        string[] foldersInCurrent = Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly);
                        foreach (string _current in foldersInCurrent){
                            folderCount.AddRange(foldersInCurrent);
                            folders.Enqueue(_current);
                        }
                    }
                }
                catch{
                    Console.WriteLine("Error: " + currentFolder);
                    // Do Nothing
                }
            }
            countFiles = files.Count();

            List<string> distinct = folderCount.Distinct().ToList(); //Remove Duplicates from scan
            Console.WriteLine("Number of folders AFTER: " + distinct.Count);
            Console.WriteLine("Number of files is: " + files.Count());
       
            Console.ReadLine();
            return files;
        }
    }
}

Thanks a lot
 
Last edited:
Even though I used EnumerateDirectories() above, GetDirectories() also fails/works the same way.
 
Also another data point: Letting .NET Framework 4.8 do the recursion itself works correctly, but that provides cold comfort when you actually want to walk the directories yourself.
C#:
static void RecursivelyListDirectories(string root)
{
    Console.WriteLine($"Enumerating directories starting at: {root}");
    try
    {
        foreach (var dir in Directory.GetDirectories(root, "*", SearchOption.AllDirectories))
            Console.WriteLine($"Working on '{dir}'");
    }

    catch (Exception ex)
    {
        Console.Error.WriteLine(ex);
    }
}
 
There aren't really a lot of options, and If I have read your topic properly, you mentioned Clickonce. You won't be able to use a elevated rights with ClickOnce, so disable ClickOnce. Right click your project properties and hit security and disable the click once security setting. Then add a app.manafest file and edit it so asInvoker is replaced with : <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />. After you decide how to handle this issue with the white space, you may get access denied errors for some of the root files/folders in C:\ or any other drives you search, but we can deal with that next in a separate topic if you need to.

Your only options that I can see are; Prevention of paths using 0160 (Best option)! Can you prevent the folders from being named like that?

Most likely not, and I wouldn't advise renaming any files or folders, unless your application is responsible for creating them. (Assuming your app is some kind of backup program.) You could also record the paths which contain 0160 and correct them in your application without touching the original files. And If your app is meant to backup every file, you could simply replace 0160 and fix the path by calling trim(), and then somehow mark that path as having needing to be renamed with 0160 should you ever need to restore it with its original name.

You could use a dictionary or an external file to keep track of files/folder paths as you perceived them with 0160 spacing, and with the trimmed version (non 0160) version. Assuming your application creates a backup or makes records of all file/folders paths. And if you ever needed to restore a file/directory, you would simply check your file to see if the file/folder needing replacing was ever formally named using 0160 so you could replicate the correct path to restore on the OS. Does that make sense?

Alternative option to renaming is skipping those files and folders. You could adapt your foreach statement with Linq to check if the file or folder contains 0160. What the below will do is check if the path does not contain a path with 0160 and skip it if it does :
C#:
foreach (string _current in foldersInCurrent.Where(s => !s.Contains(@" ")))
Simply use .Where(s => !s.Contains(@" ")) wherever you want to exclude or handle paths containing 0160.
Obviously I am sure you're aware you can also call Trim() on the path to remove any such whitespaces etc. You should also be constructing your foreach with DirInfo /FileInfo to try avoid issues like this. Use :
foreach (DirectoryInfo _current etc... this will mean rewriting some of your code.
Using a simple string is not a good use of object orientated code. You can avail of better functionality from using Dirinfo/FileInfo instead, and work on your paths from there. Hope these suggestions help.
 
Just to add, it is 4AM in the morning, and I am a little overworked after a long day, so I hope that made sense, and if there is something that Isn't clear, I will follow up with you tomorrow with any questions you might have. (if I can wake up.)

Good night.
 
As a quick reminder, the non-breaking space (160) is only an issue when it is the trailing character for .NET Framework 4.6.1 and higher. If it (and other whitespace characters) are not the trailing characters, there is not an issue. Another way to bypass the issue is just to go to .NET Core 3.0.
 
Last edited:
As far as I can tell, '$' is not a special character. I think the issue you are running is specific to the recycle bin where some of the sub-directories are ACL'd such it denies you access. As mentioned above, to get into those directories, you'll need to be running as administrator.
 
As far as I can tell, '$' is not a special character. I think the issue you are running is specific to the recycle bin where some of the sub-directories are ACL'd such it denies you access. As mentioned above, to get into those directories, you'll need to be running as administrator.
Yeah, that is correct. I did overlook fact, that I did not have access to sub-dirs. So at the time, while I was confused why it won't take (160), I did not realize that it was permission thing.
 
Back
Top Bottom