Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Ошибка доступа к файлу


Автор: Experimenter 10.9.2007, 08:03
Доброго здоровья, уважаемые!

Наверняка многим попадалось такое исключение при записи из стрима в файл:
Цитата

The process cannot access the file 'c:\myfile.txt' because it is being used by another process.

Так вот вопрос: как сделать проверку, что файл никем не занят для предупреждения этого исключения? Что-то подсказывает мне, что нужно юзать System.Security.AccessControl.FileSecurity, но пока для меня это темный лес, ткните меня носом пожалуйста, куда смотреть нужно. Или может, ссылка есть хорошая.

Заранее благодарен!

Автор: tdebugger 10.9.2007, 09:11
А что мешает осуществить проверку открыванием файла на чтение\запись с помощью классов IO ?

Автор: Experimenter 10.9.2007, 10:51
tdebugger, 
Цитата

А что мешает осуществить проверку открыванием файла на чтение\запись с помощью классов IO ? 

Каким образом, если не секрет? Получил ошибку на запись, значит файл занят? Так неинтересно... Хочу заранее знать, юзается файл каким-то процессом, или нет. Причем я не говорю, что обязательно FileSecurity нужно использовать, потому что еще сам не знаю, что в этом классе есть. Любой вариант подойдет, кроме обработки исключений ввода-вывода.

Автор: Pit_Bul 10.9.2007, 12:24
Так твое исключение и есть проверка на доступность файла, смотри как работает

Код

try
{
//здесь открываешь файл
}
catch(Exeption e)
{
//при недоступности файла здесь вылетант исключение
//e.Message.ToSring() - это текст исключения
}
finaly
{
//здесь код который должен выполниться в любом случае
}


Автор: Experimenter 10.9.2007, 15:02
Pit_Bul, блин елы-палы, знаю я, как исключения работают! Но если мне нужно именно одно-единственное исключение (когда файл занят) оттуда выдрать и обработать его, мне что, для этого текст ошибки парсить что ли? В классе IOException различных исключений выше крыши. Вот есть же метод File.Exists(), к примеру. Наверняка и для моей темы что-нибудь существует... Целое пространство имен AccessControl для чего-нибудь, да создали же...

Автор: Wanderer2019 10.9.2007, 15:20
Насколько я понимаю для тебя существует именно Exception. Ничего парсить не надо. У каждой ошибки существует свой номер, по нему и ориентируйся. 
AccessControl существует для того, чтобы работать со списком безопасности.

Автор: Experimenter 11.9.2007, 06:35
Wanderer2019, 
Цитата

У каждой ошибки существует свой номер, по нему и ориентируйся.

И где его взять тогда, этот номер?

Автор: Experimenter 11.9.2007, 07:16
Цитата

И где его взять тогда, этот номер?

Все, сам нашел:
Цитата

IOException uses the HRESULT COR_E_IO which has the value 0x80131620.

НО:
Цитата

IOException is the base class for exceptions thrown while accessing information using streams, files and directories.

The Base Class Library includes the following types, each of which is a derived class of IOException : 
DirectoryNotFoundException 
EndOfStreamException 
FileNotFoundException 
FileLoadException 
PathTooLongException 

Where appropriate, use these types instead of IOException.

Тогда еще придется исключать номера всех наследуемых эксепшенов.

Какие еще будут предложения?

Автор: mr.DUDA 11.9.2007, 11:43
Проверить существование файла (File.Exists), потом открыть файл в режиме FileShare.ReadWrite и если кинет любое исключение - значит файл эксклюзивно открыт на запись в другом процессе.

Автор: tol05 11.9.2007, 13:57
Experimenter, у тебя вылетает  system.UnauthorizedAccessException 
его и отлавливай

Автор: Experimenter 11.9.2007, 14:52
mr.DUDA, вот это уже более конструктивно, я тоже об этом думал, сначала отмёл, так как без исключений хотел сделать. Но видимо, без них никак не обойдешь этот камень.

Добавлено через 5 минут и 5 секунд
tol05, неавторизованный доступ тут ни при чем, такое исключение возникает, когда к примеру поток хочет в нерасшаренный файл данные записать, а в это время другой поток что-то пишет уже. Когда тот, что занимал файл, отвалился, тот, что хотел записывать, получает доступ.

Автор: Experimenter 12.9.2007, 06:38
Странно, данное исключение получаем даже в следующем коде:
Код

    FileStream fs1 = new FileStream("abcd.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
    FileStream fs2 = new FileStream("abcd.txt", FileMode.Open, FileAccess.Read);

Есть же разрешение на совместный доступ???!!!

Автор: mr.DUDA 12.9.2007, 09:37
Так работает:
Код
FileStream fs1 = new FileStream(@"abcd.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
FileStream fs2 = new FileStream(@"abcd.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);


Почему - надо почитать матчасть о правах доступа к файлам (не в .NET -- там мало инфы, а в Platform SDK).

Автор: tol05 12.9.2007, 09:53
и даже так работает
Код

FileStream fs1 = new FileStream("abcd.txt", FileMode.Open, FileAccess.ReadWrite);
FileStream fs2 = new FileStream("abcd.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

матчасть ни при чем. Достаточно логически поразмышлять... smile

При создании первого потока Experimenter заявлял, что готов на совместный доступ к файлу. А кому это интересно? Никто этот файл не шарит еще.
А вот при создании второго потока - нужно сказать, что готовы на совместный доступ. Потому как на момент создания второго потока может оказаться, что файл уже кто-то юзает. (А так оно и есть).

P.S. если и второй поток нужен на чтение-запись, тогда да, нужно оба потока шарить... (вариант mr.DUDA)

Автор: Experimenter 12.9.2007, 10:41
В общем-то шаред ресурсы как раз и не нужны, это случайно выявилось.
Пошарив по System.IO небезызвестной и очень популярной программой, получаем, что все явные и неявные создания стримов проходят через некий файлстримовский внутренний метод void Init. Там проверяется всё и вся. Кому интересно, аттач сделал. Но где-то на половине содержимого мои скудные познания заканчиваются, ни асилил, признаюсь честно. Да и действительно, проще исключения отловить, чем в такие дебри залезать. Может когда-нибудь я и освою все это, но пока времени нет на неспешный, вдумчивый анализ.

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

Век живи, век учись!!! (интересно, кто же такой, этот век, и что его так все воспитывать пытаются).

Автор: mr.DUDA 12.9.2007, 10:45
Цитата(tol05 @  12.9.2007,  09:53 Найти цитируемый пост)
При создании первого потока Experimenter заявлял, что готов на совместный доступ к файлу. А кому это интересно? Никто этот файл не шарит еще.А вот при создании второго потока - нужно сказать, что готовы на совместный доступ. Потому как на момент создания второго потока может оказаться, что файл уже кто-то юзает. (А так оно и есть).

А вот и нет, определяет как раз тот кто первый указал тип FileShare, а все последующие открытия файла могут юзать либо такой же либо более ограничивающий. Читайте описание enum FileShare  smile 

По дефолту (если не указывать шаринг), юзается FileShare.Read, см. конструктор FileStream в рефлекторе.

Автор: Experimenter 12.9.2007, 11:15
Цитата

система-то не дура и знает, что этот несчастный файл занят другим процессом


А может и не знает. Вот что нашел по WinAPI, раздел безопасность (типа известные ошибки Windows):

Код ошибки: 32 (0x0020)
Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.

Автор: tol05 13.9.2007, 22:05
Цитата(mr.DUDA @  12.9.2007,  10:45 Найти цитируемый пост)
Читайте описание enum FileShare

Цитата(mr.DUDA @  12.9.2007,  10:45 Найти цитируемый пост)
 см. конструктор FileStream в рефлекторе
тю!
Я ж логически помыслить предлагал, а не мануалы читать! Зафиксать баг мысленно, волевым усилием беду забороть!

 smile 

Если серьезно, да, виноват, признаю..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)