2014-01-15 80 views
0

在我的实习过程中,我一直在用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个文件后停止(如果用户回答否),但是仍然列出它已更改的文件?

+1

请提供与您问题相关的问题本身 –

+0

好的代码,对不起。上次我在这里问一个问题时,我被要求将我的代码复制到一个pastebin。 – JFBN

+1

使用'Environment.Exit(0);'http://msdn.microsoft.com/en-us/library/system.environment.exit(v=vs.110).aspx – Chandan

回答

2

这里的问题是,你正在使用递归,你可能是递归的几个层次深的地步,你想取消。只要取消最内层递归就不会取消外层调用。

为了解决这个问题,可以从递归方法返回一个布尔值,看它是否被取消了,就像这样:

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

这给了我错误:'ConsoleApplication5.Program.ProcessDirectory(string,System.Collections.Generic.List ,System.COllections.Generic。列表)':并非所有的代码路径都返回一个值。' – JFBN

+0

@JFBN尝试最新版本... –

+0

非常感谢。这适用于我。我不知道bool的价值是什么,但它似乎工作。 – JFBN

0

你可以用break语句来解决这个问题

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

我试过这样做: 'if(answer.Key == ConsoleKey.Y) { maxcheck = maxcheck + 1000; } if(answer.Key == ConsoleKey.N) { break; }' 这并没有解决它。 – JFBN

+0

即使答案是N,你是否想在foreach循环下执行? – Nil23

+0

即使答案为N,我也希望它执行“SetAllFilesAsReadOnly”。尝试在超过1.000个文件的文件夹上运行代码,然后按Y键。您可以看到它如何很好地列出所有已更改的文件。即使按N,我也不想让它继续下去。 – JFBN