Ну разве можно в мелкософте сделать что-то хорошо? Ты ж вызовешь функцию и ничего интересного — она просто сделает свою работу. А что если... наложить туда грабель?!
Все мы любим создавать небольшую помоечку на диске (к примеру, распаковать архив и автоматически обработать). Такую помоечку обычно создают в папке с каким-нть GUID'ом и потом одним махом прибивают. Ха! Не тут-то было! Если ты думаешь, что вызвал "Directory.Delete(path, true)" и гора с плеч — хрен там, потому как при любом "readonly" файле функция весело падает с UnauthorizedAccessException! Казалось бы, причём тут "неавторизованный"?? Под админом я имею полное право удалить любую фигню, но даже если вы запустите свою прогу с админскими правами, она точно так же упадёт. А ТО НЕ ДАЙ БОГ(!!!!!!!!!) ты, имбецильный бедолага (а в мелкософте вас всех такими считают), удалишь readonly файл! Он же так важен....
Короче, вместо действительно удобной функции "Удалить каталог и всю тряхомудию внутри", тебе дают всего лишь "удалятор каталога и подкаталогов, но ТОЛЬКО при условии, что они все пустые". Вот вам и грабельки, шоп погромиздить нескучно было! "Дебилы, б****!" (ц) Лавров
Я думал, что никому нахрен не нужный readonly атрибут достался нам со времён убогого DOSа, когда каждый дебил творил в меру своей фантазии. Но нет... мелкософт чтёт заплесневелые традиции и даже имея развитую систему прав NTFS, продолжает идиотничать с этими атавизмами.
Разумеется, я накарябал хелпер для адекватного удаления каталога. Выложу сюда, чтобы вы не тратили бесценное время бизнес задач на мелкомягких идиотов.
Если где там чо ошибаюсь — чур говном не кидаться, приучайтесь к цивилизованным манерам.
/// <summary>Proper deletion function, which doesn't moan 'folder does not exist'.</summary>public static void DeleteDir(string path)
{
if (!Directory.Exists(path)) return;
DeleteSubfiles(path);
Directory.Delete(path, true);
}
/// <summary>Delete files in a given folder and all subfolders.</summary>
/// <remarks>It's preparation for Directory.Delete()</remarks>static void DeleteSubfiles(string path)
{
var dir = new DirectoryInfo(path);
foreach (FileInfo fi in dir.EnumerateFiles())
DeleteFile(fi.FullName);
foreach (var di in dir.EnumerateDirectories())
DeleteSubfiles(di.FullName);
}
public static void DeleteFile(string path)
{
try {
File.Delete(path);
} catch(UnauthorizedAccessException) {
File.SetAttributes(path, FileAttributes.Archive);
File.Delete(path);// don't catch here Exception - it means smth serious
}
}
UPD
Особо вы оцените "if (!Directory.Exists(path)) return;" Ведь как же так — пришли удалять каталог, а его нет — НЕПОРЯДОК, Алярм, свистать всех наверх — у нас "труп" исчез! Вот зачем такая проверка внутри Directory.Delete??? Если мне важно, чтобы каталог существовал, для этого есть отдельный вызов Exist. Но если я удаляю каталог, какой смысл верещать, что его нет?? Ну мало ли, может это автогенерированное имя и я удаляю каталог "на авось"! Вот такие тупорылые проверки всего и вся и приводят к мегабайтам "говнокода", который не решает бизнес-задачи, а лавирует меж мелкомягких граблей.
Здравствуйте, Kolesiki, Вы писали:
K>Все мы любим создавать небольшую помоечку на диске (к примеру, распаковать архив и автоматически обработать). Такую помоечку обычно создают в папке с каким-нть GUID'ом и потом одним махом прибивают. Ха! Не тут-то было! Если ты думаешь, что вызвал "Directory.Delete(path, true)" и гора с плеч — хрен там, потому как при любом "readonly" файле функция весело падает с UnauthorizedAccessException!
А зачем ты в своей помоечке отмечаешь файлы readonly?
S>>А зачем ты в своей помоечке отмечаешь файлы readonly?
F>Это не он — в архиве могут быть.
Если кто-то другой поставил read-only, то всё работает, как надо. Кто-то другой хотел, чтобы ты подумал, прежде чем стирать этот ценный файл, раз он потрудился поставить read-only.
Здравствуйте, Kolesiki, Вы писали:
K>Все мы любим создавать небольшую помоечку на диске (к примеру, распаковать архив и автоматически обработать)
Нет. Всегда старался этого избегать.
Временные файлы создавать приходится только если предполагается работа с внешней программой или ещё какие-то объективные причины.
Ну, там отчёт генерируется, который потом в Word'е должен открыться и т.п.
Если же автоматическая обработка внутри моей же программы, то я лучше в MemoryStream засуну файл, чем сначала буду его на диск писать, потом считывать так же в память, потом удалять файл.
В разы дольше, сложнее, ещё и свет выключат у пользователя до удаления программой временных файлов и останутся они мёртвым грузом лежать.
Здравствуйте, vaa, Вы писали:
vaa>Здравствуйте, Kolesiki, Вы писали:
K>> File.SetAttributes(path, FileAttributes.Archive);
vaa>Чё грить, корявая реализация. Еще кажись на скрытых файлах падает. vaa>нужон N[ew]IO или Apache FileUtils.
Ты без "кажись", если упадёт — скажи, а так пердеть из кустов не надо. Понятно, что есть исключительные случаи, всё не предусмотришь. Но на r/o хотя бы не спотыкаемся! А главное — ОДНА функция удаляет весь каталог.
Здравствуйте, Sharowarsheg, Вы писали:
S>Здравствуйте, flаt, Вы писали:
S>>>А зачем ты в своей помоечке отмечаешь файлы readonly?
F>>Это не он — в архиве могут быть.
S>Если кто-то другой поставил read-only, то всё работает, как надо. Кто-то другой хотел, чтобы ты подумал, прежде чем стирать этот ценный файл, раз он потрудился поставить read-only.
Дело в том, что если я удаляю ВЕСЬ каталог, не имеет значения, кто там среди мусора решил жить вечно. Для таких вопросов существует СИСТЕМА ПРАВ (админ, юзер и т.п.). А приказ системе "удали каталог и всю ерунду, что внутри" обязан работать без кривляний "у меня вот тут выживший". readonly — ну когда ты САМ лично ставил этот атрибут? Или разбирался с файлами "ну что же среди тысяч файлов этот один ридонли? Дай-ка я у автора спрошу!". Ведь не делал так никогда? Потому что это атавизм из DOS и он как-то вообще не прижился — ставят его чисто от нехрен делать. Например, Git.
Здравствуйте, karbofos42, Вы писали:
K>Здравствуйте, Kolesiki, Вы писали:
K>>Все мы любим создавать небольшую помоечку на диске (к примеру, распаковать архив и автоматически обработать)
K>Нет. Всегда старался этого избегать. K>Временные файлы создавать приходится только если....
Узколобо мыслишь, родной! Тут ключевая мысль вообще не про архив — про удаление одним залпом.
K>Ты без "кажись", если упадёт — скажи, а так пердеть из кустов не надо. Проверил что ли?
Вообще, конечно, странное решение удалять без предупреждения.
Здравствуйте, Kolesiki, Вы писали:
K>Узколобо мыслишь, родной! Тут ключевая мысль вообще не про архив — про удаление одним залпом.
Это ты узко мыслишь и борешься с последствиями.
Может просто не нужно у пользователя на компе непонятными файлами сорить и не будет такой задачи/проблемы в принципе?
Здравствуйте, vaa, Вы писали:
vaa>Вообще, конечно, странное решение удалять без предупреждения.
Ну да, всегда надо предупреждать! А на сервере, где производится удаление, сажается на цепь индус, который смотрит 24/7 на экран и жмёт "Yes, I'm sure!".
Здравствуйте, karbofos42, Вы писали:
K>Здравствуйте, Kolesiki, Вы писали:
K>>Узколобо мыслишь, родной! Тут ключевая мысль вообще не про архив — про удаление одним залпом.
K>Это ты узко мыслишь и борешься с последствиями. K>Может просто не нужно у пользователя на компе непонятными файлами сорить и не будет такой задачи/проблемы в принципе?
Говорю же, узколобый тут ты. Который даже на секунду не допускает мысль, что файлы могут быть вообще не мои! Но удалять — надо. Такое в студенческую голову не приходило? Карбофос, ну вот серьёзно, что ты делаешь в ИТ с таким мышлением?? Ключевая мысль — удаление "проблемных" каталогов и желательно за один вызов. Поэтому там и написана ПРОСТЫНЯ КОДА, что M$ там насрала грабель.
K>Ну да, всегда надо предупреждать! А на сервере, где производится удаление, сажается на цепь индус, который смотрит 24/7 на экран и жмёт "Yes, I'm sure!".
K>Особо вы оцените "if (!Directory.Exists(path)) return;" Ведь как же так — пришли удалять каталог, а его нет — НЕПОРЯДОК, Алярм, свистать всех наверх — у нас "труп" исчез! Вот зачем такая проверка внутри Directory.Delete??? Если мне важно, чтобы каталог существовал, для этого есть отдельный вызов Exist. Но если я удаляю каталог, какой смысл верещать, что его нет?? Ну мало ли, может это автогенерированное имя и я удаляю каталог "на авось"! Вот такие тупорылые проверки всего и вся и приводят к мегабайтам "говнокода", который не решает бизнес-задачи, а лавирует меж мелкомягких граблей.
Здравствуйте, vaa, Вы писали:
vaa>Здравствуйте, Kolesiki, Вы писали:
K>>Ну да, всегда надо предупреждать! А на сервере, где производится удаление, сажается на цепь индус, который смотрит 24/7 на экран и жмёт "Yes, I'm sure!".
vaa>7 раз отмерь, 1 отрежь (c)
Скажешь это начальнику, когда он тебе член оттянет и отрежет! (за то, что занимаешься ненужными подтверждениями там, где всё должно работать на автомате)
Помню, в приснопамятные времена была такая ошибка в BIOS:
Здравствуйте, Kolesiki, Вы писали:
K>Здравствуйте, vaa, Вы писали:
vaa>>Здравствуйте, Kolesiki, Вы писали:
K>>>Ну да, всегда надо предупреждать! А на сервере, где производится удаление, сажается на цепь индус, который смотрит 24/7 на экран и жмёт "Yes, I'm sure!".
vaa>>7 раз отмерь, 1 отрежь (c)
K>Скажешь это начальнику, когда он тебе член оттянет и отрежет! (за то, что занимаешься ненужными подтверждениями там, где всё должно работать на автомате)
Эх, малыш! Все еще под начальником ходишь? Ну ничего, терпи!
Здравствуйте, Kolesiki, Вы писали:
S>>А зачем ты в своей помоечке отмечаешь файлы readonly?
K>А кто тебе сказал, что я? Архив тоже может содержать такой атрибут. А может и не архив! К примеру, я получил граблями, удаляя мусор за Git'ом.
Если не ты, то значит, это был я. И правильно, нефига удалять файл, на который я поставил атрибут "только для чтения". Я зря его ставил чтоле.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Kolesiki, Вы писали:
K>>Разумеется, я накарябал хелпер для адекватного удаления каталога.
НС>Сбрасывать атрибуты лучше не при удалении, а при распаковке.
Лучше и там и там, а то в процессе существования файлов у них кто-то может аттрибуты поменять и тогда не удалится ничего.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Kolesiki, Вы писали:
K>>Разумеется, я накарябал хелпер для адекватного удаления каталога.
НС>Сбрасывать атрибуты лучше не при удалении, а при распаковке.
Архив — чисто пример "помойки, которую надо удалить". В конкретно моём случае не удалялся мусор после Git'а (его .git/* ) — можно подумать, ОДИН ридонли файл имеет какой-то смысл....
НС>>>Сбрасывать атрибуты лучше не при удалении, а при распаковке. Y>>Почему?
НС>Потому что может бомбануть еще в каком нибудь коде.
Если приложение создаёт файлы чисто для себя, то ему не стоит беспокоиться о чужом неведомом коде. Свой код надо оттестировать. А косяки чужих программ всё равно не предусмотришь. Качественный код от атрибутов файлов бомбить не должен. А некачественный может и на вполне легальной ситуации бомбануть.
Сбрасывать атрибуты при распаковке — это лишний код и затраты времени, которые могут быть вообще лишними. Например, чистка файлового мусора может выполняться внешней утилитой, которая надёжно обрабатывает все эти ситуации.
А при удалении я бы просто вызывал Directory.Delete(path, true) и ловил исключение. И только в случае исключения нужно делать перебор всех файлов со сбросом атрибута ReadOnly. И тогда снова Directory.Delete(path, true). А если и тут не смогла, то значит уже не смогла.
Здравствуйте, yenik, Вы писали:
Y>А при удалении я бы просто вызывал Directory.Delete(path, true) и ловил исключение. И только в случае исключения нужно делать перебор всех файлов со сбросом атрибута ReadOnly.
Проблема только в том что мы делаем допущение о readonly, исключение об этом ничего не говорит, тогда уже надо сначала убедится, что действительно ReadOnly стал причиной исключения.
Y>>А при удалении я бы просто вызывал Directory.Delete(path, true) и ловил исключение. И только в случае исключения нужно делать перебор всех файлов со сбросом атрибута ReadOnly.
vaa>Проблема только в том что мы делаем допущение о readonly, исключение об этом ничего не говорит, тогда уже надо сначала убедится, что действительно ReadOnly стал причиной исключения.
Да, делаем известное нам допущение. Можно для надёжности вообще все атрибуты сбросить, всё равно файлу не жить. А причин исключения может быть много, обрабатываем только то, что понимаем, предвидим и можем обработать.
vaa>PS vaa>Проверил в java удаляются ro-файлы.
А в .NET вот так. По-простому форсированное удаление не сделать.
Здравствуйте, vaa, Вы писали:
vaa>Проблема только в том что мы делаем допущение о readonly, исключение об этом ничего не говорит, тогда уже надо сначала убедится, что действительно ReadOnly стал причиной исключения.
Так надо не допущение делать, а документацию смотреть.
В исходном сообщении был DirectoryInfo и там такой метод Delete, который кидает UnauthorizedAccessException именно для read-only.
Если же мы используем Directory, то у него другой метод Delete и он уже кидает IOException в случает read-only.
Здравствуйте, yenik, Вы писали:
Y>А при удалении я бы просто вызывал Directory.Delete(path, true) и ловил исключение
Ну если совсем скучно — лови! Только зачем усложнять код? Больше задач нет, кроме как плясать вокруг M$ костылей? Снял "проблемные" атрибуты и удалил — вот и вся недолга.
Y>>А при удалении я бы просто вызывал Directory.Delete(path, true) и ловил исключение
K>Ну если совсем скучно — лови! Только зачем усложнять код? Больше задач нет, кроме как плясать вокруг M$ костылей? Снял "проблемные" атрибуты и удалил — вот и вся недолга.
Чтобы снять "проблемные" атрибуты, нужно перебрать файлы. С большой вероятностью файлов с такими атрибутами не найдётся, и эта работа окажется ненужной. Только углеродный след зря останется.
Поэтому перебор файлов со снятием атрибутов следует рассматривать как План Б, если по-простому удалить не получится.