Есть текстовый файл. Открываю его (если его нет, то создаю), читаю содержимое, добавляю к нему строку фиксированного размера и сохраняю в файл с тем же именем, перетирая старый. Проблема в том, что иногда строка не добавляется. Файл остаётся прежнего размера и содержания. Везде, где можно, вставил проверку на возможные ошибки (копирования строки, чтения\записи\создания файла, выделения памяти). Любая ошибка должна вызывать jmp @Err, но его ни разу не было. А тем не менее, примерно 30% случаев строка в файл не добавляется. Не пойму, каким образом проскакивает мимо всех проверок И говорит, что всё ОК (Beep) В аттаче сама процедура. Может кто подскажет, где капкан? Как можно попасть на Beep, и при этом не увеличив размер файла? _1642355497__SaveLog.asm
Вот это лишнее or FILE_SHARE_WRITE зачем для кого-то открывать файл на запись. Почему всё так сложно? Зачем выделять память, сначала вызываешь SetFilePointer, потом WriteFile и всё. Функция CreateFile с параметром OPEN_ALWAYS сама создаст файл если его нет.
Приблизительно так, только нужно добавить проверку на успешность вызова API. Код (Text): .DATA Stroka db "Hello",13,10 S_Len equ $-Stroka .CODE start: invoke CreateFile,OFFSET fName,GENERIC_WRITE,\ FILE_SHARE_READ,0,OPEN_ALWAYS,\ FILE_ATTRIBUTE_NORMAL,0 mov hFile,eax invoke SetFilePointer,hFile, NULL, NULL, FILE_END invoke WriteFile,hFile,OFFSET Stroka,S_Len,OFFSET written,0 invoke CloseHandle,hFile
Да там столько ошибок... на 10 строчке считать надоело. Сотри все на и пиши заново, только сначала изучи команды ассемблера и АПИ получше.
Asterix FILE_SHARE_WRITE - это элементы танца с бубном SetFilePointer совсем выпал из поля зрения, отсюда и манипуляции с доп памятью. Буду пробовать. Спасибо Turkish Ты видимо сначала выучил наизусть, как стихотворение, MSDN, и после этого стал писать Hello world? Мне твой метод не подходит. Не люблю зубрёжки :-\
Процедуру упростил, но кардинально ведь от этого ничего не меняется, просто способ изменился. Строка по прежнему дописывается в файл через раз, после каждого вызова API вставлена проверка, отсылающая на MessageBox в случае ошибки, но MesssageBox пока что ни разу не появился, так что вопрос остался открытым: как может программа проскочить мимо сообщения об ошибке, при этом не дописав строку в файл. В аттаче новая процедура 116966035__SaveLog.asm
Нашёл, в чем дело. Одна из запущенных программ изменяла current directory. Файл же указывался не полный путь, а просто имя файла, так что файл поочередно дописывался то в одной директории, то в другой Вот...
Тут нужно смотреть что происходит в реальных условиях, в отладчик почаще заглядывай Чтоб можно было проверить всегда ли пишется или не всегда нужно приводить весь исходник или какой-нибудь макет реальной твоей проги, т.е. выдрав какую-то часть которую можно скомпилировать и посмотреть на ошибку. Например скомпилировав и запустив прилагаемую программу ты убедишься что все строки пишуться в файл как положено. _1630733822__WriteFile.rar
Asterix Кстати твоя прога также будет себя вести, т.к. указан не полный путь к файлу (см. предыдущий пост). Я почему-то думал, что файл всё время пишется в папку с исполняемым модулем, но это происходит только если приложение активное, если оно свернуто (как у меня через раз) и при этом пишет, то записывается не в AppPath а в CurrentDirectiry, которая может и не совпадать с AppPath. Ну вроде всё, спасибо за помощь.
cresta Ты хочешь сказать если сделать Sleep,10000, потом CreateFile,"test.txt" и во время паузы усердно переключать контексты на другие процессы (вызывающие SetCurrentDirectory), то test.txt может оказатся в каталоге чужой программы? Текущие пути и переменные создаются и записываются в память для каждого процесса ядром отдельно, ещё до проецирования модулей, на NT так точно, можно посмотреть где-то по адресу 0x20000
bogrus Немного не так. Прога, записывающая в файл лог, может вести лог (в файл) как в момент, когда она активна на экране (в фокусе) так и в момент, когда она свернута в трей и активны какие-либо другие приложения. Если прога активна, то запись в файл происходит в папку с программой. C:\masm32\RadAsm\masm\Projects\Net Stat\LogFile.txt. Как и должно быть. Если прога в трее, то запись лога иногда происходит в файл, находящийся в другой папке. Собственно, все "отсутствующие" записи были обнаружены мной в файле с таким же именем, но в другой папке. Как я нашёл это: вспомнил, что при работе каких-либо приложений, если возникает необходимость открыть\сохранить файл и вызывается CommonDialog, то очень часто он открывается в одной и той же InitialDir. C:\masm32\RadAsm\masm\Projects\New Float. Причём для разных приложений. Имя папки уже навязло в зубах, вот я и решил посмотреть в эту папку. И обнаружил там свои недостающие записи, оформленные в файл с таким же именем. Не знаю, каков механизм, и как должен определяться путь если имя не полное, но получается, что если не активное приложение пишет в файл, то его могут сбить с пути. Примерно такая картина. Причём: New Float.ехе не содержит вызовов SetCurrentDirectory, как впрочем и GetCurrentDirectory, чтобы перетянуть на себя одеяло. Но оно всегда активно (т.е. не сворачивается в трей, не минимизируется). И половина моего лога оказалась в папке с New Float.ехе
cresta Ты слишком все усложняешь. Чудес к сожалению не бывает. Просто переключаясь с проекта на проект ты получил другую текущую директорию, в которую программа и писала. Меня это уже задолбало : если кликать Экселевский файл, то макросы пишут в "Мои Документы", а если его открыть, то в родную директорию. Ты видимо кликал на файле проекта, автоматически вызывая RadAsm и забыл про МС-удобства При работе с IDE( оболочками) я и не такое получал. Там все было гораздо хуже : экзешник писался не туда и я тупо "не понимал" почему старые ошибки не исправляются, т.к. запускал экзешник ручками, а на время записи не смотрел.
valterg Тот проект, в папку которого спрятались отсутствующие записи, я в IDE давно уже не открывал. Он давно закончен и закрыт. exe этого проекта запускается ярлыком с рабочего стола. IDE однозначно ни при чём. Согласен, что чудес не бывает, вот только факты объяснить (подогнать под имеющуюся базу знаний) удаётся не всегда. А факт налицо: половина лога в другой папке
с директорией лучше определиться сразу. если это - директория, откуда запущена прога - то можно воспользоваться ф-ей GetModuleFileName, если какая-то системная - есть функции SHGetFolderPath (я не пользовался), а если папка должна настраиваться - лучше хранить ее в реестре. + для работы с путями есть удобный набор ф-й начинающиеся на Path... (в win32hlp о них ничего несказано -> MSDN)