Автор | Сообщение |
|
| |
Пост N: 7608
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 09:11. Заголовок: Как правильно ловить обновки ?
Есть сетевая папка. В неё прилетают сканы документов из разных источников , в том числе могут создаваться папки. Каким образом правильно ловить что прилетело и куда , что бы после писать эту инфу в базу , для поиска этих самых сканов. Сейчас по RPC использую для поиска hb_DirScan , но чем больше сканов тем тормознее такой поиск. Сейчас их живет около 100 000.
|
|
|
Ответов - 20
[только новые]
|
|
|
| |
Пост N: 1829
Зарегистрирован: 20.02.11
|
|
Отправлено: 04.02.22 11:09. Заголовок: Dima пишет: Каким о..
Dima пишет: цитата: | Каким образом правильно ловить что прилетело и куда , что бы |
| Дим, как вариант, использовать на удаленной машине возможности операционки, а именно процедуру сторожа изменения в файловой системы наблюдаемого каталога и по ней писать в журнал. Подключившись читаешь журнал в котором все новое и обнуляешь его Петр подробно разжевал тему в посте 1252
|
|
|
|
| |
Пост N: 7609
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 11:24. Заголовок: Игорь ты вот про это..
|
|
|
|
| |
Пост N: 1830
Зарегистрирован: 20.02.11
|
|
Отправлено: 04.02.22 11:31. Заголовок: Dima пишет: ты вот ..
Dima пишет: да , но про имя не помню , можно ли словить. Скорее всего должен быть способ. Гляну
|
|
|
|
| |
Пост N: 7610
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 12:00. Заголовок: я так понял нужна фу..
|
|
|
|
| постоянный участник
|
Пост N: 4058
Зарегистрирован: 17.02.12
|
|
Отправлено: 04.02.22 14:03. Заголовок: Dima пишет Сейчас их..
Dima пишет цитата: | Сейчас их живет около 100 000 |
| Что так сложно ? Держи папку пустой, принятые делай move в др. папку принятых, можешь по ним журнал вести и сортировать куда, кому кинуть сразу. Если доступ к папке не по RPC, а FTP ... замучаешься глотать такой список файлов. PS При таком приеме, перед move, можно проверить правильность КС, тест zip и т.д
|
|
|
|
| |
Пост N: 1831
Зарегистрирован: 20.02.11
|
|
Отправлено: 04.02.22 14:29. Заголовок: Dima пишет: я так п..
Dima пишет: цитата: | я так понял нужна функция ReadDirectoryChangesW для этого |
| Да, это оно. Но в харбуре примеров использования не встречал к сожалению
|
|
|
|
| |
Пост N: 7611
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 19:03. Заголовок: SergKis пишет: Держ..
SergKis пишет: Сергей файлы прилетают с разных мест да и прога не моя что их туда ложит , с планшетов в основном прилетает , но мысль интересная и подумаю.
|
|
|
|
| |
Пост N: 7612
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 21:08. Заголовок: Работает однако WMI ..
Работает однако WMI Только пока не понял как запросу правильно написать что бы слушал и подкаталоги внутри опрашиваемой папки. Есть мысли у кого ? Proc Main local objWMI local intInterval:= "2" local strDrive:= "C:" local strFolder:= "\\POCKET\\skans\\" local elem objWMI:=WmiService() colEvents:= objWMI:ExecNotificationQuery("Select * from __InstanceOperationEvent WITHIN "+intInterval+ ; "Where Targetinstance ISA 'CIM_DataFile' And TargetInstance.Drive="+"'"+strdrive+"'"+; "And TargetInstance.Path="+"'"+strFolder+"'" ) do while .t. if inkey(2)==27 exit endif BEGIN SEQUENCE WITH {| oErr | Break( oErr ) } objEvent:= colEvents:NextEvent(2000) Recover USING oErr * ? oErr:subCode , oErr:operation ,oErr:osCode if "TIMED OUT" $ upper(oErr:description) .or. "0X80043001" $ upper(oErr:description) loop else Return endif End SEQUENCE objTargetInst:= objEvent:TargetInstance For Each elem In objEvent:TargetInstance:Properties_ ? elem:name,elem:value Next enddo return FUNC WMIService( cComp ) Local oWmi, oItem LOCAL oErrSave := ERRORBLOCK( { | objErr | BREAK( objErr ) } ) LOCAL oErr Local oLocator LOCAL cName := '' LOCAl lLocahost := .f. LOCAL cStr := '' hb_default(@cComp,".") oLocator := CreateObject( "wbemScripting.SwbemLocator" ) oWMI := oLocator:ConnectServer(cComp,'root\CIMV2') errorblock(oErrSave) RETURN oWmi
|
|
|
|
| |
Пост N: 7613
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.02.22 23:10. Заголовок: Dima пишет: local s..
Dima пишет: цитата: | local strFolder:= "\\POCKET\\skans\\" |
| Вот тут двойные "палки" ставить обязательно иначе запрос Select может послать лесом... И по ходу вопрос а как преобразовать \POCKET\skans\ в \\POCKET\\skans\\ стандартно и без гимора ? Просто добавив лишнюю палочку.. Проехали hb_StrReplace("\Pocket\Scans\","\",{"\\"})
|
|
|
|
| |
Пост N: 7614
Зарегистрирован: 17.05.05
|
|
Отправлено: 05.02.22 18:03. Заголовок: Dima пишет: For ..
Dima пишет: цитата: | For Each elem In objEvent:TargetInstance:Properties_ ? elem:name,elem:value Next |
| Этот бесполезный кусок кода можно выбросить и вместо него использовать этот OpathClass:=objEvent:Path_:Class if OpathClass=="__InstanceCreationEvent" devout(objTargetInst:name,"gr+/n") ? elseif OpathClass=="__InstanceDeletionEvent" devout(objTargetInst:name,"r+/n") ? elseif OpathClass=="__InstanceModificationEvent" devout(objTargetInst:name,"bg+/n") ? endif Осталось понять как ловить эту же инфу из субдиректорий....
|
|
|
|
| |
Пост N: 679
Зарегистрирован: 08.07.06
|
|
Отправлено: 06.02.22 11:57. Заголовок: IMHO, оставлять посл..
IMHO, оставлять после обработки пришедшие файлы там, где они и были - тупиковая идея. Чем больше файлов, тем больше тормозов, тем более, если их такое количество. Я-бы создал такую систему: 1) Scans\Watch - сюда прилетают документы на разбор, пусть со своей структурой директориев 2) Scans\Stored - сюда твоя система перемещает документы после их обработки. Возможно с изменением структуры, например Scans\Stored\YYMMDD\... - чтобы автоматом удалять старый и никому не нужный хлам 3) Scans\Error - документы, при обработке которых возникла ошибка В нормальной рабочей ситуации 1 и 3 папки должны быть пустыми. А разбором второй папки нужно заниматься раз в неделю/месяц для подчистки мусора.
|
|
|
|
|
| |
Пост N: 7615
Зарегистрирован: 17.05.05
|
|
Отправлено: 06.02.22 19:04. Заголовок: Sergy Ты конечно пр..
Sergy Ты конечно прав. Но решил я пойти более простым путем и просто слегка модернизируем программу на планшете и она будет кидать в ту папку в которую укажу а там имена папок это даты. А сейчас планшет любой документ даже древний кидает в папку с текущей датой , поэтому и приходилось сканировать все папки на предмет нахождения нужного скана (если он не найден в папке с нужной датой) а так буду сканировать всего одну папку а файлов там пшик от 1 до 50
|
|
|
|
| постоянный участник
|
Пост N: 4059
Зарегистрирован: 17.02.12
|
|
Отправлено: 06.02.22 21:43. Заголовок: Dima пишет Но решил ..
Dima пишет цитата: | Но решил я пойти более простым путем и просто слегка модернизируем программу на планшете и она будет кидать в ту папку в которую укажу а там имена папок это даты. |
| Не уверен, что это правильно. У меня куча магазинов с разными каталогами, куда они кидают файлы (я этим не управляю), это в основном xml (у них разные структуры док.) + куча агентов с xls и xlsx (планшеты в основном), причем последние не все читаются версией LibXL, которая есть, т.е. требуется через ole прочитать и преобразовать в старый xls (часто это делают руками, т.к. лицензия excel для этого одна). + ftp, которые сканирую я (причем есть вариант с предварительным просмотром, короче, нужный док или нет) + zip + база firebird с документами. Их объединяет наличие в имени файла формата TimeStamp (с миллисекундами или нет). Суть, все файлы обрабатываются из источников и помещаются в working каталог (в основном проверка КС или 7za -t ...). Программа сканирования каталога принятых файлов (уже в working), лезет внутрь документа (кроме firebird) и распределяет файлы по задачам и обработчикам и уже обработчики проверяют правильность структуры файла (ошибочные возвращают клиенту имя файла док. и вариант первой обнаруженной ошибки, ведя лог ошибочных) и вынимают документы и представляют их для работы\просмотра (реестр, содержимое строки) в тсб. Ответственный за прием, принимает решение, принять док-т в задачу или что то с ним не то (в заказах не хватает на складах номенклатуры, например и надо согласовывать), обрабатывают и т.д. Все обработанные док. из каталогов удаляются, лог обработки ведется, т.е working каталог после сканирования (Directory использую) и обработки всегда пуст. Не забываем проверять захват файлов монопольно, только их обрабатываем. После обработчиков все файлы из working, в задаче, сохраняются в первоначальном виде, как пришли и в реестрах на них, как правило, есть ссылки
|
|
|
|
| |
Пост N: 7616
Зарегистрирован: 17.05.05
|
|
Отправлено: 06.02.22 22:33. Заголовок: SergKis пишет: Не ..
SergKis пишет: цитата: | Не забываем проверять захват файлов монопольно, только их обрабатываем |
| Это интересно. Как проверяешь ? Лично я проверяю время жизни файла , если более x минут то его можно брать и делать с ним что угодно. Чекаю с помощью FileStats. PS Полагаю через Fopen
|
|
|
|
| постоянный участник
|
Пост N: 4060
Зарегистрирован: 17.02.12
|
|
Отправлено: 06.02.22 23:22. Заголовок: Dima пишет Полагаю ч..
Dima пишет Были варианты, но закончились простым *-----------------------------------------------------------------------------* FUNCTION IsFileConnect( cFile ) *-----------------------------------------------------------------------------* LOCAL hFile IF ! hb_FileExists( cFile ) ; RETURN .F. ENDIF IF ( hFile := FOpen(cFile, 2) ) > 0 ; FClose( hFile ) ELSE ; RETURN .F. ENDIF RETURN .T. Если не срослось в этот раз, схватится в следующий (timer ставится через ini, default ~5-20 sek). Часто firebird попадает под эту раздачу, он большой (док. с накоплением какой то период) и может идти не fdb, а bak. Это после Directory(), работа по списку
|
|
|
|
| |
Пост N: 7617
Зарегистрирован: 17.05.05
|
|
Отправлено: 06.02.22 23:51. Заголовок: SergKis пишет: IF (..
SergKis пишет: цитата: | IF ( hFile := FOpen(cFile, 2) ) |
| Кхм я юзаю вместо 2 , 18 Так надежнее мне кажется. SUV еще про это писал
|
|
|
|
| постоянный участник
|
Пост N: 4061
Зарегистрирован: 17.02.12
|
|
Отправлено: 06.02.22 23:58. Заголовок: Dima пишет Так надеж..
Dima пишет цитата: | Так надежнее мне кажется. |
| Я читал, но сделано бывает давно (18 не ставил, надо тестить ... на веру брать, сам знаешь, PC os разные ...), да и дергаться тут нет смысла, т.к. обработчики с BEGIN SEQUNCE ... Не обработал, файл остался, след. Directory() попытается обработать.
|
|
|
|
| |
Пост N: 7633
Зарегистрирован: 17.05.05
|
|
Отправлено: 23.03.22 18:16. Заголовок: SergKis пишет: IF (..
SergKis пишет: цитата: | IF ( hFile := FOpen(cFile, 2) ) > 0 |
| похоже надо IF ( hFile := FOpen(cFile, 2) ) >= 0 If there is an error in opening a file, a -1 will be returned by the function. Files handles may be in the range of 0 to 65535
|
|
|
|
| постоянный участник
|
Пост N: 4105
Зарегистрирован: 17.02.12
|
|
Отправлено: 23.03.22 18:45. Заголовок: Dima пишет похоже на..
Dima пишет цитата: | похоже надо IF ( hFile := FOpen(cFile, 2) ) >= 0 |
| Значения handle 0, 1, 2 заняты уже, так что достаточно проверки > 0, т.е. (от А. Кресина ф-я cedi_rediron(...)) IF hb_FileExists( cPrg ) .and. ! hb_FileExists( cHrb ) // compile prg -> hrb cTmp := hb_memoread(cPrg) IF !Empty(cTmp) nTmp := cedi_rediron( 1, cErr ) nErr := cedi_rediron( 2, cErr ) cBuf := hb_compileFromBuf( cTmp, "harbour", "-n2", "-q", "-w" ) cedi_rediroff( 2, nErr ) cedi_rediroff( 1, nTmp ) cTmp := hb_memoread(cErr) IF Empty( cBuf ) .or. " Warning " $ cTmp .or. "Error " $ cTmp .or. "error " $ cTmp cTmp := cPrg + CRLF + CRLF + cTmp IF lNoMain SET WINDOW MAIN OFF ENDIF AlertStop ( cTmp, Txt("ERROR") + " " + Txt("Compile") ) // "COMPILATION ERROR" IF lNoMain SET WINDOW MAIN ON ENDIF lRet := .F. // compile error ELSE hb_memowrit(cHrb, cBuf) fErase(cErr) ENDIF ENDIF ENDIF
|
|
|
|
| |
Пост N: 7634
Зарегистрирован: 17.05.05
|
|
Отправлено: 23.03.22 18:50. Заголовок: SergKis пишет: Знач..
SergKis пишет: цитата: | Значения handle 0, 1, 2 заняты уже |
| OK
|
|
|
|