从 IOException 消息中提取文件名

Extract the filename from an IOException message

我想知道如何从 IOException 消息中提取文件路径。

以下代码搜索 C:\Temp 下的子目录并检测是否有任何 *_test.xlsx 正在打开:

class Program
{
    static void Main(string[] args)
    {
        string[] files = Directory.GetFiles(@"C:\Temp", "*_test.xlsx", SearchOption.AllDirectories);

        try 
        {
            if (files == null)
            {
                Console.WriteLine("File Not Found");
            }
            else
            {
                foreach (var file in files)
                {
                    using (Stream stream = new FileStream(file, FileMode.Open))
                    {
                        // Do Nothing
                    }
                }
            }
        }
        catch (IOException ex)
        {
            Console.WriteLine(ex); // Here I'd like to show only the 'C:\Temp_folder_test.xlsx' part
        }
    }
}

如果正在打开文件,则会捕获 IOException 并显示:

System.IO.IOException: The process cannot access the file 'C:\Temp_folder_test.xlsx' because it is being used by another process.
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode)
   at CheckIfFileInUse.Program.Main(String[] args) in C:\Users\xxxxx\source\repos\CheckIfFileInUse\Program.cs:line 22

不过,我不需要完整的消息。
我只需要文件路径(在本例中,C:\Temp_folder_test.xlsx)。

我搜索并找到 this answer,但这不是我想要的。
StackTrace() frame.GetFileName() returns 程序文件路径(在我的例子中,C:\Users\xxxxx\source\repos\CheckIfFileInUse\Program.cs)。

如何从 IOException 消息中提取文件路径?

总的来说:你不能,因为不是每个 IOException 都有一个与之关联的文件名。也许 EndOfStreamException(这是一个 IOException)在不需要文件的 MemoryStream 上运行。

但是自己构建它是微不足道的。在内部级别捕获异常并抛出您自己的异常。请注意 <-- 进行更改的位置

class Program
{
    static void Main(string[] args)
    {
        string[] files = Directory.GetFiles(@"C:\Temp", "*_test.xlsx", SearchOption.AllDirectories);

        try 
        {
            if (files == null)
            {
                Console.WriteLine("File Not Found");
            }
            else
            {
                foreach (var file in files)
                {
                    try       // <--
                    {        
                        using (Stream stream = new FileStream(file, FileMode.Open))
                        {
                            // Do Nothing
                        }
                    }
                    catch (IOException ex)    // <--
                    {
                        var fileex = new IOExceptionWithFileInfo(file);
                        fileex.InnerException = ex; // Keep the original information
                        throw fileex;
                    }
                }
            }
        }
        catch (IOExceptionWithFileInfo ex)   // <--
        {
            Console.WriteLine(ex.FileName); 
        }
    }
}

OP 的 TODO 作为练习:实施 class IOExceptionWithFileInfo,派生自 Exception

在内部层面上捕捉也可以帮助您处理所有文件并构建所有有问题的文件的列表,如下所示:

var listOfErrors = new List<IOExceptionWithFileInfo>();
[...]
    catch (IOException ex)
    {
        var fileex = new IOExceptionWithFileInfo(file);
        fileex.InnerException = ex; // Keep the original information
        listOfErrors.Add(fileex);
    }
[...]
if (listOfErrors.Length > 0)
{
    // Display all of them to the user
}