3

我发现我可以写入(例如,将文件复制到)只读目录。也就是说,带有...Attributes = FileAttributes.ReadOnly.I 的目录甚至可以更改其名称。我发现唯一不能做的就是删除它。这真的是唯一ReadOnly能阻止的事情吗?

编辑:

这是代码:(目录为空。)

(new DirectoryInfo(path)).Attributes = FileAttributes.ReadOnly;
Directory.Delete(path);

它抛出一个Access to the path 'c:\... is denied.异常。

但是改成之后ReadOnlyNormal可以正常使用了。

那么, a能阻止什么,什么不能阻止ReadOnly(当然,以编程方式。不是:通过 Windows 资源管理器。)

编辑2:

我收到了链接到文档的答案,说ReadOnly在目录上不尊重,这可能.Net是删除失败的原因。所以我将改写这个问题:“使用 C#/.Net 时,只读对目录有何影响?”。

4

3 回答 3

1

正如 Damien_The_Unbeliever 所提到的,如果我们查看 FILE_ATTRIBUTE_READONLY 的 Win32 API,它会提到:

目录不支持此属性。

另请参阅:http: //go.microsoft.com/fwlink/p/ ?linkid=125896

因此,您似乎确实可以使用 win32 或资源管理器简单地删除此类目录。然而,.NET 似乎会在删除目录之前检查它们的标志。例如,您可以在 Directory.Delete 上使用 DotPeek 或 Reflector 来查看这一点。这就是导致您的“访问被拒绝”错误的原因。

编辑:

我对此进行了更详细的研究,似乎不是 .NET 引发了拒绝访问错误。考虑以下测试代码:

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ReadOnlyDirTest
{
   class Program
   {
      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false)]
      extern static bool RemoveDirectory(string path);

      static String CreateTempDir()
      {
         String tempDir;
         do
         {
            tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         } while (Directory.Exists(tempDir));

         Directory.CreateDirectory(tempDir);
         return tempDir;
      }

      static void Main(string[] args)
      {
         var tempDir = CreateTempDir();

         // Set readonly.
         new DirectoryInfo(tempDir).Attributes |= FileAttributes.ReadOnly;

         try
         {
            Directory.Delete(tempDir);
         }
         catch (Exception e)
         {
            Console.WriteLine("Directory.Delete: " + e.Message);
         }

         if (!Directory.Exists(tempDir))
            Console.WriteLine("Directory.Delete deleted directory");

         try
         {
            if (!RemoveDirectory(tempDir))
               Console.WriteLine("RemoveDirectory Win32 error: " + Marshal.GetLastWin32Error().ToString());
         }
         catch (Exception e)
         {
            Console.WriteLine("RemoveDirectory: " + e.Message);
         }

         if (!Directory.Exists(tempDir))
            Console.WriteLine("RemoveDirectory deleted directory");

         // Try again without readonly, for both.
         tempDir = CreateTempDir();
         Directory.Delete(tempDir);
         Console.WriteLine("Directory.Delete: removed normal directory");

         tempDir = CreateTempDir();
         if (!RemoveDirectory(tempDir))
            Console.WriteLine("RemoveDirectory: could not remove directory, error is " + Marshal.GetLastWin32Error().ToString());
         else
            Console.WriteLine("RemoveDirectory: removed normal directory");

         Console.ReadLine();
      }
   }
}

在我的机器上运行它(win 7)我得到以下输出:

    Directory.Delete:拒绝访问路径“C:\...\Local\Temp\a4udkkax.jcy”。
    删除目录 Win32 错误:5
    Directory.Delete:删除正常目录
    RemoveDirectory:删除正常目录

我们看到我们得到错误代码 5,根据http://msdn.microsoft.com/en-gb/library/windows/desktop/ms681382(v=vs.85).aspx,这是一个拒绝访问错误。

然后我只能假设资源管理器在删除目录之前取消设置只读属性,这当然很容易完成。该命令rmdir还删除标记为只读的目录。

由于文档表明 readonly 标志不应该在目录上得到尊重(即使它似乎在 Win 7 中),我不会依赖这种行为。换句话说,我不会依靠 readonly 来阻止任何事情。

于 2012-11-02T11:27:01.523 回答
1

文件系统中目录条目的只读属性的用处有限。大多数用户都希望目录中的所有文件也变为只读。但这不是 NTFS 的工作方式,属性仅适用于文件系统对象本身,而不是像安全属性那样“继承”。

请注意资源管理器如何修改属性在其 UI 中的工作方式,当您打开它时,它会执行任何用户期望的操作,它将所有文件设为只读,而不是在目录本身上设置属性。

但是,是的,它确实有效,它可以防止修改目录对象本身。因此,如果您在代码中打开它,那么确实会阻止删除目录。就像处理文件一样。

于 2012-11-02T12:37:47.940 回答
1

它没有。剥去足够多的层,你会发现用来改变目录属性的函数是SetFileAttributes

设置文件或目录的属性。

并注意:

FILE_ATTRIBUTE_READONLY 1 (0x1) 只读文件。应用程序可以读取该文件,但不能写入或删除它。该属性在目录上不受支持。有关详细信息,请参阅“在 Windows Server 2003、Windows XP 或 Windows Vista 中,您无法查看或更改文件夹的只读或系统属性。

(我的重点)

于 2012-11-02T11:19:25.637 回答