Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > путь к файлу


Автор: larinva 14.10.2009, 22:32
Всем привет! подскажите какой функцией пользоваться чтобы не указывать явный путь к файлу пример (LoadFromFile(c:\12\nm.txt)) а то если изменищь директорю придется вносить изменение и в программе

Автор: Keeper89 14.10.2009, 23:09
Если nm.txt лежит в папке с программой. можно использовать
Код

LoadFromFile(ExtractFilePath(Application.ExeName) + 'nm.txt')

Автор: Данкинг 14.10.2009, 23:52
Если ты перемещаешь файл, то программе так и так нужно каким-то образом дать знать об этом. К примеру, создать файл конфигурации для хранения списка путей к файлам, и в этом списке уже изменять пути. 
Ну, конечно, ещё можно предусмотреть в программе какой-нибудь поиск файла. Но это, сам понимаешь, каково будет по скорости - искать новый каталог файла по всему винту. smile 

Автор: Akella 15.10.2009, 09:23
Советую не делать так. А реализовать работу с файлами, как это сделано во многих нормальных программах - работа с файлами в папке Мои документы или лучше в папке "C:\Documents and Settings\имя_пользователя\Application Data", в противном случае винда может не дать программе доступ к файлу, особенно если программа будет установлена в папке Program files. Всё равно когда-нибудь прийдётся переделывать, не сегодня, так через год. Так почему бы сразу не реализовать правильно?

Автор: larinva 15.10.2009, 10:20
Всем сп-бо направление понял тема может быть закрыта! smile 

Автор: malor 11.11.2011, 15:51
Цитата(Akella @  15.10.2009,  09:23 Найти цитируемый пост)
А реализовать работу с файлами, как это сделано во многих нормальных программах - работа с файлами в папке Мои документы или лучше в папке "C:\Documents and Settings\Имя_пользователя\Application Data"

Какая переменная окружения соответствует папке "Мои документы" ?

Автор: northener 11.11.2011, 20:14
Советую использовать функцию SHGetSpecialFolderPath с параметром CSIDL_MYDOCUMENTS

Автор: CodeMonkey 11.11.2011, 22:34
Подгоню ссылочку: http://www.gunsmoker.ru/2011/09/blog-post_11.html (код в конце).

Автор: northener 11.11.2011, 23:46
Цитата(CodeMonkey @  11.11.2011,  22:34 Найти цитируемый пост)
Подгоню ссылочку

Хм. Эту статью я ещё не видел.
И "FOLDERID" меня заинтересовал. У вас, Александр всегда под рукой ссылки. Не могли бы вы подкинуть сюда ещё и ссылку на статью или что-либо другое, что объяснит чем "старый"вызов ShGet(Special)Folderxxx может обломаться на Vista+.
Есть у меня и "особый/шкурный" интерес. smile

Автор: CodeMonkey 11.11.2011, 23:51
Он должен нормально работать, ИМХО. Но пути к новым папкам через него не получить - нет констант.

Автор: northener 12.11.2011, 00:21
Цитата(CodeMonkey @  11.11.2011,  23:51 Найти цитируемый пост)
Но пути к новым папкам через него не получить - нет констант.

А какие "новые" папки имеются в виду?
Или это "задел" на "новые разработки"?

Автор: Lols 12.11.2011, 02:49
Цитата(CodeMonkey @ 11.11.2011,  23:51)
Он должен нормально работать, ИМХО. Но пути к новым папкам через него не получить - нет констант.

Ну, это тогда просто нужно будет учесть и все - не смертельно. Или я не права?

Автор: CodeMonkey 12.11.2011, 03:13
Цитата(northener @  12.11.2011,  01:21 Найти цитируемый пост)
А какие "новые" папки имеются в виду?


Физические папки: FOLDERID_Contacts, FOLDERID_DeviceMetadataStore, FOLDERID_DocumentsLibrary, FOLDERID_Downloads, FOLDERID_GameTasks, FOLDERID_ImplicitAppShortcuts, FOLDERID_Libraries, FOLDERID_Links, FOLDERID_LocalAppDataLow, FOLDERID_MusicLibrary, FOLDERID_PhotoAlbums, FOLDERID_PicturesLibrary, FOLDERID_Playlists, FOLDERID_ProgramFilesX64, FOLDERID_ProgramFilesCommonX64, FOLDERID_Public, FOLDERID_PublicDownloads, FOLDERID_PublicGameTasks, FOLDERID_PublicLibraries, FOLDERID_PublicRingtones, FOLDERID_QuickLaunch, FOLDERID_RecordedTVLibrary, FOLDERID_Ringtones, FOLDERID_SampleMusic, FOLDERID_SamplePictures, FOLDERID_SamplePlaylists, FOLDERID_SampleVideos, FOLDERID_SavedGames, FOLDERID_SavedSearches, FOLDERID_SidebarDefaultParts, FOLDERID_SidebarParts, FOLDERID_UserPinned, FOLDERID_UserProfiles, FOLDERID_UserProgramFiles, FOLDERID_UserProgramFilesCommon, FOLDERID_VideosLibrary

Виртуальные папки: FOLDERID_AddNewPrograms, FOLDERID_AppUpdates, FOLDERID_ChangeRemovePrograms, FOLDERID_ConflictFolder, FOLDERID_Games, FOLDERID_HomeGroup, FOLDERID_OriginalImages, FOLDERID_SEARCH_CSC, FOLDERID_SEARCH_MAPI, FOLDERID_SearchHome, FOLDERID_SyncManagerFolder, FOLDERID_SyncResultsFolder, FOLDERID_SyncSetupFolder, FOLDERID_UsersFiles, FOLDERID_UsersLibraries

Я выделил жирным интересные (на мой взгляд) папки.

Цитата(Lols @  12.11.2011,  03:49 Найти цитируемый пост)
Ну, это тогда просто нужно будет учесть и все - не смертельно. Или я не права? 


Разумеется.

Хотя, смотря как "учитывать". К примеру, папка для сейвов игр. В XP мы можем учесть её отсутствие и писать в AppData - окей. Но если ровно же этот код мы будем использовать и в Vista+, то получится, что мы его пишем не туда - вот тебе и "учли".

Добавлено через 6 минут и 25 секунд
Итого: если в программе мы хотим работать только с папками, которые входят в CSIDL, то использовать ShGet(Special)FolderXXX - это окей. Это будет работать и работать корректно. Никаких проблем тут нет, обратная совместимость - конёк Microsoft. Да, можно проверять версию системы и использовать функции ShGetKnownFolderXXX на Vista+. Но вы от этого ничего не выиграете, а даже скорее наоборот - теперь в вашем коде две ветки (и в два раза больше кода).

Но если нам надо получать хотя бы одну новую папку (из Vista+), то (ИМХО) лучше использовать ShGet(Special)FolderXXX-функции на XP и ниже, и ShGetKnownFolderXXX - на Vista и выше. Чисто по соображениям единообразия.

Автор: northener 12.11.2011, 03:28
Цитата(CodeMonkey @  12.11.2011,  03:13 Найти цитируемый пост)
Я выделил жирным интересные (на мой взгляд) папки.

Ну мне  это "не интересно".
Ну а в целом, спасибо!

Автор: Akella 12.11.2011, 21:12
Цитата(malor @  11.11.2011,  15:51 Найти цитируемый пост)
Какая переменная окружения соответствует папке "Мои документы" ? 


Код

 with TRegistry.Create do
   try
     RootKey := HKEY_CURRENT_USER;
     OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders', false);
     sMyDocAppPath := IncludeTrailingPathDelimiter(ReadString('Personal'));
   finally
     CloseKey;
     free;
   end;


Автор: northener 13.11.2011, 00:25
Цитата(Akella @  12.11.2011,  21:12 Найти цитируемый пост)
 with TRegistry.Create do

А кто и где нам в Микрософте обещал, что реестр для всех версий Винды будет совместим?
Обещали нам только, что API'шные функции будут совместимы (в меру возможностей).

Автор: CodeMonkey 13.11.2011, 00:26
Цитата(Akella @  12.11.2011,  22:12 Найти цитируемый пост)
with TRegistry.Create do


От тебя не ожидал.

http://www.transl-gunsmoker.ru/2008/12/shell-folders.html

Автор: Akella 14.11.2011, 10:52
Цитата(northener @  13.11.2011,  00:25 Найти цитируемый пост)
P.S. Второй раз за рабочий день спорю с модератором. 
Ведь сколько раз предупреждал себя, что этого делать не нужно! :( 


ты путаешь функции модератора и обычного пользователя форума, не делай  этого

Добавлено через 4 минуты и 24 секунды
Цитата(CodeMonkey @ 13.11.2011,  00:26)
Цитата(Akella @  12.11.2011,  22:12 Найти цитируемый пост)
with TRegistry.Create do


От тебя не ожидал.

http://www.transl-gunsmoker.ru/2008/12/shell-folders.html

судя по этой ссылке: http://msdn.microsoft.com/en-us/library/bb762494(v=VS.85).aspx

константа CSIDL_MYDOCUMENTS появилась в Version 6.0. (http://msdn.microsoft.com/en-us/library/bb776779(v=VS.85).aspx)

А до этого её не было. Или я ошибаюсь?

Таким образом в Windows 2000 программы выдаст исключение, так?

Автор: CodeMonkey 14.11.2011, 14:49
Цитата(Akella @  14.11.2011,  11:52 Найти цитируемый пост)
судя по этой ссылке: http://msdn.microsoft.com/en-us/library/bb...4(v=VS.85).aspx

константа CSIDL_MYDOCUMENTS появилась в Version 6.0. (6.0    Windows XP)

А до этого её не было. Или я ошибаюсь?

Таким образом в Windows 2000 программы выдаст исключение, так? 


Ты смотришь на виртуальную My documents. Она - с XP, да.

А физическая My documents была и до этого. 

Автор: Akella 14.11.2011, 17:06
не понял :(

Автор: CodeMonkey 14.11.2011, 17:07
По твоей ссылке см. CSIDL_PERSONAL

Автор: Akella 14.11.2011, 21:19
Т.е. мне предварительно нужно вычислить версию винды, а уж потом выбирать, какую константу использовать?

Автор: northener 14.11.2011, 23:08
Цитата(Akella @  14.11.2011,  10:52 Найти цитируемый пост)
ты путаешь функции модератора и обычного пользователя форума, не делай  этого

Понял. smile Некоторые другие модераторы придерживаются других правил.

Добавлено @ 23:12
Цитата(Akella @  14.11.2011,  21:19 Найти цитируемый пост)
Т.е. мне предварительно нужно вычислить версию винды, а уж потом выбирать, какую константу использовать? 

Имхо, Винда сама разберется куда писать и откуда читать, если использовать именно CSIDL_PERSONAL.

Автор: CodeMonkey 15.11.2011, 08:46
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
Т.е. мне предварительно нужно вычислить версию винды, а уж потом выбирать, какую константу использовать? 


Нет, эти две константы равны. Просто до XP Мои документы была физической папкой.

Автор: Akella 17.11.2011, 12:46
Цитата(northener @  14.11.2011,  23:08 Найти цитируемый пост)
Имхо, Винда сама разберется куда писать и откуда читать, если использовать именно CSIDL_PERSONAL.

тогда зачем вторая константа?

Добавлено через 1 минуту и 1 секунду
Цитата(CodeMonkey @ 15.11.2011,  08:46)
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
Т.е. мне предварительно нужно вычислить версию винды, а уж потом выбирать, какую константу использовать? 


Нет, эти две константы равны. Просто до XP Мои документы была физической папкой.

в семёрке папка Documents тоже физическая

Добавлено через 2 минуты и 43 секунды
Где я не прав? Путь к папке Мои документы в реестре живёт уже лет 20. Вы думаете, что с помощью константы винда как-то по другому путь вычисляет? В итоге всё равно всё сводится к реестру.

Автор: CodeMonkey 17.11.2011, 15:36
Цитата(Akella @  17.11.2011,  13:46 Найти цитируемый пост)
тогда зачем вторая константа?


Это не вторая константа. Это одна и та же константа. Но у неё два имени.

Её второе имя добавили в XP. До XP была только PERSONAL.

Цитата(Akella @  17.11.2011,  13:46 Найти цитируемый пост)
в семёрке папка Documents тоже физическая


Вообще-то в Win7 нет папки Мои документы. Если у тебя Win7 стоит - попробуй тыкнуть в "Документы". Увидишь интересную надпись "Documents Library; includes: 2 location(s)".

Цитата(Akella @  17.11.2011,  13:46 Найти цитируемый пост)
Где я не прав?


Ты про что конкретно? Ты дофига где не прав smile  (не сочти за наезд)

1. 
Цитата(Akella @  12.11.2011,  22:12 Найти цитируемый пост)
sMyDocAppPath := IncludeTrailingPathDelimiter(ReadString('Personal'));


Где не прав: http://www.transl-gunsmoker.ru/2008/12/shell-folders.html 

Чёрным по белому разработчик Windows говорит, что твой способ - неправильный. 

Специально для тебя в Windows 7 в том ключе создали значение "!Do not use this registry key" с данными "Use the SHGetFolderPath or SHGetKnownFolderPath function instead".

2. 
Цитата(Akella @  14.11.2011,  11:52 Найти цитируемый пост)
Таким образом в Windows 2000 программы выдаст исключение, так? 


Где не прав: CSIDL_PERSONAL была всегда.

3. 
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
Т.е. мне предварительно нужно вычислить версию винды, а уж потом выбирать, какую константу использовать? 


Где не прав: CSIDL_MYDOCUMENTS = CSIDL_PERSONAL.

ShlObj.h:
Код
#define CSIDL_MYDOCUMENTS               CSIDL_PERSONAL
#define CSIDL_PERSONAL                  0x0005       


4. 
Цитата(Akella @  17.11.2011,  13:46 Найти цитируемый пост)
в семёрке папка Documents тоже физическая


Где не прав: в Windows 7 нет папки Мои документы. Есть библиотека "Документы".

Даже если брать утверждение для XP, это не совсем верное.

До XP Мои документы была физической папкой, представленной на рабочем столе. Т.е. прямо в папке рабочего стола была физическая папка Мои документы. И ей соответствовала CSIDL_PERSONAL. Всегда. Ферштейн?

А в XP Мои документы более не является физической папкой. Если ты посмотришь на физическое хранилище рабочего стола, то никакой Мои документы там не будет. Понимаешь? У Моих документов есть физическое хранилище, но сама папка, начиная с XP, - виртуальная.

В этом же время ввели псевдоним CSIDL_MyDocuments. Он тождественно равен CSIDL_PERSONAL.

PIDL к виртуальной папке (виртуальная Мои документы на рабочем столе) или путь к физической (физическое хранилище Мои документы) - возвращаются разными функциями. 

Вот так надо трактовать документацию.

5. 
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
Путь к папке Мои документы в реестре живёт уже лет 20


Где не прав: люди перебегают на красный свет со времён появления светофоров. Из чего не следует, что это правильно.

6. 
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
Вы думаете, что с помощью константы винда как-то по другому путь вычисляет?


Где не прав: "знали ли вы, что если вы ни разу не открывали свою папку "Шрифты", и никакая программа ни разу не вызывала SHGetSpecialFolderLocation(CSIDL_FONTS), то никакой записи "Fonts" в ключе "Shell Folders" не будет?"

Как видишь, по другому. Функция возвращает результат всегда, реестр - не всегда.

7. 
Цитата(Akella @  14.11.2011,  22:19 Найти цитируемый пост)
В итоге всё равно всё сводится к реестру.


Где не прав: http://www.transl-gunsmoker.ru/2008/12/shell-folders.html 

Чёрным по белому разработчик Windows говорит, что реестр не является первоисточником этой информации. Это поведение было убрано ещё в бетах Windows 95.

Добавлено через 4 минуты и 1 секунду
Чтобы было совсем ясно: есть разница между "это - работает" и "это - правильно".

Автор: Akella 18.11.2011, 17:41
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Её второе имя добавили в XP. До XP была только PERSONAL.

Зачем мне использовать её второе имя.
У константы не может быть два имени. Это просто два константы или две переменных, ссылающиеся на одно и тоже значение. Мне так кажется.

Добавлено @ 17:42
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Вообще-то в Win7 нет папки Мои документы. Если у тебя Win7 стоит - попробуй тыкнуть в "Документы". Увидишь интересную надпись "Documents Library; includes: 2 location(s)".


а где я писал, что Мои документы в семёрке физическая папка smile

Добавлено @ 17:42
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Ты про что конкретно? Ты дофига где не прав   (не сочти за наезд)

ФСЁ, ты забанен  smile

Добавлено @ 17:44
Цитата
Другими словами, ключ реестра "Shell Folders" существует только затем, чтобы на RTM версии Windows 95 могли работать четыре программы, написанные в 1994-м году. 


но это работает до сих пор, уже почти 20 лет smile

Добавлено @ 17:47
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Где не прав: CSIDL_PERSONAL была всегда.

Зачем тогда CSIDL_MYDOCUMENTS?

Это вносит путаницу.

Добавлено @ 17:49
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Т.е. прямо в папке рабочего стола была физическая папка Мои документы.

и в Win2000?

Добавлено через 10 минут
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
но сама папка, начиная с XP, - виртуальная.

с трудом верится

Добавлено через 11 минут и 20 секунд
Цитата(CodeMonkey @  17.11.2011,  15:36 Найти цитируемый пост)
Где не прав: "знали ли вы, что если вы ни разу не открывали свою папку "Шрифты", и никакая программа ни разу не вызывала SHGetSpecialFolderLocation(CSIDL_FONTS), то никакой записи "Fonts" в ключе "Shell Folders" не будет?"


но это не про папку Мои документы

Добавлено через 13 минут и 23 секунды
В любом случае я понял. Короче наворотили разработчики винды.....

Автор: northener 18.11.2011, 23:43
Цитата(Akella @  18.11.2011,  17:41 Найти цитируемый пост)
В любом случае я понял.

Т.е. Это в сочетании с вышенаписанным следует читать "Понял, но не принял"!

Цитата(Akella @  18.11.2011,  17:41 Найти цитируемый пост)
Короче наворотили разработчики винды...

А разве мы все (разработчики) не "обязаны" поддерживать обратную совместимость? А порой из-за изначальной непродуманности проекта обратная совместимость может быть реализована только костылями. :(

Автор: Lols 19.11.2011, 01:55
Уважаемые, определитесь про 7ю винду - тут уже у меня шкурный интерес. Так что с папкой?

Автор: northener 19.11.2011, 02:02
Цитата(Lols @  19.11.2011,  01:55 Найти цитируемый пост)
Уважаемые, определитесь про 7ю винду - тут уже у меня шкурный интерес. Так что с папкой? 

А какие проблемы с папкой?

Автор: northener 19.11.2011, 02:29
Используйте WinAPI-шные функции типа ShGetxxx и "пребудет вам щастье" smile

Автор: Akella 19.11.2011, 10:31
Цитата(Lols @ 19.11.2011,  01:55)
Уважаемые, определитесь про 7ю винду - тут уже у меня шкурный интерес. Так что с папкой?

А что с папкой?

Добавлено через 44 секунды
По-моему тут нам уже разъяснили более чем достаточно. Разве нет?

Автор: Akella 19.11.2011, 16:01
Модератор: Сообщение скрыто.

Автор: Akella 23.12.2011, 14:31
Да, Вы оказались правы.
Пришлось использовать SHGetSpecialFolderPath с параметром CSIDL_PERSONAL

А вот параметр CSIDL_MYDOCUMENTS не помог :(

Код

procedure GetUserDocsScanFilterPath();
var
  Path: LPTSTR;
begin
  Path := LPTSTR(AllocMem(MAX_PATH));
  try

  SHGetSpecialFolderPath(application.ActiveFormHandle, Path , CSIDL_PERSONAL, false);
  sUserDocsScaniFilterPath := IncludeTrailingPathDelimiter(Path ) + 'Сканфильтр\';

  if not DirectoryExists(sUserDocsScaniFilterPath) then
    ForceDirectories(sUserDocsScaniFilterPath);

  finally
    FreeMem(Path);
  end;
end;


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