C# 如何轻松检查 .NET 中的文件是否被拒绝访问?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/265953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:30:52  来源:igfitidea点击:

how can you easily check if access is denied for a file in .NET?

c#.netfile-access

提问by Horas

Basically, I would like to check if I have rights to open the file before I actually try to open it; I do not want to use a try/catch for this check unless I have to. Is there a file access property I can check before hand?

基本上,我想在实际尝试打开文件之前检查我是否有权打开文件;除非必须,否则我不想使用 try/catch 进行此检查。是否有我可以事先检查的文件访问属性?

回答by Joel Coehoorn

I have done this countless times in the past, and nearly every time I've done it I was wrong to even make the attempt.

过去我已经做过无数次了,而且几乎每次我都这样做了,我什至尝试都错了。

File permissions (even file existence) are volatile— they can change at any time. Thanks to Murphy's Law this especiallyincludes the brief period between when you check the file and when you try to open it. A change is even more likely if you're in an area where you know you need to check first. Yet strangely enough it will never happen in your testing or development environments, which tend to be fairly static. This makes the problem difficult to track down later and makes it easy for this kind of bug to make it into production.

文件权限(甚至文件存在)是不稳定的——它们可以随时更改。由于墨菲定律,这尤其包括您检查文件和尝试打开文件之间的短暂时间。如果您所在的区域您知道需要先检查,则更改的可能性更大。然而奇怪的是,它永远不会发生在您的测试或开发环境中,这些环境往往是相当静态的。这使得以后难以追踪问题,并使这种错误很容易进入生产环境。

What this means is that you still have to be able to handle the exception if file permissions or existence are bad, in spite of your check. Exception handling code is required, whether or not you check for the permissions of the file in advance. Exception handling code provides allof the functionality of existence or permissions checks. Additionally, while exception handlers like this are known to be slow, it's important to remember that disk i/o is even slower... a lotslower... and calling the .Exists() function or checking permissions will force an additional trip out the file system.

这意味着,尽管您进行了检查,但如果文件权限或存在性不好,您仍然必须能够处理异常。异常处理代码是必需的,无论您是否事先检查了文件的权限。异常处理代码提供存在或权限检查的所有功能。此外,虽然异常处理这样的被称为是缓慢的,但要记住,磁盘I / O更慢......一个很重要很多慢...并调用.Exists()函数或检查权限将强制额外的行程出文件系统。

In summary, an initial check before trying to open the file is both redundant and wasteful. There is no additional benefit over exception handling, it will actually hurt, not help, your performance, it adds cost in terms of more code that must be maintained, and it can introduce subtle bugs into your code. There is just no upside at all to doing the initial check. Instead, the correct thing here is to just try to open the file and put your effort into a good exception handler if it fails. The same is true even if you're just checking whether or not the file exists. This reasoning applies to anyvolatile resource.

总之,在尝试打开文件之前进行初始检查既多余又浪费。异常处理没有额外的好处,它实际上会损害而不是帮助您的性能,它会增加必须维护的更多代码的成本,并且它可能会在您的代码中引入细微的错误。进行初步检查根本没有任何好处。相反,这里正确的做法是尝试打开文件并在失败时将精力投入到一个好的异常处理程序中。即使您只是检查文件是否存在,也是如此。这种推理适用于任何易失性资源。

回答by Robert Rossney

First, what Joel Coehoorn said.

首先,乔尔·科霍恩 (Joel Coehoorn) 所说的话。

Also: you should examine the assumptions that underly your desire to avoid using try/catch unless you have to. The typical reason for avoiding logic that depends on exceptions (creating Exceptionobjects performs poorly) probably isn't relevant to code that's opening a file.

另外:除非必须,否则您应该检查避免使用 try/catch 的愿望背后的假设。避免依赖于异常的逻辑(创建Exception对象性能不佳)的典型原因可能与打开文件的代码无关。

I suppose that if you're writing a method that populates a List<FileStream>by opening every file in a directory subtree and you expected large numbers of them to be inaccessible you might want to check file permissions before trying to open a file so that you didn't get too many exceptions. But you'd still handle the exception. Also, there's probably something terribly wrong with your program's design if you're writing a method that does this.

我想,如果您正在编写一个List<FileStream>通过打开目录子树中的每个文件来填充 a 的方法,并且您希望它们中的大量无法访问,您可能需要在尝试打开文件之前检查文件权限,以便您没有得到太多的异常。但是您仍然会处理异常。此外,如果您正在编写执行此操作的方法,则您的程序设计可能存在严重错误。

回答by Ash

Quick tip for anyone else coming here with a similar problem:

给遇到类似问题的其他人的快速提示:

Watch out for web synchronization apps such as DropBox. I just spent 2 hours thinking the "using" statement (Dispose pattern) is broken in .NET.

注意 DropBox 等网络同步应用程序。我只是花了 2 个小时认为“使用”语句(处置模式)在 .NET 中被破坏了。

I eventually realised that Dropbox is continually reading and writing files in the background, in order to sync them.

我最终意识到 Dropbox 在后台不断读取和写入文件,以便同步它们。

Guess where my Visual Studio Projects folder is located? Inside the "My Dropbox" folder of course.

猜猜我的 Visual Studio Projects 文件夹在哪里?当然,在“My Dropbox”文件夹中。

Therefore as I ran my application in Debug mode, the files it was reading and writing were also continually being accessed by DropBox to be synched with the DropBox server. This caused the locking/access conflicts.

因此,当我在调试模式下运行我的应用程序时,它正在读取和写入的文件也不断被 DropBox 访问以与 DropBox 服务器同步。这导致了锁定/访问冲突。

So at least I now know that I need to a more robust File Open function (ie TryOpen() that will make multiple attempts). I am surprised it's not already a built-in part of the framework.

所以至少我现在知道我需要一个更强大的文件打开函数(即 TryOpen() 将进行多次尝试)。我很惊讶它还不是框架的内置部分。

[Update]

[更新]

Here's my helper function:

这是我的辅助功能:

/// <summary>
/// Tries to open a file, with a user defined number of attempt and Sleep delay between attempts.
/// </summary>
/// <param name="filePath">The full file path to be opened</param>
/// <param name="fileMode">Required file mode enum value(see MSDN documentation)</param>
/// <param name="fileAccess">Required file access enum value(see MSDN documentation)</param>
/// <param name="fileShare">Required file share enum value(see MSDN documentation)</param>
/// <param name="maximumAttempts">The total number of attempts to make (multiply by attemptWaitMS for the maximum time the function with Try opening the file)</param>
/// <param name="attemptWaitMS">The delay in Milliseconds between each attempt.</param>
/// <returns>A valid FileStream object for the opened file, or null if the File could not be opened after the required attempts</returns>
public FileStream TryOpen(string filePath, FileMode fileMode, FileAccess fileAccess,FileShare fileShare,int maximumAttempts,int attemptWaitMS)
{
    FileStream fs = null;
    int attempts = 0;

    // Loop allow multiple attempts
    while (true)
    {
        try
        {
            fs = File.Open(filePath, fileMode, fileAccess, fileShare);

            //If we get here, the File.Open succeeded, so break out of the loop and return the FileStream
            break;
        }
        catch (IOException ioEx)
        {
            // IOExcception is thrown if the file is in use by another process.

            // Check the numbere of attempts to ensure no infinite loop
            attempts++;
            if (attempts > maximumAttempts)
            {
                // Too many attempts,cannot Open File, break and return null 
                fs = null;
                break;
            }
            else
            {
                // Sleep before making another attempt
                Thread.Sleep(attemptWaitMS);

            }

        }

    }
    // Reutn the filestream, may be valid or null
    return fs;
}

回答by Rudzitis

public static FileStream GetFileStream(String filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileShare, ref int attempts, int attemptWaitInMilliseconds)
{            
    try
    {
         return File.Open(filePath, fileMode, fileAccess, fileShare);
    }
    catch (UnauthorizedAccessException unauthorizedAccessException)
    {
        if (attempts <= 0)
        {
            throw unauthorizedAccessException;
        }
        else
        {
            Thread.Sleep(attemptWaitInMilliseconds);
            attempts--;
            return GetFileStream(filePath, fileMode, fileAccess, fileShare, ref attempts, attemptWaitInMilliseconds);
        }
    }
}

回答by dj shahar

Here is the solution you are looking for

这是您正在寻找的解决方案

var fileIOPermission = new FileIOPermission(FileIOPermissionAccess.Read,
                                            System.Security.AccessControl.AccessControlActions.View,
                                            MyPath);

if (fileIOPermission.AllFiles == FileIOPermissionAccess.Read)
{
    // Do your thing here...
}

this creates a new permission of read based on view for path of all files then checks if it's equal to file access read.

这会根据所有文件的路径视图创建一个新的读取权限,然后检查它是否等于文件访问读取。

回答by Omid Matouri

public static bool IsFileLocked(string filename)
        {
            bool Locked = false;
            try
            {
                FileStream fs =
                    File.Open(filename, FileMode.OpenOrCreate,
                    FileAccess.ReadWrite, FileShare.None);
                fs.Close();
            }
            catch (IOException ex)
            {
                Locked = true;
            }
            return Locked;
        }