Программа использует TSaveDialog. Стандартно вызывается SaveDialog.Execute. Все нормально под Win98SE и XP, но при запуске программы под Windows Vista (бизнес) вызов диалога с регулярной периодичностью разрушает данные в памяти программы и программа вылетает с кучей сообщений об ошибках. Используется Delphi 6. Может кто с таким сталкивался? Подскажите что менять - версию Delphi, Висту или есть другие варианты?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
29-04-2008 01:15 | Сообщение от автора вопроса
2 Бел Амор
Большое спасибо за анализ моей проблемы. И Ваш вариант формирования имени файла действительно намного элегантнее, отдельное спасибо.
По существу вопроса я всё же склоняюсь к причине, описанной в ответе DRON-а.
Я попробовал все предложенные Вами варианты. Последний (5) я сделал сам сразу, как возникла эта проблема. После получения данных сохраняю их автоматически в файл с именем temp.data вызовом SaveDataToFile. Всё работает и при вылете программы пользователь не теряет данные. Повесил для тестирования сохранение на таймер и сохранял сотни раз подряд разные данные в разных вариантах - сбоев нет.
Пробуя пункт номер один задавал фиксированный каталог и имя файла (напр. dlgFileSave.FileName := 'test.dat') или не задавал совсем ни то ни другое (забивал с клавиатуры). Результат одинаковый, обращение к массивам после "неудачного" вызова диалога - ошибки и вылет программы.
Range checking и Overflow checking включены изначально. На всякий случай сделал как Вы сказали - этих ошибок при работе программы нет.
В результате проб выяснил что вылетает только при вызове (вернее после) окна SaveDialog. Очень плохо что происходит это не каждый раз и непредсказуемо когда. Остальной текст на этот процесс не влияет (закоментил всё). Ещё хуже что программа вылетает не на всех машинах с Вистой, а как-то выборочно. Обнаружить с чем связана эта "нелюбовь" к отдельным экземплярам Висты, выключая "левые расширения оболочки", пока не удалось. Не найду - сделаю дополнительный простенький диалог вместо вызова стандартного. Некрасиво, но работать будет. Найду - прикончу поставившего их!
1. Комбинация Vista + Delphi6 + манифест
2. Ещё до вызова btnSaveClick кто-то затирает часть памяти.
3. За счёт других региональных настроек формируется недопустимое имя файла и Виста на него неадекватно реагирует.
4. Ошибка происходит в процедуре SaveDataToFile и после первого прохода портит какую-то область памяти.
5. Попытка записи в защищённый от записи каталог и неадекватная реакция на это программы (например, программа установлена в Program files и пытается писать туда-же). Кстати, это характерно именно для Висты.
Попробовать:
1. Не задавать имя файла вообще или задавать вручную заведомо допустимое.
2. Закомментировать SaveDataToFile
3. Попробовать вставить совершенно новый диалог и вызывать его - посмотреть, будет ли вылет.
4. Включить в опциях проекта (закладка Compiler) Range checking и Overflow checking. После этого удалить exe и все dcu, и перекомпилировать проект (на Build - не полагаться).
5. Попробовать не вызывать диалог вообще, а сохранять файл с заранее заданным заведомо корректным именем (полным).
Наиболее вероятной причиной проблемы я считаю некорректное имя файла и неадекватную реакцию на него Висты. Независимо от правильности этого предположения, способ формирования имени файла в вашей процедуре мне не нравится категорически. Могу предложить альтернативный вариант:
s := FormatDateTime('yyyy-mm-dd_hh-nn_(ss)', StartDateTime) + '.data';
Сходу не совсем понял что такое "левые расширения оболочки".
Расширения оболочки это "Shell extensions", а "левые" означает, что они не от MS, а от Васи Пупкина. Эти расширения загружаются в адресное пространство вашего процесса при любом взаимодействии с оболочкой (TSave(Open)Dialog, контекстное меню и свойства файла итд) и могут вытворять всё что угодно.
И ещё вопрос, Ваш unit ShellExtFix под ХР (автор про ХР спрашивал) или под любую Винду.
Проверял я его (и то не слишком внимательно) только под XP. И вообще данный "модуль" это крайнее решение, просто в том вопросе товарищ хотел решить проблему без выезда к клиенту, а по нормальному, такие глюки (если они действительно из-за ShellExtensions) вас не должны волновать, это проблема пользователя понаставившего разную фигню.
2 Бел Амор
Не, может я неясно сформулировал вопрос, но ничего общего с »вопрос КС №60563« у меня нет. Тот вопрос про фишку с путями я давно прочитал и помню. У меня по другому, очень похоже на »вопрос КС №54843«. При вызове диалога разрушаются динамические массивы в памяти, те которые должны сохранятся и дальше куча сообщений об ошибках обращения к несуществующим адресам памяти. Причем даже до показа диалога не доходит. Попробовал перехватить ошибки используя try-except. Но похоже что-то сделал не так. При ошибке никаких моих сообщений нет, показывается диалог с пустой строкой вместо предлагаемого пользователю имени файла. Если пользователь вписал имя файла вручную и попытался сохранить - полный крах программы.
2 DRON
Спасибо. Сходу не совсем понял что такое "левые расширения оболочки". Попробую скачать указанные утилиты и разобраться. И ещё вопрос, Ваш unit ShellExtFix под ХР (автор про ХР спрашивал) или под любую Винду. Я понимаю что он делает (из описания) но не совсем понимаю как (по тексту юнита), но пока мне важен результат и помаленьку разберусь.
Гляньте пожалуйста, может я что напутал в своем тексте? Хотя под 98-м и ХР всё работает отлично, проблема только с Вистой. Виста свежеустановленная.
procedure TMainForm.btnSaveClick(Sender: TObject);
var
FileHandle: Integer;
FileName: TFileName;
s: string;
begin
try
s := DateTimeToStr(StartDateTime); // StartDateTime: TDateTime
while System.Pos(':', s) > 0 do s[System.Pos(':', s)] := '-';
s := s + '.data';
except
s := 'Файл с данными.data'
end;
try
dlgFileSave.FileName := s
except
Application.MessageBox('Ошибка подготовки диалога сохранения.',
'Сохранение данных', MB_ICONERROR or MB_OK);
exit
end;
try
if dlgFileSave.Execute then
begin
FileName := dlgFileSave.FileName;
FileHandle := FileCreate(FileName, fmOpenReadWrite);
SaveDataToFile(FileHandle, mmComment.Text); // сохраняю динмассивы в файл
FileClose(FileHandle);
Application.MessageBox('Данные успешно сохранены в файле.',
'Сохранение данных', MB_ICONINFORMATION or MB_OK)
end
except
Application.MessageBox('Не удалось записать данные в файл',
'Сохранение данных', MB_ICONERROR or MB_OK)
end;
end;
Все нормально под Win98SE и XP, но при запуске программы под Windows Vista (бизнес) вызов диалога с регулярной периодичностью разрушает данные в памяти программы и программа вылетает с кучей сообщений об ошибках.
С большой степенью вероятности вы найдёте ответ, заглянув в »вопрос КС №60563«
Замечу только, что всё сказанное в отношении TOpenDialog относится и к TSaveDialog - они отличаются, если мне не изменяет память, всего одним методом...
P.S. Причём тут Виста? Не знаю. Указанная проблема актуальна не только в Висте. И совсем не обязательно, что ваши проблемы связаны именно с описанным явлением.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.