简体   繁体   English

为什么我的程序循环?

[英]Why does my program loop?

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

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 ). 没有它的文件,获取它,并将它们的名称添加到列表( changedFiles )。

Once it has scanned all files, it stops, and lists the files it changed, and those it couldn't (eg 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?". 现在我试图让它在扫描完1.000个文件之后再问:“你想继续吗?”。 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). 如果用户按下Y,它会继续,并在成功后再发送1.000个文件后再次询问(并且这一直持续到所有文件都被扫描完毕,然后程序继续,并列出更改的文件等)。

The issue is, that if the user presses N (for no), it just loops. 问题是,如果用户按下N(表示否),它就会循环。 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? 如何让我的程序在这些1.000文件之后停止(如果用户回答“否”),但仍然列出它已更改的文件?

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: 要解决此问题,您可以从递归方法返回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.
    }
}

You can use break statement to solve this problem 您可以使用break语句来解决此问题

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM