Текущий архив: 2005.03.20;
Скачать: CL | DM;
Вниз
EInOutError - Invalide File Name Найти похожие ветки
← →
Германн © (2005-03-04 01:16) [0]Возвращаюсь к более раннему моему топику. Нашел способ уточнить подробности сего исключения. И вижу, что имя файла - полностью нормальное! Никаких "запрещенных символов" не содержит.
Теперь вопрос. Если кто знает :(
Может ли эта ошибка(исключение) генерироваться из-за того, что ограничены права данного юзера на создание файла в некоей директории(папке)?
ОС точно не знаю. Но думаю, что это либо 2k, либо XP.
← →
Gero © (2005-03-04 01:19) [1]Может.
← →
Германн © (2005-03-04 01:25) [2]2 Gero © (04.03.05 01:19) [1]
Вы уверены?
Тогда Спасибо!
← →
Gero © (2005-03-04 08:33) [3]
> Германн © (04.03.05 01:25)
Тем не менее, оно может генерироваться и не из-за этого.
← →
Anatoly Podgoretsky © (2005-03-04 08:54) [4]Германн © (04.03.05 01:16)
Это означает, что не смогло работать с таким именем, а конкретная причина неизвестна, в том числе и права. Проверяется через проводник и проверяется дважды в той папке и папке где гарантированы права. Еще может мешать антивирус и другие подобные бяки.
А что за код?
← →
Германн © (2005-03-04 12:55) [5]2 Anatoly Podgoretsky © (04.03.05 08:54) [4]
Код совершенно обычный:
AssignFile(FDest,SndName);
{$I-}
Reset(FDest,1);
{$I+}
if (IOResult <> 0) or (not Loop) then begin
FInspMain.SaveLog(nil,SndName,"TSndData.Create");
Rewrite(FDest,1);
Move(CWaveStruct,FDestHeader,SizeOf(TWaveStruct));
BlockWrite(FDest,FDestHeader,SizeOf(TWaveStruct));
end else begin
BlockRead(FDest,FDestHeader,SizeOf(TWaveStruct));
Seek(FDest,FileSize(FDest));
end;
Этот код работает уже лет 8. И без проблем.
А вот теперь на одном объекте:
03.03.2005 12:59:29-C:\INSPECT\SOUND\TEMP\1314.WAV
03.03.2005 12:59:29-EInOutError : Invalid filename
**************************************************
Первая строка записана в лог функцией SaveLog. Вторая записана в обработчике Application.OnException.
Сегодня обещали на том объекте проверить все права.
← →
Anatoly Podgoretsky © (2005-03-04 13:21) [6]И где код обработчика, где код SaveLog?
Почему после ошибки открытия делаются попытки записи?
Почему не используется более совершенная технология исключений, а вместо ее устаревшая из ДОС и та не правильно используется.
Не надо пока ни какие права проверять, надо сначала привести код программы.
← →
Германн © (2005-03-05 01:03) [7]2 Anatoly Podgoretsky © (04.03.05 13:21) [6]
Код не мой. Код был написан другим человеком где-то в 95-96 годах. Еще на Д1. Позже он был портирован сначала на Д3 потом, может быть был изменен для Д4. И только два дня назад его(исходник) "вытрясли" из разработчика для того, чтобы выяснить причину ошибки EInOutError : Invalid filename.
Для этого во все места, где происходила работа с файлами, тем или иным способом, был вставлен вызов функции SaveLog. Её код:procedure TFInspMain.SaveLog(E: Exception; EStr, PlaceSt: String);
var
i : Integer;
FT : TextFile;
St : String;
begin
St:=ChangeFileExt(Application.ExeName,"."+FormatDateTime("yymm",Now)+".log.txt");
AssignFile(FT,St);
if FileExists(St) then Append(FT) else ReWrite(FT);
if E <> nil then begin
St:=DateTimeToStr(Now)+"-"+ E.ClassName+" : "+E.Message;
Writeln(FT,St);
//LogMemo.Lines.Add(St);
if (E is EDBEngineError) then begin
for i:=0 to EDBEngineError(E).ErrorCount-1 do begin
St:=IntToStr(i)+": "+EDBEngineError(E).Errors[i].Message;
Writeln(FT,St);
//LogMemo.Lines.Add(St);
St:="ErrorCode="+IntToStr(EDBEngineError(E).Errors[i].ErrorCode)+
" Category="+IntToStr(EDBEngineError(E).Errors[i].Category)+
" SubCode="+IntToStr(EDBEngineError(E).Errors[i].SubCode);
Writeln(FT,St);
//LogMemo.Lines.Add(St);
end;
if EDBEngineError(E).Errors[0].ErrorCode = DBIERR_INDEXOUTOFDATE then begin
St:=EDBEngineError(E).Errors[1].Message;
St:=Copy(St,Pos("Table:",St)+8,Length(St));
St:=ExtractFileName(St);
if Pos(".",St) <> 0 then St:=Copy(St,1,Pos(".",St)-1);
CheckTbl(St);
end;
end;
if EStr <> "" then Writeln(FT,EStr);
if PlaceSt <> "" then Writeln(FT,PlaceSt);
end else begin
if EStr <> "" then begin
St:=DateTimeToStr(Now)+"-"+EStr;
Writeln(FT,St);
if PlaceSt <> "" then Writeln(FT,PlaceSt);
end else if PlaceSt <> "" then begin
St:=DateTimeToStr(Now)+"-"+PlaceSt;
Writeln(FT,St);
end;
end;
Writeln(FT,"*****************************************************************");
CloseFile(FT);
end;
Код обработчика:
procedure TFInspMain.AppEvents1Exception(Sender: TObject; E: Exception);
begin
SaveLog(E,"","");
end;
>Почему после ошибки открытия делаются попытки записи?
Потому что файл, о котором идет тут речь - временный. Создаваемый программой тогда, когда это нужно. Точнее - это WAV-файл который "собирается по кусочкам" из других, уже имеющихся, WAV-файлов, для озвучивания произошедшего в системе события. Но! События могут быть двух типов: ординарные и особенные. В первом случае их достаточно озвучить однократно и затем замолчать. Во втором - их надо постоянно повторять до тех пор, пока ситуация не исправится или оператор не нажмет специльную кнопку, подтверждая, что он тревогу принял и осознал. В этом втором случае файл уже может существовать, если предыдущая тревога еще не снята. И тогда новое сообщение прибавляется к старому. Во всех остальных случаях файл, по умолчанию" не существует, поскольку его имя - содержимое автоикрементного поля DB.
← →
GuAV © (2005-03-05 01:31) [8]Германн © (05.03.05 1:03) [7]
> Точнее - это WAV-файл который "собирается по
> кусочкам" из других, уже имеющихся
А почему бы не проигрывать их ("кусочки") синхронно в отдельном потоке, а имена или IDы их передавать через postmessage ?
Или собирать их из "кусочков" в памяти ? (у PlaySound / sndPlaySound есть флаг SND_MEMORY)
← →
GuAV © (2005-03-05 01:43) [9]
> потоке, а имена или IDы их передавать через
> postmessage ?
т.е. PostThreadMessage. выбирать их PeekMessage с pm_remove, если нечего проигрывать ждать WaitMessage
← →
Германн © (2005-03-05 01:53) [10]2 GuAV © (05.03.05 01:31) [8]
Если бы это писАл я, да еще сейчас, а не 10 лет назад, я бы вообще пошел бы другим путем. Например, использовал бы что-то из SpeechAPI. Гораздо удобнее, чем WAV-файлы.
Но кто мне это оплатит?
А вот "разбираться с ошибками" уже существующей программы, блин! Хочу уйти из этой конторы. Ищу другую. Но это - offtopic!
Но, кстати.
>А почему бы не проигрывать их ("кусочки") синхронно в отдельном потоке, а имена или IDы их передавать через postmessage ?
А что бы это изменило? Причем тут "отдельный поток"? Мне вроде как и основного хватало?
>Или собирать их из "кусочков" в памяти ? (у PlaySound / sndPlaySound есть флаг SND_MEMORY)
Эт-да, да вот только разница будет, "если файл уже есть в памяти", а если его ещё нужно "собрать из кусочков"?
← →
GuAV © (2005-03-05 02:02) [11]Германн © (05.03.05 1:53) [10]
Эт-да, да вот только разница будет, "если файл уже есть в памяти", а если его ещё нужно "собрать из кусочков"?
Так можете собирать в памяти, заменив например BlockWrite на TMemoryStream.Write
Германн © (05.03.05 1:53) [10]
А что бы это изменило? Причем тут "отдельный поток"? Мне вроде как и основного хватало?
То что никакого "сбора" бы не было. Проигрываете один, затем другой, в перерывах проверяеете не изменился ли "плейлист". Я бы так попробовал бы перед тем как "склеивать". В прочем учитывая [10] это отпадает.
← →
Германн © (2005-03-05 02:37) [12]2GuAV © (05.03.05 02:02) [11]
>То что никакого "сбора" бы не было. Проигрываете один, затем другой, в перерывах проверяеете не изменился ли "плейлист".
Я, конечно не прав, что не изложил полностью идеологию данной функции. Данная функция формирует Wav-файл, в который включен "номер датчика" в диапазоне от 1 до 99.
"Склеивание" в том числе преполагало и "склеивание" для "вразумительного" произношения числа "девяносто девять" файлов "90.wav" и "9.wav".
← →
GuAV © (2005-03-05 02:39) [13]Работоспособный пример, поясняющий идею с потоком. В ListBox1 несколько полных путей к WAV файлам.
uses MMSystem;
var ThdID: DWORD;
const
WM_PLAY_ONCE = WM_USER + 0;
WM_PLAY_ADD = WM_USER + 1;
WM_PLAY_REMOVE = WM_USER + 2;
WM_PLAY_QUIT = WM_USER + 3;
function WaveThd(Parameter: Pointer): Integer;
var
Msg: TMsg;
L: TList;
I: Integer;
sounds: TStrings;
begin
sounds := Parameter;
L := Tlist.Create;
while True do
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
case Msg.message of
WM_PLAY_ONCE:
PlaySound(PChar(sounds[Msg.lParam]), 0, SND_SYNC or SND_FILENAME);
WM_PLAY_ADD:
L.Add(Pointer(Msg.lParam));
WM_PLAY_REMOVE:
L.Remove(Pointer(Msg.lParam));
WM_PLAY_QUIT, WM_QUIT: Break;
end
else
if L.Count = 0 then
begin
if not WaitMessage then Break
end
else
begin
for I := 0 to L.Count - 1 do
PlaySound(PChar(sounds[Integer(L[I])]), 0, SND_SYNC or SND_FILENAME);
end;
Result := Msg.wParam;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
BeginThread(nil, 0, WaveThd, ListBox1.Items, 0, ThdID);
end;
// проиграть один раз выбранный в LisbBox1 файл
procedure TForm1.Button1Click(Sender: TObject);
begin
PostThreadMessage(ThdID, WM_PLAY_ONCE, 0, ListBox1.ItemIndex);
end;
// поставить выбранный в LisbBox1 файл на постоянное воспроизведение
procedure TForm1.Button2Click(Sender: TObject);
begin
PostThreadMessage(ThdID, WM_PLAY_ADD, 0, ListBox1.ItemIndex);
end;
// снять выбранный в LisbBox1 файл с постоянного воспроизведенич
procedure TForm1.Button3Click(Sender: TObject);
begin
PostThreadMessage(ThdID, WM_PLAY_REMOVE, 0, ListBox1.ItemIndex);
end;
← →
GuAV © (2005-03-05 02:42) [14]Германн © (05.03.05 2:37) [12]
Склеивание" в том числе преполагало и "склеивание" для "вразумительного" произношения числа "девяносто девять" файлов "90.wav" и "9.wav".
Всё равно не понятно зачем в файл клеить. Можно склеивать в памяти. Самый удобный способ - через TMemoryStream.
← →
Германн © (2005-03-05 02:46) [15]Предлагаю всем желающим ознакомиться с вариантом GuAV © (05.03.05 02:39) [13]
Принять или не принять сей вариант - Ваше дело.
Я - пас. Поскольку мой сабж - не об этом!
← →
GuAV © (2005-03-05 02:55) [16]
> Германн © (05.03.05 2:46) [15]
Когда писал [13], [12] не видел, сори...
Хотя его легко до вида когда 90 и 9 будут произносится правильно.
PlaySound(IntToShr((N div 10)*10)+".wav", 0, SND_SYNC or SND_FILENAME);
PlaySound(IntToShr((N mod 10))+".wav", 0, SND_SYNC or SND_FILENAME);
если N равно 99 то будет сказано сначало 90.wav, а потом 9.wav.
← →
Германн © (2005-03-05 03:09) [17]2 GuAV © (05.03.05 02:55) [16]
В твоем варианте вполне может быть "сказано" так, что будет "воспринято" заказчиком или покупателем, как "основание для неплатежа" или как "основание еще чего-нибудь". Ведь вторая функция PlaySound выполнится БГ знает когда после выполнения первой функции PlaySound! А произношение "девяносто....................девять" - очень плохо звучит.
← →
Германн © (2005-03-05 03:24) [18]Да бог ним. С вариантом.
Меня сейчас интересует только "EInOutEroor : Invalid filename"
Как оно может возникнуть? и Как с ним бороться?
Жду сообщений с объекта.
← →
Defunct © (2005-03-05 04:10) [19]Германн © (05.03.05 03:24) [18]
> Меня сейчас интересует только "EInOutEroor : Invalid filename"
Меняйте на
GuAV © (05.03.05 02:42) [14]
> Самый удобный способ - через TMemoryStream.
и больше этот вопрос Вас не будет волновать.
или учитывая, что
Германн © (05.03.05 01:03) [7]
> Потому что файл, о котором идет тут речь - временный.
Замените каталог временных файлов на более подходящий с всегда разрешенными правами на создание и запись, пишем:function ValidateFileName( AFileName: String ):String;
var
TempName : PChar;
begin
GetMem( TempName, 1024);
try
GetTempPath( 1024, TempName );
Result := TempName + ExtractFileName(AFileName)
finally
FreeMem( TempName, 1024)
end
end;
и
Германн © (04.03.05 12:55) [5]
> AssignFile(FDest, SndName );
Заменяем все SndName на ValidateFileName(SndName)
Вариант?
← →
Германн © (2005-03-06 02:03) [20]2 Defunct © (05.03.05 04:10) [19]
>Меняйте на
>GuAV © (05.03.05 02:42) [14]
>> Самый удобный способ - через TMemoryStream.
>и больше этот вопрос Вас не будет волновать.
Поменяю, но не на вариант GuAV © (05.03.05 02:42) [14], а на тот, что я высказал в Германн © (05.03.05 01:53) [10].
Вот только найти бы того, кто это оплатит!
>или учитывая, что
>Германн © (05.03.05 01:03) [7]
>> Потому что файл, о котором идет тут речь - временный.
>Замените каталог временных файлов на более подходящий с всегда ?>разрешенными правами на создание и запись, пишем:
Именно это сейчас и делается! Т.е. люди на том объекте сейчас именно и обещали "разобраться с правами пользователей!" И навести в этом отношении порядок, если что не так!" Жду от них ответа в виде лог-файла!
А Вы можете указать на что-то "неправильное" в сообщении
Германн © (04.03.05 12:55) [5] по поводу записей в логе?
← →
Defunct © (2005-03-06 02:43) [21]> А Вы можете указать на что-то "неправильное" в сообщении
> по поводу записей в логе?
Могу сказать, что исключение возникло либо на строке ReWrite(F) либо вообще не в этой процедуре, не более того.
← →
Германн © (2005-03-06 02:59) [22]2 Defunct © (06.03.05 02:43) [21]
Оно где-то там.
Если это не так, то прошу меня расстрелять при первой возможности, и, плииз, максимально безболезненно. :)
← →
Anatoly Podgoretsky © (2005-03-06 11:52) [23]Все тоже самое, reset в проверке, а затем rewrite уже без проверки. Либо делается проверка на каждом шаге, или что лучше делается в защищенном блоке. А при такой реализации даже узнать где произошла ошибка не получится, даже отладка не поможет, нельзя читать IOResult в отладчике.
Надо просто переписать программу, а еще лучше вообще сменить алгоритм, ряд вариантов подсказали.
При этой реализации лог будет показывать температуру где то там.
Не используй
{$I-}
Reset(FDest,1);
{$I+}
пиши с помощью защищенны[ блоков
AssignFile(FDest,SndName);
try
Reset(FDest,1);
...
...
except
Обработка ошибки
end;
Тоже если вздумаешь при ошибки перезаписывать файл.
← →
Defunct © (2005-03-06 20:55) [24]Defunct © (06.03.05 02:43) [21]
Добавлю, токое исключение может возникнуть в случае, если файл с атрибутом Read-Only был открыт в блоке {$i-} Reset(F) {$i+}
← →
Германн © (2005-03-07 02:38) [25]2 Anatoly Podgoretsky ©
2 Defunct ©
Мужики!
Приведенный код, я согласен, "ну очень "хреновый""!
Но, еще раз, - он не мой! А переделка сего кода требует "времязатрат" и, ес-но "доп.оплаты". Но мне такого не было предложено!
Таким образом, если сия проблема может быть решена "Какой-либо "установкой "Каких-либо прав юзеров"", то я буду "ну очень рад!"
Пока, отключаюсь. Жду сообщений от юзеров с объекта. Результат сообщу.
Как только, так сразу :)
← →
Anatoly Podgoretsky © (2005-03-07 11:20) [26]Тогда какого черты ты спрашиваешь, без изменения кода удачи не видать. Приходи тогда, когда будет предложено.
← →
Германн © (2005-03-08 01:55) [27]2 Anatoly Podgoretsky © (07.03.05 11:20) [26]
>Тогда какого черты ты спрашиваешь, без изменения кода удачи не >видать. Приходи тогда, когда будет предложено.
Простите напомню:
Германн © (04.03.05 12:55) [5]
2 Anatoly Podgoretsky © (04.03.05 08:54) [4]
Этот код работает уже лет 8. И без проблем.
И это без обмана. Программа с этим кодом работает уже 8 лет. На разных объектах. И нигде такой проблемы не было!
Но! Как правило, до сих пор никто или почти никто не занимался "установкой прав юзеров".
Таки вот и задал я свой вопрос, потому что не понял из-за чего возникает ошибка EInOutError : Invalid File Name?
Потому что в в логе, имя файла совершенно нормальное!
Анатолий!
А Вы, когда постируете свои ответы всегда глядите лишь на последнее сообщение? Или иногда учитываете всю ветку?
← →
Gero © (2005-03-08 01:59) [28]
> Германн © (08.03.05 01:55)
Так что с правами?
Какие NTFS-разрешения/запреты стоят?
← →
Palladin © (2005-03-08 02:13) [29]
> Код совершенно обычный:
> AssignFile(FDest,SndName);
> {$I-}
> Reset(FDest,1);
> {$I+}
> if (IOResult <> 0) or (not Loop) then begin
> FInspMain.SaveLog(nil,SndName,"TSndData.Create");
> Rewrite(FDest,1);
> Move(CWaveStruct,FDestHeader,SizeOf(TWaveStruct));
> BlockWrite(FDest,FDestHeader,SizeOf(TWaveStruct));
> end else begin
> BlockRead(FDest,FDestHeader,SizeOf(TWaveStruct));
> Seek(FDest,FileSize(FDest));
> end;
Ничуть не обычный.
Во первых: IOResult считывается имеено в рамках {$I+} {$I-},
вне, оно не имеет смысла. Во вторых, его значение отнюдь не лишено смысла, и стоит его проанализировать прежде чем гадать, что же происходит.
← →
Германн © (2005-03-08 02:42) [30]2 Gero © (08.03.05 01:59) [28]
Отвечу как только, так сразу :) Но ес-сно только после праздников.
2 Palladin © (08.03.05 02:13) [29]
>Во первых: IOResult считывается имеено в рамках {$I+} {$I-},
>вне, оно не имеет смысла.
Извини Тимур, но кто тебе сказал такую чушь?
Насчет "во-вторых" я уже говорил. Именно о том что оно стоит. А пока добавлены лишь весьма дешевые строки с записью в лог.
← →
Palladin © (2005-03-08 02:55) [31]Да в общем то оно очевидно как из определения, так и из документации (советую к прочтению F1, как знаете, еще из TP3 эта тема тянется). Как только IOResult принимает значение отличные от нуля вне границ {$I+} {$I-} возникает исключение. Для того {$I-} {$I+} и созданны вообще то...
← →
Германн © (2005-03-08 03:25) [32]2 Palladin © (08.03.05 02:55) [31]
Ну и... ?
Вы привели часть опубликованного мной кода:
>Palladin © (08.03.05 02:13) [29]
>> Код совершенно обычный:
>> AssignFile(FDest,SndName);
>> {$I-}
>> Reset(FDest,1);
>> {$I+}
>> if (IOResult <> 0) or (not Loop) then begin
Я, лично на TP3 не работал.
Имхо, врядли кто из участников сего форума на ТР3 смог поработать! Ну максимум Юрий Зотов и то врядли. В те времена в СССР просто не было компьютеров на которых можно было бы пользоваться ТР3, а если такие и были, то они были в распоряжении "солидных людей"!
Но в работах на TP4 уже принимал участие. А уж на TP5 мною сделано много.
А Опции компиллятора {$I-} и {$I+} созданы для того, чтобы имелась возможность "отключить стандартную реакцию" системы на ошибку ввода/вывода. Ранее это - сообщение системы об ошибке, сейчас это - возбуждение исключения (что вообщем-то одно и то же).
Страницы: 1 вся ветка
Текущий архив: 2005.03.20;
Скачать: CL | DM;
Память: 0.56 MB
Время: 0.034 c