【问题标题】:Removing read only attribute on a directory using C#使用 C# 删除目录上的只读属性
【发布时间】:2011-04-21 11:33:48
【问题描述】:

我使用以下代码 sn-p 成功地删除了文件的只读属性:

在 main.cs 中

FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();

foreach (var childFolderOrFile in sqlParentFileSystemInfo)
{
    RemoveReadOnlyFlag(childFolderOrFile);
}

private static void RemoveReadOnlyFlag(FileSystemInfo fileSystemInfo)
{
    fileSystemInfo.Attributes = FileAttributes.Normal;
    var di = fileSystemInfo as DirectoryInfo;

    if (di != null)
    {
        foreach (var dirInfo in di.GetFileSystemInfos())
            RemoveReadOnlyFlag(dirInfo);
    }
}

很遗憾,这不适用于文件夹。运行代码后,当我转到文件夹时,右键单击并执行属性,这是我看到的:

只读标志仍然被检查,尽管它从它下面的文件中删除了它。这会导致进程无法删除此文件夹。当我手动删除标志并重新运行该进程(一个 bat 文件)时,它能够删除该文件(所以我知道这不是 bat 文件的问题)

如何在 C# 中删除此标志?

【问题讨论】:

    标签: c# .net .net-3.5 c#-4.0


    【解决方案1】:

    您还可以执行以下操作以递归清除指定父目录中所有目录和文件的只读(和存档等):

    private void ClearReadOnly(DirectoryInfo parentDirectory)
    {
        if(parentDirectory != null)
        {
            parentDirectory.Attributes = FileAttributes.Normal;
            foreach (FileInfo fi in parentDirectory.GetFiles())
            {
                fi.Attributes = FileAttributes.Normal;
            }
            foreach (DirectoryInfo di in parentDirectory.GetDirectories())
            {
                ClearReadOnly(di);
            }
        }
    }
    

    因此,您可以这样称呼它:

    public void Main()
    {
        DirectoryInfo parentDirectoryInfo = new DirectoryInfo(@"c:\test");
        ClearReadOnly(parentDirectoryInfo);
    }
    

    【讨论】:

      【解决方案2】:

      尝试使用 DirectoryInfo 代替 FileInfo

      DirectoryInfo di = new DirectoryInfo(@"c:\temp\content");
      di.Attributes = FileAttributes.Normal;
      

      清理文件的属性-

      foreach (string fileName in System.IO.Directory.GetFiles(@"c:\temp\content"))
      {
          System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
          fileInfo.Attributes = FileAttributes.Normal;
      }
      

      【讨论】:

      • 这似乎不适用于目录。我仍然看到带有只读集的属性。
      【解决方案3】:

      对话框只是以一种相当奇怪的方式工作。无论 ReadOnly 属性的状态如何,它始终以您在屏幕截图中看到的方式显示。复选框处于“未确定”状态。您必须单击它并清除或选中它以使其执行其操作。尽管有提示文本(但不是复选框旁边的提示),它只更改目录中文件的 ReadOnly 属性,而不是目录本身。

      使用 attrib 命令行命令查看实际情况。您的代码很可能会失败,因为该目录包含设置了 ReadOnly 属性的文件。你必须迭代它们。

      【讨论】:

        【解决方案4】:

        Windows 中目录上的只读标志实际上是用词不当。该文件夹不使用只读标志。问题将与定制有关。 Windows 使用该标志来识别文件夹上有自定义项。

        这是一个旧帖子,有一个问题正在日落,但是,我认为人们可能仍然会遇到它,因为当你点击它时它会很烦人。

        Microsoft's Explanation

        【讨论】:

          【解决方案5】:

          用于从目录和文件中递归删除只读属性的 IEnumerable / Lambda 解决方案:

          new DirectoryInfo(@"some\test\path").GetDirectories("*", SearchOption.AllDirectories).ToList().ForEach(
              di => {
                  di.Attributes &= ~FileAttributes.ReadOnly;
                  di.GetFiles("*", SearchOption.TopDirectoryOnly).ToList().ForEach(fi => fi.IsReadOnly = false);
              }
          );
          

          【讨论】:

            【解决方案6】:

            在原dirInfo上设置Attributes属性:

            dirInfo.Attributes = FileAttributes.Normal;
            
            FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();
            
            foreach (var childFolderOrFile in sqlParentFileSystemInfo)
            {
                RemoveReadOnlyFlag(childFolderOrFile);
            }
            

            【讨论】:

            • 不起作用。仍然可以看到处于“未确定”状态的带有只读标志的属性
            【解决方案7】:

            以防万一以后发生这种情况......

            在我之前发布的所有其他答案要么是错误的,要么使用了不必要的递归。

            首先,windows 属性对话框中的“只读”复选框总是有文件夹的三态标记。这是因为文件夹本身不是只读的,但里面的文件可以。

            如果您想为所有文件设置/取消设置只读标志。你可以这样做:

            void SetReadOnlyFlagForAllFiles(DirectoryInfo directory, bool isReadOnly)
            {
                // Iterate over ALL files using "*" wildcard and choosing to search all directories.
                foreach(FileInfo File in directory.GetFiles("*", SearchOption.All.Directories))
                {
                    // Set flag.
                    File.IsReadOnly = isReadOnly;
                }
            }
            

            【讨论】:

            • 当目录是只读的,你不能从目录中添加/删除文件时,你会怎么做?这就是 OP 的要求。
            • @Dunk 不是被问到的。而且您仍然有一个奇怪的想法,即“目录”具有只读属性……它没有。您是否尝试过任何代码? OPs 代码确实有效,但这只是因为您可以将 DirectoryInfo 转换为 FileInfo。它真正做的只是设置所有文件的属性,自己测试。目录不能设置为 FileAttibutes.Normal 或 .ReadOnly,它始终是 .Directory。正如我所说,资源管理器总是显示目录的中间状态。 BAT文件也可以以任何方式删除“只读”目录,因此更有可能在他的PC上锁定其他东西。
            【解决方案8】:

            我看到@DotnetDude 在 cmets 中说男人的解决方案不起作用。在我看来,这是因为人们没有提到需要使用 File.SetAttributes 方法来应用新属性。

            【讨论】:

              【解决方案9】:

              这可能直接相关,也可能不直接相关,但在您的情况下,根本问题可能是由底层文件引起的。例如,我在尝试删除目录时遇到了这个问题:

              System.IO.Directory.Delete(someDirectory, true)
              

              这会导致“访问路径 'blah' 被拒绝”。为了解决这个潜在问题,我删除了子文件的只读属性,然后能够删除父目录。就我而言,我使用的是 powershell,因此您可以使用 .NET 等效项。

              dir -r $PrePackageDirectory |% {if ($_.PSIsContainer -ne $true){$_.IsReadOnly = $false}}
              

              【讨论】:

                【解决方案10】:
                Shell("net share sharefolder=c:\sharefolder/GRANT:Everyone,FULL")
                
                
                Shell("net share sharefolder= c:\sharefolder/G:Everyone:F /SPEC B")
                
                
                Shell("Icacls C:\sharefolder/grant Everyone:F /inheritance:e /T")
                
                
                Shell("attrib -r +s C:\\sharefolder\*.* /s /d", AppWinStyle.Hide)
                

                此代码对我有用.. 与具有读写权限的每个人共享一个文件夹

                【讨论】:

                • @Kiquenet, Shell 不是一个类;这是一个 VB.NET 函数。在 C# 中,您可以使用 Process.Start() 来实现类似的行为(即启动另一个进程。)查看 ProcessProcessStartInfo 类的文档以获取更多信息。不过,出于关闭只读属性的目的,就像最初的问题一样,我建议使用 Mark Avenius 的答案,而不是开始一个新进程。
                猜你喜欢
                • 2011-01-19
                • 1970-01-01
                • 2010-10-27
                • 1970-01-01
                • 2022-01-10
                • 2014-08-20
                • 2014-05-07
                • 2010-12-25
                相关资源
                最近更新 更多