为什么我的程序循环?

时间:2014-01-15 08:48:12

标签: c# loops attributes readonly

在我的实习过程中,我一直在研究一个用C#编写的简单的控制台程序(我是一个编程新手,所以这花了我几天才做出来)。

整个代码可以在这里找到:

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

基本上它的作用是用户在控制台窗口中写入目录的路径,程序扫描其中的所有文件以获取只读属性。

没有它的文件,获取它,并将它们的名称添加到列表中(changedFiles)。

一旦扫描完所有文件,它就会停止,并列出它所更改的文件以及它不能的文件(例如,当前正在使用的文件无法更改)。

现在我正在努力使它在扫描了1.000个文件后,它会问:“你想继续吗?”。如果用户按下Y,它会继续,并在成功后再次询问1.000以上(并且这一直持续到所有文件都被扫描,然后程序继续,并列出更改的文件等)。

问题是,如果用户按下N(表示否),它就会循环播放。坐在那里再问:“你想继续吗?”。

我该怎么改变?如何让我的程序在这些1.000文件之后停止(如果用户回答“否”),但仍然列出它已经更改的文件?

2 个答案:

答案 0 :(得分:2)

这里的问题是您正在使用递归,并且您可能在要取消的位置处有多个级别的递归。只是取消最里面的递归不会取消外部调用。

要解决此问题,您可以从递归方法返回bool值以查看它是否被取消,如下所示:

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.
    }
}

答案 1 :(得分:0)

您可以使用break语句来解决此问题

if(answer.Key == ConsoleKey.Y)
{
    maxcheck = maxcheck + 1000;
}                
if(answer.Key ==ConsoleKey.N)
{
    return;
}