与打开 FileStream 相关的异常混乱

发布于 2025-01-08 05:12:04 字数 498 浏览 1 评论 0原文

好的,所以我在很多地方搜索了这个问题的答案,但如果我错过了一些明显的东西,我愿意接受任何链接。

我有兴趣在用户尝试打开特定文件时向用户生成合理的错误消息,但无论出于何种原因程序无法访问该文件。我想区分以下情况:

  • 该文件被另一个进程锁定,因此该进程无法写入该文件。
  • 用户没有写入文件的适当访问权限(例如,他们的用户权限,如 Windows 资源管理器中文件的“属性”屏幕中所示,没有授予用户写入权限)
  • 该文件需要“提升”权限访问该文件。

我正在使用 FileStream 对象。我查看了 用于实例化 FileStream 的 msdn 文档,它是我根本不清楚哪个异常对上述内容执行什么操作,以及如何区分它们。我承认我的 Windows 编程经验有限,所以我可能会遗漏一些明显的东西。如果是这样,我很抱歉。

Ok, so I have searched in many places for the answer to this question, but I'm open to any links if I missed something obvious.

I am interested in producing reasonable error messages to the user when they attempt to open a particular file, but for whatever reason the program cannot access that file. I would like to distinguish between the following cases:

  • The file was locked by another process such that this process cannot write to it.
  • The user does not have the appropriate access privileges to write to the file (as in, their user permissions, as seen in the Properties screen for a file in Windows explorer, do not give the user write permission)
  • The file requires "elevated" permission to access the file.

I am using a FileStream object. I have looked at the msdn documentation for instantiating a FileStream, and it is not at all clear to me which Exception does what for the above, and how to distinguish between them. I admit that my experience with Windows programming is limited, so I may be missing something obvious. My apologies if so.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

俏︾媚 2025-01-15 05:12:04

您可以执行以下操作:

1) 在尝试访问您的文件之前,您可以测试您是否有权访问该文件。从这个SO线程开始,如果用户拥有Write权限(即右键单击文件时 -> 属性 -> 安全性)。这涵盖了您关于不当访问权限的观点(2)(请注意,可能有比下面的代码更强大/防错的方法来获取此信息):

public static bool HasWritePermissionOnFile(string path)
{
    bool writeAllow = false;
    bool writeDeny = false;

    FileSecurity accessControlList = File.GetAccessControl(path);
    if (accessControlList == null)
    {
        return false;
    }

    var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier));
    if (accessRules == null)
    {
        return false;
    }

    foreach (FileSystemAccessRule rule in accessRules)
    {
        if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write)
        {
            continue;
        }

        if (rule.AccessControlType == AccessControlType.Allow)
        {
            writeAllow = true;
        }
        else if (rule.AccessControlType == AccessControlType.Deny)
        {
            writeDeny = true;
        }
    }

    return writeAllow && !writeDeny;
}

2)请尝试实例化您的 FileStream ,并捕获异常:

try
{
    string file = "...";
    bool hasWritePermission = HasWritePermissionOnFile(file);
    using (FileStream fs = new FileStream(file, FileMode.Open))
    {
    }
}
catch (UnauthorizedAccessException ex)
{
    // Insert some logic here
}
catch (FileNotFoundException ex)
{
    // Insert some logic here
}
catch (IOException ex)
{
    // Insert some logic here
}

在您的情况 (3) 中(文件需要提升),会引发 UnauthorizedAccessException

在您的情况(1)(文件被另一个进程锁定)中,会抛出 IOException 。然后,您可以检查异常的 HRESULT 以获取更多详细信息:

catch (IOException ex)
{
    // Gets the HRESULT
    int hresult = Marshal.GetHRForException(ex);

    // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
    // for system error code
    switch (hresult & 0x0000FFFF)
    {
        case 32:    //ERROR_SHARING_VIOLATION
            Console.WriteLine("File is in use by another process");
            break;
    }
}

现在您应该能够区分 3 个用例。

Here's what you could do:

1) You could test if you have rights to access to the file before trying to access to your file. From this SO thread, here is a method that should return true if user has Write rights (i.e. when right-clicking on a file -> property -> security). This covers your point (2) for unappropriated access privileges (do note that there is maybe something more robust/error-proof to get this information than the code below):

public static bool HasWritePermissionOnFile(string path)
{
    bool writeAllow = false;
    bool writeDeny = false;

    FileSecurity accessControlList = File.GetAccessControl(path);
    if (accessControlList == null)
    {
        return false;
    }

    var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier));
    if (accessRules == null)
    {
        return false;
    }

    foreach (FileSystemAccessRule rule in accessRules)
    {
        if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write)
        {
            continue;
        }

        if (rule.AccessControlType == AccessControlType.Allow)
        {
            writeAllow = true;
        }
        else if (rule.AccessControlType == AccessControlType.Deny)
        {
            writeDeny = true;
        }
    }

    return writeAllow && !writeDeny;
}

2) Do try to instantiate your FileStream, and catch exceptions:

try
{
    string file = "...";
    bool hasWritePermission = HasWritePermissionOnFile(file);
    using (FileStream fs = new FileStream(file, FileMode.Open))
    {
    }
}
catch (UnauthorizedAccessException ex)
{
    // Insert some logic here
}
catch (FileNotFoundException ex)
{
    // Insert some logic here
}
catch (IOException ex)
{
    // Insert some logic here
}

In your case (3) (file requires elevation), UnauthorizedAccessException is thrown.

In your case (1) (file is locked by another process), IOException is thrown. You can then check the HRESULT of the exception for more details:

catch (IOException ex)
{
    // Gets the HRESULT
    int hresult = Marshal.GetHRForException(ex);

    // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
    // for system error code
    switch (hresult & 0x0000FFFF)
    {
        case 32:    //ERROR_SHARING_VIOLATION
            Console.WriteLine("File is in use by another process");
            break;
    }
}

Now you should be able to distinguish your 3 use cases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文