WEB форумы на jedi
[Форум] [Помощь] [Поиск] [Выйти]
Добро пожаловать, [info]User

WEB форумы на jedi [ПОИСК] [Архив до 03.2006]

Тема Детский вопрос. DELPHI К предыдущему сообщению На следующее сообщение Программирование

Отправил olamot в 18:33 30.11.2004[Ответить]
Известно, что где- то на диске есть файл abcde.exe.
Как определить полный путь к файлу, зная только его имя и присвоить значение пути переменной ээээ....
PATH:string;

В книжках, что только не пишут, кроме этого!


Отправил Xanth в 20:13 30.11.2004[Ответить]
Дерево каталогов обойди. Почитай про рекурсию (простейший способ).


Отправил olamot в 20:47 30.11.2004[Ответить]
Пойду почитаю... как дерево обойти.
Рекурсия... рекурсия... где- то видел в оглавлениях.

-----------------
МДЯ...
Как я понял, рекурсия- это нечто абстрактное. Понятие, А не функция, процедура или метод (простите, не в суе будет упомянут)
Таким образом Вашу фразу можно прочитать так:

Чтобы найти, попробуй поискать.

НЕ ЗНАЮ Я КАК. Наверняка у кого- нить в загашнике есть готовая функция.
Может лучше НА ЕЕ примере рекурсию изучить.


Отправил deadman в 07:40 01.12.2004[Ответить]
Если файл входит в саму ОС, то может находится на диске на котором установлена ОС. Если к этому нет возражений, то можно сократить поиски одним диском и даже одной папкой... Если же нет... Придётся провести поиск на всех несьемных носителях на компьютере.

Вообщем скоро дам ответ...

PS. Письмо получил, но что-то как не отправляю Вам на почту ничего не приходит :)


Отправил deadman в 12:52 01.12.2004[Ответить]
Вот ответ:

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 но надежды на удачный исход нет :)


Отправил CAHbKA в 13:29 01.12.2004[Ответить]
ёлки, программисты активизировались :)
дельфи я видел 1 раз из-за плеча коллеги, примеров т.е. не будет, но думаю, что прав Xanth. ведь где- то на диске есть файл это совсем не файл в %PATH%

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

а бряк из цикла по каталогам %PATH% подразумевает, что искомый файл один, а если они в каждом заботливо разложены, с одинаковым именем, но разные версии скажем, и нужен не первый попавшийся ? :)


Отправил bargan в 13:40 01.12.2004[Ответить]
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, и атрибут только для чтения можно не снимать если не собираетесь изменять файл.


Отправил bargan в 13:49 01.12.2004[Ответить]
кстати g_fMustFreeThread - это volatile переменная на случай если очень долго ищет :) (разумеется искать лучше в отдельном потоке)


Отправил CAHbKA в 14:22 01.12.2004[Ответить]
настальжи от этих findfirst, таким бородатым досом повеяло :)
бтв, пример из UNIX Code Migration Guide, chapter 9 понятнее, а posix который там рядом показан так просто красив :-)


Отправил deadman в 15:58 01.12.2004[Ответить]
bargan: а кто директорию указывать будет ?? :))) или опять искать будем по всем дискам :))
САНЬКА: если уж так охото искать рекурсивно по всем дискам, то есть компонент TFileFinder ищет многопотоково, ориентирован как раз на поиск, хоть на сетевых дисках, хоть где... По-моему слишком громоздкое решение для простой задачи. Как говорится тут практически пишется замена ShellExecute. А если вспомнить то ShellExecute так и ищет :)) (в смысле в Path)... А вот если в Path моя функция не найдёт, можно и по всем дискам прошвырнутся ?? Как думаете ?? Получается оптимальное решение для поставленной задачи!


Отправил CAHbKA в 16:26 01.12.2004[Ответить]
я думаю, что надо добиться правильной постановки вопроса :)
а то в итоге может оказаться, что ищется нечто а-ля ворд, и взять это проще из, скажем, ассоциаций


вторую часть вопроса будете отвечать? :)
которая про путь менять ;-)


Отправил deadman в 17:01 01.12.2004[Ответить]
САНЬКА: насчёт ассоциаций я уже давал ответ ;) см. предыдущая тема... Насчёт второго вопроса (как я его понял): найти самую позднюю версию файла? Если мне память не изменяет :) есть функция GetFileVersionInfo, которая вместе с VerQueryValue и даёт нам искомые данные, а именно:
...
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
...

Я думаю так :) Если конечно кто-то захочет могу переписать :) мою функцию...


Отправил CAHbKA в 17:39 01.12.2004[Ответить]
:)

не, вроде второй вопрос в этой же теме Как определить полный путь(1) к файлу, зная только его имя и присвоить(2) значение пути переменной ээээ.... PATH:string

а про версию это к тому было, что в каждом каталоге, что в path, может находится файл abcde.exe, теоретически :)
а разбор в функции останавливается на первом


Отправил deadman в 17:45 01.12.2004[Ответить]
Так что-то я ничего не понимаю :) Это что надо написать как присвоить получившееся значение переменной PATH ??? :) Или я совсем сошёл с ума...


Отправил olamot в 18:24 01.12.2004[Ответить]
Да!
А вы тут накрутили. Смотрится красиво, конечно.
Я интересовался не системными пафами.
А хотел лишь зная название фуйла, отыскать его на диске и присвоить значение ПУТЬ строковой переменной, чтобы потом ее использовать.

Простите, если проставил вопрос в неприличной позе.
-----
Юрий! Респект.


Отправил CAHbKA в 18:27 01.12.2004[Ответить]
deadman: так а почему нет? environment унаследовали, поменять можем, а если речь идёт о родительском?


Отправил olamot в 18:38 01.12.2004[Ответить]
То есть НЕТ!
красивое название PATH не относится к системным
Это просто совпадение.
Юрий, ну Вы- то в курсе что Я не в состоянии еще задавать ТАКИЕ вопросы- не по Хуану сомбреро!

---
или я тоже уже запутался.


Отправил bargan в 19:13 01.12.2004[Ответить]
deadmen: void WorkInDir(TCHAR* szDirPath)//Обрабатывает указанную директорию

- по моему насчет директории, всем понятно.


Отправил bargan в 19:28 01.12.2004[Ответить]
Поиск по сети без компонентов:

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;
}


Отправил deadman в 20:12 01.12.2004[Ответить]
olamot: Спасибо ещё раз :) Всегда приятно работать когда это кто-то оценит :)

bargan: А Вы думаете я не догадался что он обрабатывает указанную директорию ? А кто же укажет где у нас этот файл то лежит ? Может просканируем все диски пользователя, все его тысячи файлов ? Меня такая скорость бы не удовлетворила... Здесь просто другой вопрос надо найти файлы входящие в ОС. Это гораздо проще и эффективнее (а самое главное быстрей) сделать через переменные окружения. Извините если я понял вопрос не правильно, но по-моему всё так. И ещё если хочется использовать мощные функции поиска можно воспользоваться уже упомянутым TFileFinder он поддерживает множество задаваемых директорий поиска, кучу масок файлов и главное не допускает дублирования в таких случаях:
\
\server <== (*)
d:win95
d:win95 emp <== (*)

Каталоги (*) будут игнорироваться т.к. [\server] входит в множество [\], а [d:win95 emp] входит в [d:win95]

А также:
Фильтрование файлов. Гарантируется, что один и тот же файл не будет дважды и более возвращен. Это может случиться при поиске файлов по нескольким маскам (Например поиск ведется по маскам [some*.*] и [*.txt] в этом случае файл somebody.txt попадает в две категории)

По-моему значительный компонент. Ещё раз оговорюсь это лично моё мнение.

САНЬКА: Т.е. вы хотите изменить переменные окружения ? Это же легко. Может я не совсем правильно Вас понимаю ?


Отправил olamot в 20:29 01.12.2004[Ответить]

olamot В стране чудес!

P.S. Просьба на Сях не кодить! Я и без того юзаю глюки.
(свои).


Отправил deadman в 20:45 01.12.2004[Ответить]
А что за глюки то :) может можно исправить ? Своё предложение (насчёт beta-тестирования) держу в уме :)


Отправил olamot в 21:29 01.12.2004[Ответить]
Да вот провел ядерные испытания с поиском...
В двух словах.
В Вин98 msPaint лежит в папке Аксессуары. Получаю естессна фигу, а не дорогу в рай.
---------
Может через реестр?
извините, если глупсть
---------

Какое там Бета- альфа- омега тестирование, когда прога себе файл найти не может.


Отправил deadman в 21:57 01.12.2004[Ответить]
Так значит это из моего примера, как я понял ? Напиши точно то что она выводит (в Win98) ... А в XP что без проблем ?

PS. В ICQ вылезть не можешь ?


Отправил olamot в 22:12 01.12.2004[Ответить]
Я рискну напомнить историю наших заморочек.
Мне нужно было чтобы окна нужных мне программ
не проваливались под другие окна. Эти проги- фонограф и
Пэинт.
В любезно предложенной вами функции требуется ввод полного пути
к этим прогам.

Может поити просто:
для ~ХР
1)По функции GetWindowsDirectory определить каталог Windows
2)К ней прибавить system32- там нашарить и фонограф и Пэинт.

для ~98
1)По функции GetWindowsDirectory определить каталог Windows
там нашарить фонограф
2)Жестко прописать папку C:Program filesaccessories
там нашарить и Пэинт.

КАк Вы думаете, это будет жизнеустойчивый способ?


Отправил deadman в 22:14 01.12.2004[Ответить]
Для такой задачи да. Поверь мне использовать универсальные методы лучше! Только единственное ещё прошу (на коленях почти :)) расскажи об ошибке больше самому жутко интересно!

PS. Единственное надо будет ещё систему определить. Так что давай лучше ошибку найдём! Через переменные окружения ещё много интересного можно найти!


Отправил olamot в 22:22 01.12.2004[Ответить]
Насчет что она выводит
В 98
Фонограф лежит в папке Виндовоз- путь к нему определяется.
Пэйнт лежит в аксессуарах, путь к нему не определяется.
(пустая строка)

в ХР не пробовал. Если 98-й слопает и ХР тоже. Это видно из подхода. Не так ли?

Вот Блин! блин! блин!


Отправил deadman в 22:24 01.12.2004[Ответить]
Напиши что выводит программа.....

Понял ничего не выводит :))) она у же у меня так настроена :)))

Тут знаешь в чём проблема: акссесуары не внесены в переменные окружения! Напиши следующее (кинь на форму Memo):

Memo1.lines.add(GetDOSEnvVar('Path'));

Ответ скинь сюда....


Отправил olamot в 22:27 01.12.2004[Ответить]
Нисего не выводит- кликаю по кнопке, на лэйбле ничего не появляется. Все. Ничего не виснет, не ругается.
... просто тупо смотрит на меня... я на нее.
Оба счастливы- каждый по своему.


Отправил deadman в 22:28 01.12.2004[Ответить]
Прочти последнее :)))


Отправил olamot в 22:35 01.12.2004[Ответить]
Предлагаю Так!
Пусть эти окна проваливаются в тар- тарары пока.
По ALT-TAB их все равно можно достать!

А пока дописать эту прогу.


Отправил olamot в 22:38 01.12.2004[Ответить]
ОК


Отправил deadman в 07:49 02.12.2004[Ответить]
САНЬКА: Сегодня ночью придумал такую схемку:

1. запускаем программу
2. ищем пути к программам в Path, если находим 9, иначе 3
3. ищем поиском в папке с установленной Windows, если находим 8, иначе 4
4. ищем на диске с ОС, если находим 8, иначе 5
5. ищем на всех дисках пользователя, если находим 8, иначе 6
6. предлагаем пользователю указать путь в программе, если указывает 8, иначе 7
7. говорим мол без этой программы работать никак не можем и выходим
8. заносим путь в переменную окружения Path далее 9
9. запуск программы

Получается если в Path прога есть то всё нормально, если же нет проищем все папки и всё будет супер. Тут как раз и воспользуемся изменением переменных окружения :)


Отправил deadman в 07:54 02.12.2004[Ответить]
Причём тот алгоритм что я описал можно легко загнать в программу установки. И она будет выполнятся только один раз за всю историю работы программы. Получается пользователи довольны (всё работает быстро), а мы выполнили поставленную задачу. Если бы я пользовался прогой у которой был бы написанный мной алгоритм, наверное сильно бы перепугался :) когда она при запуске вдруг резко зашевелила винчестером :). Поэтому лучше этот алгоритм выполнять один раз и навсегда!


Отправил deadman в 08:11 02.12.2004[Ответить]
САНЬКА: Вроде наконец понял что Вы хотели сказать примером своей программы. Получается на время работы второй задачи переменная окружения test123 будет иметь значение test2, а после выполнения всё вернётся на свои места. Т.е. фактически будем иметь две копии переменной окружения test123. Я всё правильно понял?


Отправил olamot в 13:12 02.12.2004[Ответить]
Пока дописываю пррогу как есть.
Как подумаю, ведь еще хелп какой- то нужен будет!!!!!


Отправил CAHbKA в 22:30 01.12.2004[Ответить]
ну почему я. если подходить буквоедски к вопросу, то результаты поиска задача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



Отправил deadman в 22:33 01.12.2004[Ответить]
Сегодня не кому ответить не смогу. Выгоняют причём так сильно что стены трещат..... Заработался :)))) Завтра обязательно всем отвечу всё решу! Век воли не видать!