Удаление атрибута только для чтения в каталоге с использованием С#

Я успешно смог удалить атрибут только для чтения в файле, используя следующий фрагмент кода:

В 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);
    }
}

К сожалению, это не работает в папках. После запуска кода, когда я иду в папку, щелкните правой кнопкой мыши и сделаю свойства, вот что я вижу:

alt text

Флаг только для чтения по-прежнему проверяется, хотя он удаляет его из файлов под ним. Это заставляет процесс не удалять эту папку. Когда я вручную удаляю флаг и повторно запускаю процесс (файл bat), он может удалить файл (поэтому я знаю, что это не проблема с файлом bat)

Как удалить этот флаг в С#?

Ответы

Ответ 1

Вы также можете сделать что-то вроде следующего, чтобы рекурсивно очистить readonly (и архив и т.д.) для всех каталогов и файлов в указанном родительском каталоге:

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;

Очистить attrbutes на файлах -

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 только на файлы в каталоге, а не на сам каталог.

Используйте команду командной строки атрибута, чтобы увидеть, что происходит. По всей вероятности, ваш код не работает, потому что каталог содержит файлы, у которых есть атрибут ReadOnly. Вам придется перебирать их.

Ответ 4

Флаг только для чтения в каталогах в Windows на самом деле является неправильным. В папке не используется флаг только для чтения. Проблема будет связана с настройкой. Флаг используется Windows для определения того, что в папке есть настройки.

Это старая статья с проблемой, которая заходит на закат, но фигурные люди все еще могут столкнуться с ней, так как это очень раздражает, когда вы ее нажимаете.

Пояснение корпорации Майкрософт

Ответ 5

Задайте свойство Attributes в исходном dirInfo:

dirInfo.Attributes = FileAttributes.Normal;

FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();

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

Ответ 6

На всякий случай, если это произойдет позже...

ВСЕ другие ответы, опубликованные до моего, либо ошибочны, либо используют ненужную рекурсию.

Прежде всего, флажок "Только для чтения" в диалоговом окне свойств окон всегда имеет маркер tri-state для папок. Это связано с тем, что сама папка не читается, но файлы внутри могут быть.

Если вы хотите установить/отключить флаг только для чтения для ВСЕХ файлов. вы можете сделать это просто следующим образом:

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;
    }
}

Ответ 7

IEnumerable/Lambda решение для рекурсивного удаления атрибута readonly из каталогов и файлов:

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);
    }
);

Ответ 8

Я вижу, что @DotnetDude сказал в комментариях, что решения парней не работают. На мой взгляд, это происходит потому, что ребята не упомянули, что нужно использовать метод File.SetAttributes для применения новых атрибутов.

Ответ 9

Это может быть или не быть напрямую связано, но проблема с корнем в вашем случае может быть вызвана базовыми файлами. Например, я столкнулся с этой проблемой, пытаясь удалить каталог:

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

В результате "Доступ к пути" бла "отрицается". Чтобы устранить эту проблему, я удалил атрибут "только для чтения" в подфайлах и смог удалить родительский каталог. В моем случае я использовал 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)

этот код работает для меня.. для обмена папкой с каждым с правами на чтение и запись