[Форум] [Помощь] [Поиск] [Выйти] |
Добро пожаловать, User |
|
|
| ||
Известно, что где- то на диске есть файл abcde.exe. Как определить полный путь к файлу, зная только его имя и присвоить значение пути переменной ээээ.... PATH:string; В книжках, что только не пишут, кроме этого! |
| ||
Дерево каталогов обойди. Почитай про рекурсию (простейший способ). |
| ||
Пойду почитаю... как дерево обойти. Рекурсия... рекурсия... где- то видел в оглавлениях. ----------------- МДЯ... Как я понял, рекурсия- это нечто абстрактное. Понятие, А не функция, процедура или метод (простите, не в суе будет упомянут) Таким образом Вашу фразу можно прочитать так: Чтобы найти, попробуй поискать. НЕ ЗНАЮ Я КАК. Наверняка у кого- нить в загашнике есть готовая функция. Может лучше НА ЕЕ примере рекурсию изучить. |
| ||
Если файл входит в саму ОС, то может находится на диске на котором установлена ОС. Если к этому нет возражений, то можно сократить поиски одним диском и даже одной папкой... Если же нет... Придётся провести поиск на всех несьемных носителях на компьютере. Вообщем скоро дам ответ... PS. Письмо получил, но что-то как не отправляю Вам на почту ничего не приходит :) |
| ||
Вот ответ: function GetDOSEnvVar(const VarName: string): string; var i: integer; begin Result := ''; try i := GetEnvironmentVariable(PChar(VarName), nil, 0); if i > 0 then begin SetLength(Result, i); GetEnvironmentVariable(Pchar(VarName), PChar(Result), i); end; except Result := ''; end; end; function CheckFile(NameFile: string): string; var slMy: TStringList; Str, Delimiter, temp: string; i: integer; begin result:=''; slMy:=TStringList.create; Str:=GetDOSEnvVar('Path'); Delimiter:=';'; slMy.Text:=StringReplace(Str,Delimiter,#13#10,[rfReplaceAll]); for i:=0 to slMy.count-1 do begin temp:=ExcludeTrailingBackslash(slMy[ i ])+''+NameFile; if fileexists(temp) then begin result:=temp; break; end; end; slMy.free; end; Первая функция получает переменные окружения. Вторая проверяет файл на существование. Пример использования: s:=CheckFile('mspaint.exe'); У меня в s содержится: c:windowssystem32mspaint.exe Если файл не найден ни в одной из переменных окружения то функция возвращает ''. PS. Если будешь кидать в support.pas, то добавь в uses модуль classes. Выглядеть будет так: uses windows, sysutils, messages, forms, registry, classes; Будут вопросы спрашивай ... Хотел скинуть на e-mail но надежды на удачный исход нет :) |
| ||
ёлки, программисты активизировались :) дельфи я видел 1 раз из-за плеча коллеги, примеров т.е. не будет, но думаю, что прав Xanth. ведь где- то на диске есть файл это совсем не файл в %PATH% вариация решения Xanth - вывести диалог выбора файла, пусть пользователь сам укажет, останется вернуть путь и обработать как надо а бряк из цикла по каталогам %PATH% подразумевает, что искомый файл один, а если они в каждом заботливо разложены, с одинаковым именем, но разные версии скажем, и нужен не первый попавшийся ? :) |
| ||
void WorkInDir(TCHAR* szDirPath)//Обрабатывает указанную директорию { WIN32_FIND_DATA FileData; HANDLE hSearch; DWORD dwAttrs; DWORD dwStrLen; TCHAR* chSearchDir = new TCHAR[_tcslen(szDirPath) + 4]; _tcscpy(chSearchDir,szDirPath); _tcscat(chSearchDir,_T(*.*)); BOOL fFinished = FALSE; hSearch = FindFirstFile(chSearchDir, &FileData); if (hSearch == INVALID_HANDLE_VALUE) { delete chSearchDir; return; } while (!fFinished) { if (!((_tcscmp(FileData.cFileName,_T(.)) == 0) !! (_tcscmp(FileData.cFileName,_T(..)) == 0))) { dwAttrs = FileData.dwFileAttributes; if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) {//Если это директория то рекурсивно заходим в нее TCHAR* chTemp = new TCHAR[_tcslen(szDirPath) + _tcslen(FileData.cFileName) + 2]; _tcscpy(chTemp,szDirPath); _tcscat(chTemp,FileData.cFileName); _tcscat(chTemp,_T(\)); WorkInDir(chTemp);//Рекурсивный вызов delete chTemp; } else {//Если это просто файл то обрабатываем его TCHAR* chTemp = new TCHAR[_tcslen(szDirPath) + _tcslen(FileData.cFileName) + 1]; _tcscpy(chTemp,szDirPath); _tcscat(chTemp,FileData.cFileName); if (dwAttrs & FILE_ATTRIBUTE_READONLY) { SetFileAttributes(chTemp, dwAttrs ^ FILE_ATTRIBUTE_READONLY); } #pragma warning( disable : 4267 ) dwStrLen = _tcslen(chTemp); #pragma warning( default : 4267 ) if (g_fMustFreeThread == TRUE) { delete chTemp; delete chSearchDir; return; } if (CheckFile(chTemp, _T(abcde.exe))) { // Здесь делаем с файлом то что на надо } delete chTemp; } } if (!FindNextFile(hSearch, &FileData)) { if (GetLastError() == ERROR_NO_MORE_FILES) { fFinished = TRUE; } else { delete chSearchDir; return; } } } FindClose(hSearch); delete chSearchDir; } - извиняюсь что не на Delphi, и атрибут только для чтения можно не снимать если не собираетесь изменять файл. |
| ||
кстати g_fMustFreeThread - это volatile переменная на случай если очень долго ищет :) (разумеется искать лучше в отдельном потоке) |
| ||
настальжи от этих findfirst, таким бородатым досом повеяло :) бтв, пример из UNIX Code Migration Guide, chapter 9 понятнее, а posix который там рядом показан так просто красив :-) |
| ||
bargan: а кто директорию указывать будет ?? :))) или опять искать будем по всем дискам :)) САНЬКА: если уж так охото искать рекурсивно по всем дискам, то есть компонент TFileFinder ищет многопотоково, ориентирован как раз на поиск, хоть на сетевых дисках, хоть где... По-моему слишком громоздкое решение для простой задачи. Как говорится тут практически пишется замена ShellExecute. А если вспомнить то ShellExecute так и ищет :)) (в смысле в Path)... А вот если в Path моя функция не найдёт, можно и по всем дискам прошвырнутся ?? Как думаете ?? Получается оптимальное решение для поставленной задачи! |
| ||
я думаю, что надо добиться правильной постановки вопроса :) а то в итоге может оказаться, что ищется нечто а-ля ворд, и взять это проще из, скажем, ассоциаций вторую часть вопроса будете отвечать? :) которая про путь менять ;-) |
| ||
САНЬКА: насчёт ассоциаций я уже давал ответ ;) см. предыдущая тема... Насчёт второго вопроса (как я его понял): найти самую позднюю версию файла? Если мне память не изменяет :) есть функция GetFileVersionInfo, которая вместе с VerQueryValue и даёт нам искомые данные, а именно: ... DWORD dwFileVersionMS; DWORD dwFileVersionLS; DWORD dwProductVersionMS; DWORD dwProductVersionLS; DWORD dwFileFlagsMask; DWORD dwFileFlags; DWORD dwFileOS; DWORD dwFileType; DWORD dwFileSubtype; DWORD dwFileDateMS; DWORD dwFileDateLS; ... Я думаю так :) Если конечно кто-то захочет могу переписать :) мою функцию... |
| ||
:) не, вроде второй вопрос в этой же теме Как определить полный путь(1) к файлу, зная только его имя и присвоить(2) значение пути переменной ээээ.... PATH:string а про версию это к тому было, что в каждом каталоге, что в path, может находится файл abcde.exe, теоретически :) а разбор в функции останавливается на первом |
| ||
Так что-то я ничего не понимаю :) Это что надо написать как присвоить получившееся значение переменной PATH ??? :) Или я совсем сошёл с ума... |
| ||
Да! А вы тут накрутили. Смотрится красиво, конечно. Я интересовался не системными пафами. А хотел лишь зная название фуйла, отыскать его на диске и присвоить значение ПУТЬ строковой переменной, чтобы потом ее использовать. Простите, если проставил вопрос в неприличной позе. ----- Юрий! Респект. |
| ||
deadman: так а почему нет? environment унаследовали, поменять можем, а если речь идёт о родительском? |
| ||
То есть НЕТ! красивое название PATH не относится к системным Это просто совпадение. Юрий, ну Вы- то в курсе что Я не в состоянии еще задавать ТАКИЕ вопросы- не по Хуану сомбреро! --- или я тоже уже запутался. |
| ||
deadmen: void WorkInDir(TCHAR* szDirPath)//Обрабатывает указанную директорию - по моему насчет директории, всем понятно. |
| ||
Поиск по сети без компонентов: void ScanNetwork() // Сканирует сетевые файлы { LPSERVER_INFO_101 pBuf = NULL; LPSERVER_INFO_101 pTmpBuf; DWORD dwLevel = 101; DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; DWORD dwEntriesRead = 0; DWORD dwTotalEntries = 0; DWORD dwTotalCount = 0; DWORD dwServerType = SV_TYPE_ALL; // all servers DWORD dwResumeHandle = 0; NET_API_STATUS nStatus; LPTSTR pszServerName = NULL; DWORD i; PSHARE_INFO_502 BufPtr,p; NET_API_STATUS res; DWORD er=0,tr=0,resume=0, j; TCHAR* lpszFullNetPath; lpszFullNetPath = new TCHAR[1024]; // // Call the NetServerEnum function to retrieve information // for all servers, specifying information level 101. // nStatus = NetServerEnum((LPCSTR) pszServerName, dwLevel, (LPBYTE *) &pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries, dwServerType, NULL, &dwResumeHandle); // // If the call succeeds, // if ((nStatus == NERR_Success) !! (nStatus == ERROR_MORE_DATA)) { if ((pTmpBuf = pBuf) != NULL) { // // Loop through the entries and // print the data for all server types. // for (i = 0; i < dwEntriesRead; i++) { assert(pTmpBuf != NULL); if (pTmpBuf == NULL) break; // В pTmpBuf->sv101_name хранится название очередного сервера //********************************************** // // Call the NetShareEnum function; specify level 502. // if (i == 0) { pTmpBuf++; dwTotalCount++; continue; } do // begin do { res = NetShareEnum ((LPSTR)pTmpBuf->sv101_name, 502, (LPBYTE *) &BufPtr, -1, &er, &tr, &resume); // // If the call succeeds, // if(res == ERROR_SUCCESS !! res == ERROR_MORE_DATA) { p=BufPtr; // // Loop through the entries; // print retrieved data. // for(j=1;j<=er;j++) { //В p->shi502_netname хранится имя ресурса //********************************************** _tcscpy(lpszFullNetPath,_T(\\)); _tcscat(lpszFullNetPath,(TCHAR*) pTmpBuf->sv101_name); _tcscat(lpszFullNetPath,_T(\)); _tcscat(lpszFullNetPath,(TCHAR*) p->shi502_netname); _tcscat(lpszFullNetPath,_T(\)); WorkInDir(lpszFullNetPath); //********************************************** p++; } // // Free the allocated buffer. // NetApiBufferFree(BufPtr); } } // Continue to call NetShareEnum while // there are more entries. // while (res==ERROR_MORE_DATA); // end do //********************************************** pTmpBuf++; dwTotalCount++; } } } // // Free the allocated buffer. // if (pBuf != NULL) NetApiBufferFree(pBuf); delete lpszFullNetPath; } |
| ||
olamot: Спасибо ещё раз :) Всегда приятно работать когда это кто-то оценит :) bargan: А Вы думаете я не догадался что он обрабатывает указанную директорию ? А кто же укажет где у нас этот файл то лежит ? Может просканируем все диски пользователя, все его тысячи файлов ? Меня такая скорость бы не удовлетворила... Здесь просто другой вопрос надо найти файлы входящие в ОС. Это гораздо проще и эффективнее (а самое главное быстрей) сделать через переменные окружения. Извините если я понял вопрос не правильно, но по-моему всё так. И ещё если хочется использовать мощные функции поиска можно воспользоваться уже упомянутым TFileFinder он поддерживает множество задаваемых директорий поиска, кучу масок файлов и главное не допускает дублирования в таких случаях: \ \server <== (*) d:win95 d:win95 emp <== (*) Каталоги (*) будут игнорироваться т.к. [\server] входит в множество [\], а [d:win95 emp] входит в [d:win95] А также: Фильтрование файлов. Гарантируется, что один и тот же файл не будет дважды и более возвращен. Это может случиться при поиске файлов по нескольким маскам (Например поиск ведется по маскам [some*.*] и [*.txt] в этом случае файл somebody.txt попадает в две категории) По-моему значительный компонент. Ещё раз оговорюсь это лично моё мнение. САНЬКА: Т.е. вы хотите изменить переменные окружения ? Это же легко. Может я не совсем правильно Вас понимаю ? |
| ||
olamot В стране чудес! P.S. Просьба на Сях не кодить! Я и без того юзаю глюки. (свои). |
| ||
А что за глюки то :) может можно исправить ? Своё предложение (насчёт beta-тестирования) держу в уме :) |
| ||
Да вот провел ядерные испытания с поиском... В двух словах. В Вин98 msPaint лежит в папке Аксессуары. Получаю естессна фигу, а не дорогу в рай. --------- Может через реестр? извините, если глупсть --------- Какое там Бета- альфа- омега тестирование, когда прога себе файл найти не может. |
| ||
Так значит это из моего примера, как я понял ? Напиши точно то что она выводит (в Win98) ... А в XP что без проблем ? PS. В ICQ вылезть не можешь ? |
| ||
Я рискну напомнить историю наших заморочек. Мне нужно было чтобы окна нужных мне программ не проваливались под другие окна. Эти проги- фонограф и Пэинт. В любезно предложенной вами функции требуется ввод полного пути к этим прогам. Может поити просто: для ~ХР 1)По функции GetWindowsDirectory определить каталог Windows 2)К ней прибавить system32- там нашарить и фонограф и Пэинт. для ~98 1)По функции GetWindowsDirectory определить каталог Windows там нашарить фонограф 2)Жестко прописать папку C:Program filesaccessories там нашарить и Пэинт. КАк Вы думаете, это будет жизнеустойчивый способ? |
| ||
Для такой задачи да. Поверь мне использовать универсальные методы лучше! Только единственное ещё прошу (на коленях почти :)) расскажи об ошибке больше самому жутко интересно! PS. Единственное надо будет ещё систему определить. Так что давай лучше ошибку найдём! Через переменные окружения ещё много интересного можно найти! |
| ||
Насчет что она выводит В 98 Фонограф лежит в папке Виндовоз- путь к нему определяется. Пэйнт лежит в аксессуарах, путь к нему не определяется. (пустая строка) в ХР не пробовал. Если 98-й слопает и ХР тоже. Это видно из подхода. Не так ли? Вот Блин! блин! блин! |
| ||
Напиши что выводит программа..... Понял ничего не выводит :))) она у же у меня так настроена :))) Тут знаешь в чём проблема: акссесуары не внесены в переменные окружения! Напиши следующее (кинь на форму Memo): Memo1.lines.add(GetDOSEnvVar('Path')); Ответ скинь сюда.... |
| ||
Нисего не выводит- кликаю по кнопке, на лэйбле ничего не появляется. Все. Ничего не виснет, не ругается. ... просто тупо смотрит на меня... я на нее. Оба счастливы- каждый по своему. |
| ||
Прочти последнее :))) |
| ||
Предлагаю Так! Пусть эти окна проваливаются в тар- тарары пока. По ALT-TAB их все равно можно достать! А пока дописать эту прогу. |
| ||
ОК |
| ||
САНЬКА: Сегодня ночью придумал такую схемку: 1. запускаем программу 2. ищем пути к программам в Path, если находим 9, иначе 3 3. ищем поиском в папке с установленной Windows, если находим 8, иначе 4 4. ищем на диске с ОС, если находим 8, иначе 5 5. ищем на всех дисках пользователя, если находим 8, иначе 6 6. предлагаем пользователю указать путь в программе, если указывает 8, иначе 7 7. говорим мол без этой программы работать никак не можем и выходим 8. заносим путь в переменную окружения Path далее 9 9. запуск программы Получается если в Path прога есть то всё нормально, если же нет проищем все папки и всё будет супер. Тут как раз и воспользуемся изменением переменных окружения :) |
| ||
Причём тот алгоритм что я описал можно легко загнать в программу установки. И она будет выполнятся только один раз за всю историю работы программы. Получается пользователи довольны (всё работает быстро), а мы выполнили поставленную задачу. Если бы я пользовался прогой у которой был бы написанный мной алгоритм, наверное сильно бы перепугался :) когда она при запуске вдруг резко зашевелила винчестером :). Поэтому лучше этот алгоритм выполнять один раз и навсегда! |
| ||
САНЬКА: Вроде наконец понял что Вы хотели сказать примером своей программы. Получается на время работы второй задачи переменная окружения test123 будет иметь значение test2, а после выполнения всё вернётся на свои места. Т.е. фактически будем иметь две копии переменной окружения test123. Я всё правильно понял? |
| ||
Пока дописываю пррогу как есть. Как подумаю, ведь еще хелп какой- то нужен будет!!!!! |
| ||
ну почему я. если подходить буквоедски к вопросу, то результаты поиска задача1 складывает в переменную окружения, задача2 результатами пользуется. эмулирую: C:>set TEST123 Environment variable TEST123 not defined C:>set TEST123=test1 C:>set TEST123 TEST123=test1 (1) задача1 запустилась и отработала :) C:>cmd /c set TEST123=test2 && set TEST123 TEST123=test2 (2) тут запускаем задачу2 C:>set test123 TEST123=test1 |
| ||
Сегодня не кому ответить не смогу. Выгоняют причём так сильно что стены трещат..... Заработался :)))) Завтра обязательно всем отвечу всё решу! Век воли не видать! |