Question

I've been working on a simple console program written with C# the past couple of days at my internship (I'm a programming newb, so this took me days to make yes).

The entire code can be found here:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ConsoleApplication5
{
    class Program
    {
        static int maxcheck = 1000;
        static int stopsearch = 0;

        public static void ProcessDirectory(string targetDirectory, List<string> foundFiles, List<string> errorFiles) 
        {
        try
        {
            // Process the list of files found in the directory. 
            string [] fileEntries = Directory.GetFiles(targetDirectory);
            foreach(string fileName in fileEntries)
            {
                if (foundFiles.Count() >= maxcheck)
                {
                    ConsoleKeyInfo answer;
                    Console.Clear();
                    Console.SetCursorPosition(2, 2);
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine("{0} files has been searched.",maxcheck);
                    Console.Write("  Do you wish to continue (Y/N): ");
                    Console.ForegroundColor = ConsoleColor.Green;
                    answer = Console.ReadKey();
                    Console.Clear();
                    if(answer.Key == ConsoleKey.Y)
                    {
                        maxcheck = maxcheck + 1000;
                    }
                    if(answer.Key ==ConsoleKey.N)
                    {
                        stopsearch = stopsearch + 1;
                    }
                }
                else
                {
                    ProcessFile(fileName, foundFiles, errorFiles);
                }
            }

            // Recurse into subdirectories of this directory. 
            string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
            foreach(string subdirectory in subdirectoryEntries)
                ProcessDirectory(subdirectory, foundFiles, errorFiles);
        }
        catch(Exception)
        {
            errorFiles.Add(targetDirectory);
        }    

        // Insert logic for processing found files here. 
        public static void ProcessFile(string fileName, List<string> changedFiles, List<string> errorfiles) 
        {
            //Console.WriteLine("Processed file '{0}'.", path);
            try
            {
                System.IO.FileAttributes attr = System.IO.File.GetAttributes(fileName);
                if ((attr & System.IO.FileAttributes.ReadOnly) == 0)
                {
                    attr = attr | System.IO.FileAttributes.ReadOnly;

                    System.IO.File.SetAttributes(fileName, attr);
                    changedFiles.Add(fileName);
                }
            }
            catch (UnauthorizedAccessException)
            {
                errorfiles.Add(fileName);
            }
            catch (InvalidOperationException)
            {
                errorfiles.Add(fileName);
            }
            catch (Exception)
            {
                errorfiles.Add(fileName);
            }
        }

        static void SetAllFilesAsReadOnly(string rootPath)
        {
            Console.ForegroundColor = ConsoleColor.White;

            List<string> errorfiles = new List<string>();
            List<string> changedfiles = new List<string>();

            if (stopsearch < 1)
            {
                ProcessDirectory(rootPath, changedfiles, errorfiles);
            }

            if (changedfiles.Count() > 0)
            {
                Console.SetCursorPosition(2, 2);
                Console.Write("Press any key to see the files that was changed");
                Console.ForegroundColor = ConsoleColor.Green;
                Console.ReadKey();
                Console.Clear();
                Console.SetCursorPosition(2, 2);

                foreach (string file in changedfiles)
                {
                    Console.WriteLine("  " + file);
                }

                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("");
                Console.WriteLine("  Write-protection was set on {0} files.", changedfiles.Count());
            }
            else
            {
                Console.SetCursorPosition(2, 2);
                Console.Write("Write-protection was not changed on any files.");
            }
            Console.ForegroundColor = ConsoleColor.Black;
            Console.ReadKey();

            if (errorfiles.Count() > 0)
            {
                Console.WriteLine("");
                Console.WriteLine("  These are the files that was NOT changed:");

                foreach (string file in errorfiles)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("  " + file);
                }

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("");
                Console.WriteLine("  Write-protection could not be set on {0} files.", errorfiles.Count());
                Console.ReadKey();
            }
        }

        static void Main(string[] args)
        {
            string pathstring;

            if ((args.Count() == 0) || (args[0] == ""))
            {
                Console.SetCursorPosition(2, 2);
                Console.Write("Please enter the path of the directory you wish to check: ");
                Console.ForegroundColor = ConsoleColor.Green;
                pathstring = Console.ReadLine();
            }
            else
            {
                pathstring = args[0];
            }

            Console.Clear();
            SetAllFilesAsReadOnly(pathstring);    
        }
    }
}

Basically what it does is that the user writes a path of a directory in the console window, and the program scans all files in there for read-only attribute.

The files that does not have it, get it, and their name is added to a list (changedFiles).

Once it has scanned all files, it stops, and lists the files it changed, and those it couldn't (e.g. files that are currently in use cannot be changed).

Now I'm trying to make it so that after it has scanned 1.000 files, it asks: "Do you wish to continue?". If the user press Y, it continues, and asks Again after 1.000 more files, successfully (and this goes on until all files has been scanned, then the program continues, and lists the files changed etc).

The issue is, that if the user presses N (for no), it just loops. Sits there asking again: "Do you wish to continue?".

How can I change this? How can I make my program just stop after those 1.000 files (if the user answered NO), but still have it list the files it has changed?

Was it helpful?

Solution

The problem here is that you are using recursion, and you might be several levels of recursion deep at the point where you want to cancel. Just cancelling the innermost recursion won't cancel the outer calls.

To solve this, you can return a bool value from the recursive method to see if it was cancelled, like so:

public static bool ProcessDirectory(string targetDirectory, List<string> foundFiles, List<string> errorFiles)
{
    try
    {
        // Process the list of files found in the directory.
        string [] fileEntries = Directory.GetFiles(targetDirectory);
        foreach (string fileName in fileEntries)
        {
            if (foundFiles.Count() >= maxcheck)
            {

                ConsoleKeyInfo answer;
                Console.Clear();
                Console.SetCursorPosition(2, 2);
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("{0} files has been searched.", maxcheck);
                Console.Write("  Do you wish to continue (Y/N): ");
                Console.ForegroundColor = ConsoleColor.Green;
                answer = Console.ReadKey();
                Console.Clear();

                if (answer.Key == ConsoleKey.Y)
                {
                    maxcheck = maxcheck + 1000;
                }
                if (answer.Key == ConsoleKey.N)
                {
                    return false;
                }
            }
            else
            {
                ProcessFile(fileName, foundFiles, errorFiles);
            }
        }

        // Recurse into subdirectories of this directory.
        string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);

        foreach (string subdirectory in subdirectoryEntries)
            if (!ProcessDirectory(subdirectory, foundFiles, errorFiles))
                return false;

        return true;
    }

    catch (Exception)
    {
        errorFiles.Add(targetDirectory);
        return false; // or true if you want to continue in the face of exceptions.
    }
}

OTHER TIPS

You can use break statement to solve this problem

if(answer.Key == ConsoleKey.Y)
{
    maxcheck = maxcheck + 1000;
}                
if(answer.Key ==ConsoleKey.N)
{
    return;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top