Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
Внизкак узнать открыт файл или нет? Найти похожие ветки
← →
umbra © (2005-09-21 12:17) [0]Я подозреваю, что это довольно частый вопрос, но поиском ничего не нашел. Как при доступе к файлу определить открыт ли он уже каким либо процессом (приложением) или нет? Намекните, пожалуйста
← →
Tonich © (2005-09-21 12:20) [1]один из вариантов
function UseFile(FilePath:string):boolean;
var
HFileRes:HFILE;
begin
Result := False;
try
if not FileExists(FilePath) then Exit;
HFileRes := CreateFile(Pchar(FilePath),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0);
Result := (HFileRes = INVALID_HANDLE_VALUE);
if not Result then CloseHandle(HFileRes)
finally
end;
← →
Digitman © (2005-09-21 12:21) [2]
> Как при доступе к файлу
смотря что подразумевается под "доступ к файлу" ..
← →
umbra © (2005-09-21 13:53) [3]
> Tonich ©
Спасибо!
← →
Fay © (2005-09-21 14:41) [4]2 Tonich © (21.09.05 12:20) [1]
Зачем try..finally ?
← →
Tonich © (2005-09-21 14:53) [5]
> Fay © (21.09.05 14:41) [4]
дань привычке )))
Только я вас умоляю, давайте не будим развивать тему
скорости выполнения и ресурсозатрат кода
← →
Джо © (2005-09-21 16:33) [6]
>
> [5] Tonich © (21.09.05 14:53)
>
> > Fay © (21.09.05 14:41) [4]
>
> дань привычке )))
> Только я вас умоляю, давайте не будим развивать тему
> скорости выполнения и ресурсозатрат кода
А причем тут затраты и прочее? Блок finally-то пустой ;)
← →
Eraser © (2005-09-21 17:02) [7]
> Tonich © (21.09.05 12:20) [1]
Согласен с [4] и [6], для API вызовов защищёные блоки никчему.
← →
Джо © (2005-09-21 18:09) [8]
>
> [7] Eraser © (21.09.05 17:02)
>для API вызовов защищёные блоки никчему.
Бывает, что и "к чему", но в данном случае - уж точно ни к чему ;)
← →
Tonich © (2005-09-21 20:13) [9]Удалено модератором
← →
Джо © (2005-09-21 20:20) [10]
> [9] Tonich © (21.09.05 20:13)
А ты разве сказал человеку, как узнать, открыт или закрыт файл? :)
← →
Мексиканец © (2005-09-22 00:01) [11]Вообще смысл в том, что те приложения, для которых, запись в файл с которым они работают, во время работы критично, должны выставлять атрибут только для чтения либо запрещать вовсе. Программа которая обращается к файлу не получает доступа на запись, так как открывшая файл программа запретила его. Так что если разработчик придерживался этой концепции, то нужно просто проверять причину ошибки открытия файла функцией GetLastError().
Примерно это выглядит так:
hFile:= CreateFile();
if hFile = 0 then
case GetLastError() of
...
end;
← →
Мексиканец © (2005-09-22 00:11) [12]Извените конечно, но я что то не припомню случая когда вызовы API функций нужно контролировать блоками try...finally. API функции не могут вызвать исключительную ситуацию. Достаточно проверять значения возвращаемые функциями и если ошибка (как правило 0) то получить расшириный код ошибки функцией GetLastError().
Сказанное не относится к манипуляциям с возвращаемыми значениями функций :)
← →
Джо © (2005-09-22 01:27) [13]
> [12] Мексиканец © (22.09.05 00:11)
ВызываемWritePrivateProfileString("","","","d:\1.ini");
на XP
начинаем думать :))
← →
simpson © (2005-09-22 10:55) [14]> Мексиканец © (22.09.05 00:11) [12]
> API функции не могут вызвать исключительную ситуацию
Орех?
> Достаточно проверять значения возвращаемые функциями
Рассмотрим простую ситуацию: открытие COM-порта, установка его параметров, таймаутов и т. д. Последовательный вызов нескольких API-функций.
Что лучше, конструкции вида:
hFile := CreateFile(...);
if hFile = INVALID_HANDLE_VALUE then
begin
Result := GetLastError;
Exit;
end;
if not GetCommState(...) then
begin
Result := GetLastError;
Exit;
end;
...
или
hFile := CreateFile(...);
if hFile <> INVALID_HANDLE_VALUE then
begin
if GetCommState(...) then
begin
...
end
else
Result := GetLastError;
end
else
Result := GetLastError;
либо
hFile := CreateFile(...);
if hFile = INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
if not GetCommState(...) then
RaiseLastOSError;
...
if not SetCommState(...) then
RaiseLastOSError;
...
finally
CloseHandle(hFile);
end;
ИМХО, 3-й вариант более логичный и более читабельный. Если есть механизм SEH, почему бы его не использовать? Тем более, он прекрасно поддреживается в Delphi.
ЗЫ: "Извените" пишется через "и", а причатсные обороты в таком случае нужно отделять запятой: "Достаточно проверять значения, возвращаемые функциями".
Такое впечатление, что русский язык изучался по китайскому букварю.
← →
Fay © (2005-09-22 16:33) [15]2 simpson © (22.09.05 10:55) [14]
>> ИМХО, 3-й вариант более логичный и более читабельный
Он более ленивый (хотя я и сам так часто пишу). Тема небходимости try..finally не раскрыта.
>> "Извените" пишется через "и",
Согласен, но у многих это (через "е") уже в крови 8).
З.Ы.
причастные 8)
← →
simpson © (2005-09-22 17:16) [16]> Fay © (22.09.05 16:33) [15]
Про необходимость. Позволю не согласиться и попробую раскрыть тему :)
Вариант не ленивый. Он прежде всего логичный.
Если исключить программы, которые "истинные пацаны" пишут "чиста на АПИ", то получается, половина проекта, использующая VCL, написана со вcесторонним использованием SEH (как минимум, потому что используется VCL :) ), а другая половина? Использует конструкции типа 1 и 2?
Мне не лень написать кучу if"ов. Мне лень обладать механизмом обработки исключений и не пользоваться им - он специально для этого придуман. А еще лень иметь в одном проекте две принципиально разные схемы действий при возникновении исключительных ситуаций.
Про читабельность - согласен, это - субъективное.
> З.Ы.
> причастные 8)
Извиняюсь, быстро писАл. :)
Просто задолбали ученики церковно-приходских школ, которые почему-то решили пойти в программисты, не выучив родной язык.
← →
Fay © (2005-09-22 19:05) [17]2 simpson © (22.09.05 17:16) [16]
Полностью согласен. Но, недеюсь, Вы не станете утверждать, что в примере [1] ожидается некая невдолбенно исключительная ситуация 8)
← →
Мексиканец © (2005-09-22 21:39) [18]Удалено модератором
← →
Мексиканец © (2005-09-22 21:41) [19]Удалено модератором
← →
DiamondShark © (2005-09-22 23:44) [20]
> ИМХО, 3-й вариант более логичный и более читабельный
А вариант
Win32Check( GetCommState(...) );
ещё читабельней.
← →
Игорь Шевченко © (2005-09-23 01:07) [21]simpson © (22.09.05 17:16) [16]
> Мне не лень написать кучу if"ов. Мне лень обладать механизмом
> обработки исключений и не пользоваться им - он специально
> для этого придуман. А еще лень иметь в одном проекте две
> принципиально разные схемы действий при возникновении исключительных
> ситуаций.
Я целиком и полностью поддерживаю.
Лень, безусловно, дело благородное.
Она вынуждает писать код, подобный такому:
procedure TCanvas.Lock;
begin
EnterCriticalSection(CounterLock);
Inc(FLockCount);
LeaveCriticalSection(CounterLock);
EnterCriticalSection(FLock);
end;
function TCanvas.TryLock: Boolean;
begin
EnterCriticalSection(CounterLock);
try
Result := FLockCount = 0;
if Result then Lock;
finally
LeaveCriticalSection(CounterLock);
end;
end;
То есть, в последнем примере между вызовами EnterCriticalSection и LeaveCriticalSection исключений на первый взгляд и не должно произойти.
Или такому:
procedure TFoo.Bar;
.....
DC := GetDC(0);
try
for I:=Low(Boolean) to High(Boolean) do begin
OldFont := SelectObject(DC, FCaptionFonts[I]);
try
GetTextMetrics(DC, tm);
FCyCaptionFontChars[I] := tm.tmHeight;
finally
SelectObject(DC, OldFont);
end;
end;
finally
ReleaseDC(0, DC);
end;
....
end;
Где тоже вроде исключений не может произойти.
Однако, исключения могут произойти в обоих случаях, если self=nil и ресурсы системы будут захвачены и не освобождены, что весьма плохо.
С уважением,
← →
Tonich © (2005-09-23 11:50) [22]
> Джо © (21.09.05 20:20) [10]
это один из вариантов , проверить используется ли файл други приложением или нет!!! или ВЫ считаете что нет???
ТоХда прошу научить как же надо это делать, а то от ВАС было только замечание ....
← →
Джо © (2005-09-23 12:53) [23]
> [22] Tonich © (23.09.05 11:50)
1. CreateFile возвращает INVALID_HANDLE_VALUE не только в сабжевой ситуации (кстати, не вполне четко обрисованной). Причин может быть много, одна из них - у процесса может быть недостаточно прав на открытие файла, файл может быть зашифрован, да мало ли что?
2. Название функции не соответствует назначению :)
← →
Джо © (2005-09-23 12:57) [24]
> ТоХда прошу научить как же надо это делать, а то от ВАС
> было только замечание ....
Не могу научить, ибо сам не знаю. Думаю даже, что это и почти невозможно сделать, т.е., определить "открыт ли файл каким-нибудь процессом". Осмелюсь даже предположить - что, в принципе, это и не имеет практической пользы, выяснять такие нюансы. Достаточно корректно обработать ситуацию, когда файл недоступен. А не выяснять, почему он недоступен.
← →
Игорь Шевченко © (2005-09-23 13:21) [25]Джо © (23.09.05 12:57) [24]
> Думаю даже, что это и почти невозможно сделать, т.е., определить
> "открыт ли файл каким-нибудь процессом".
Возможно. Но непросто.
← →
Джо © (2005-09-23 13:38) [26]
> [25] Игорь Шевченко © (23.09.05 13:21)
> Возможно. Но непросто.
Да я тоже думаю, что докопаться все-таки можно (конкретный способ назвать "сходу" не могу). А смысл? Только для каких-то системных утилит или в познавательных целях. "Познавательный смысл" в виду того, что просится готовое решение - исключается; системные утилиты - исключаю "интуитивно" (возможно, ошибаюсь).
← →
Игорь Шевченко © (2005-09-23 13:57) [27]Джо © (23.09.05 13:38) [26]
> А смысл? Только для каких-то системных утилит
Да, конечно. В прикладной софтине вроде ни к чему
← →
umbra © (2005-09-23 14:34) [28]пе
> обработать ситуацию, когда файл недоступен
А если он доступен, но чтобы решить, что делать дальше надо знать, открыт он или нет?
← →
Джо © (2005-09-23 14:37) [29]
> [28] umbra © (23.09.05 14:34)
> А если он доступен, но чтобы решить, что делать дальше надо
> знать, открыт он или нет?
Зависит, наверное, от того - что предполагается "делать". Это большая тайна?
← →
simpson © (2005-09-23 14:41) [30]> umbra © (23.09.05 14:34) [28]
Да нет таких прикладных задач, когда надо знать, открыт файл, или нет, прежде чем начинать с ним работу. Работа с файлами на прикладном уровне сводится к тому, чтобы попытаться открыть файл в нужном режиме, и, если это невозможно, выдать соответствующее сообщение об ошибке и отреагировать согласно условиям задачи (например, прекратить работу, или попытаться позже).
Ну узнал ты, что файл, к которому ты пытаешься обратиться, занят процессом "proga.exe". И что? Жестоко убьешь этот процесс, чтобы самому начать работу с занятым файлом? Не думаю. :)
← →
umbra © (2005-09-23 14:43) [31]ну, к примеру, есть две проги, одна пишет в файл, другая из него читает. запускаются автоматически, интервалы между запусками изменяющиеся. А читать надо только после того, как все записано
← →
simpson © (2005-09-23 14:45) [32]> umbra © (23.09.05 14:43) [31]
Ну так причем же здесь сабж? Тебе всего лишь нужен механизм межпроцессного взаимодействия.
← →
umbra © (2005-09-23 14:50) [33]по-моему гораздо проще проверить открыт ли файл (спасибо, Tonich), чем устраивать механизм межпроцессного взаимодействия между программами разных разработчиков при отсутствии исходного кода.
← →
umbra © (2005-09-23 14:57) [34]
> что предполагается "делать"
Или например, при запуске проги надо убедиться, что это первый ее екземпляр. Для этого при запуске проверяется, открыт ли определенный файл -если открыт, то значит прога уже раз запущена, надо вторую закрывать. Опять таки, проще проверить файл, чем искать окна, процессы и т.д.
← →
Джо © (2005-09-23 15:09) [35]
> [34] umbra © (23.09.05 14:57)
> Или например, при запуске проги надо убедиться, что это
> первый ее екземпляр. Для этого при запуске проверяется,
> открыт ли определенный файл -если открыт, то значит прога
> уже раз запущена, надо вторую закрывать. Опять таки, проще
> проверить файл, чем искать окна, процессы и т.д.
Очень показательный ответ.
Кстати, как думаешь - в какой место попадет твой замечательный лисапедный способ, если твою программу снимут из Task Manager"а? Или для этого предлагаешь решать задачу: "Как скрыть мой процесс из списка процессов"? Очень показательный ответ :(
← →
umbra © (2005-09-23 15:23) [36]аварийное завершение тоже можно перехватить и файл закрыть (удалить)
Но я согласен, пример не очень удачный. Хотя на этом замечательном лисапедном способе держится пол-линуха.
← →
Игорь Шевченко © (2005-09-23 15:48) [37]
> Хотя на этом замечательном лисапедном способе держится пол-
> линуха.
Какая именно половина Linux"а ? :)
← →
BiN © (2005-09-23 15:53) [38]http://66.249.93.104/search?q=cache:B7JYEdq4hnMJ:delphimaster.ru/cgi-bin/forum.pl%3Fid%3D1121359278%26n%3D5+querydosdevi ce+%D0%BC%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B0+Delphi&hl=ru
а также
http://66.249.93.104/search?q=cache:mYb99Yo7iqwJ:www.delphimaster.ru/cgi-bin/forum.pl%3Fid%3D1120126541%26n%3D5+querydos device+%D0%BC%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B0+Delphi&hl=ru
(спасибо кэшу гугля)
← →
umbra © (2005-09-23 16:00) [39]Серверная, в основном. Самба, сендмейл, ксинетд, ссаш к примеру
← →
ANB © (2005-09-23 17:05) [40]
> Или например, при запуске проги надо убедиться, что это
> первый ее екземпляр.
- это делается намного проще. А вот конкретный пример из реального проекта :
Есть консольная прога (текстовый режим, никаких окон), она время от времени отвечает на звонки по модему и складывает ответ в файл. Другая прога должна прочитать этот файл только, когда он не занят (в него не пишут). Повторное чтение неизмененного файла уже обработано и некритично. Вот таким способом и сделано - каждая из прог открывает файл в монопольном режиме и если не получается - ждет, пока получится. Хотя я бы сам, имхо, сделал бы по другому, но это самый тупорылый вариант, с учетом того, что из управляещей проги нет доступа к WinAPI.
Страницы: 1 2 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.013 c