我正在尝试编写一个小程序,递归遍历用户指定文件夹(及其所有子文件夹)中包含的所有文件。程序应该检查每个文件的大小,如果它匹配用户定义的值,将它们的完整路径(File.FullName)复制到我在程序的唯一形式上设置的文本框控件。 麻烦的是,由于程序的预期用途(使用从外部驱动器上的损坏分区恢复的文件和文件夹),路径长度通常远远超过最大路径长度限制。为了略微避免这种情况,我决定使用Win32命令行函数“subst”将用户选择的起始目录映射到虚拟驱动器。
private void button1_Click(object sender, EventArgs e)
{
if (txtboxSizeFilter.Text != "")//code will execute only if a size filter has been provided by the user
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
List<char> driveLetters = new List<char>(26); // Allocate space for alphabet
for (int i = 65; i < 91; i++) // increment from ASCII values for A-Z
{
driveLetters.Add(Convert.ToChar(i)); // Add uppercase letters to possible drive letters
}
foreach (string drive in Directory.GetLogicalDrives())
{
driveLetters.Remove(drive[0]); // removed used drive letters from possible drive letters
}
GlobalVars.Drive = driveLetters[0].ToString() + ":"; //gets the next available drive letter to be used as the virtual drive and adds a convenient ":" at the end
string command = "subst " + GlobalVars.Drive + " " + "\"" + folderBrowserDialog1.SelectedPath.ToString() + "\""; //command to be passed to "cmd". Ex. Content= subst J: "C:\users\someuser\somelongnamefolder\some longer name folder with spaces"
System.Diagnostics.Process.Start("cmd.exe", @"/c " + command);//launches the command prompt and initiates subst. This section has been tested and works fine.
DirectoryInfo DI = new DirectoryInfo(GlobalVars.Drive);//here i start at the drive letter that points to the desired directory.
foreach (var fi in DI.EnumerateFiles("*", SearchOption.AllDirectories))//searches for any file in all dirs. THE EXCEPTION "DirectoryNotFound" OBJECT OF THIS QUESTION IS THROWN EXACTLY HERE.
{
try //I need this because I might throw a PathTooLongException despite my use of subst
{
if (fi.Length == Convert.ToInt64(txtboxSizeFilter.Text))//if the size of the file is = to target size then I add the full path name to the textbox along with its actual size (for debug purposes only).
{
txtboxResults2Confirm.Text = txtboxResults2Confirm.Text + fi.FullName.ToString() + "_" + fi.Length.ToString() + Environment.NewLine;
}
}
catch (PathTooLongException)//if the path is too long, indicate it with the codeword "SKIP"
{
txtboxResults2Confirm.Text = txtboxResults2Confirm.Text + "SKIP" + Environment.NewLine;
}
}
btnConfirm.Enabled = true;//enables the other button on the form that will actually delete the files.
}
}
else
{
MessageBox.Show("INPUT SIZE FIRST!");
}
}
如注释和磁贴中所指定,第二个foreach语句中出现未处理的DirectoryNotFound异常(如IDE,Microsoft Visual Studio Ultimate 2013所示)。执行一步一步的调试表明foreach循环实际上工作了一段时间,然后“随机”抛出异常。我能够验证它是否通过根目录中的所有文件和至少第一个子目录的大部分文件完全没有任何问题(因为大量的文件/子目录我无法精确定位到哪里失败发生)。该错误表明找不到的目录是根目录(因此,请遵循注释中的示例:“无法找到J:\”)。我试图跟随第一个捕获另一个来处理DirectoryNotFound异常无济于事,这是有道理的,因为异常似乎直接源于foreach语句。我还尝试将整个foreach语句包装成try-catch框架而没有任何运气。最后,摆脱整个“subst”部分并仅使用用户选择的路径不会产生这样的错误。 我的问题是,为什么抛出异常?为什么我无法以任何方式处理它?是否有另一种解决此问题的方法可以确保避免使用DirectoryNotFound异常?
答案 0 :(得分:1)
Process.Start
正是这样做的:它启动一个新的进程(有自己的主线程等),当你原始程序中的下一行代码执行时,它可能完成也可能不完成。解决此问题的几种方法:a)调用DefineDosDevice
,这意味着“subst”命令在当前程序线程中运行,或者b)抓取管道到cmd进程并监听它完成。两者都是中等难度,挑选你的毒药。
当然,您遇到的异常是因为subst
命令在枚举(但未消除别名)目录的代码执行时没有及时完成。