:: Игры Разума
Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
В прилагаемом архиве находятся экзешник test.exe, табличка test и база данных test. Известно, что в экзешнике имеется включенный файл test.txt. Задача - скопировать этот файл на диск с именем _test.txt. Экзешник при этом изменять не разрешается. Разрешается изменять таблицу и базу данных. Из сторонних средств разрешается использовать только сам фокс.
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Боюсь разочаровать, но
ON KEY LABEL CTRL+F1 STRTOFILE(FILETOSTR("test.txt"),"_test.txt")
DO test.exe
* Нажать CTRL+F1
Как я понимаю, наличия БД или таблицы вообще не требуется... Лишь бы прога на чём-нить "висела" типа модальной формы или READ EVENTS.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
Да, Игорь, каюсь, об этом не подумал. Но давай, немного усложним задачу. Предположим, что экзешник из IDE по какой-либо причине не запускается. Ну, скажем, стоит в начале что-нибудь вроде
push key clear
clear typeahead
if version(2)=2
return
endif
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну тады в DBC прописать эту же строку.
PROCEDURE dbc_OpenData(cDatabaseName, lExclusive, lNoupdate, lValidate)
*Immediately after DBC is opened.
ON KEY LABEL CTRL+F1 STRTOFILE(FILETOSTR("test.txt"),"_test.txt")
ENDPROC
Усложняем дальше

P.S. Есть какая-то тонкость в том как фокс даёт доступ файловым функциям ко "включенным" файлам - т.е. если прописать вызов внешнего fxp, то он уже не видит файла. Кажись и прямое прописывание STRTOFILE(FILETOSTR("test.txt"),"_test.txt") во "внешнем" dbc файле не проходит - а вот через ON KEY LABEL - работает. Наверное будет работать и через меню - если создать пункт и цеплянуть к нему команду (не вызов процедуры).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
Igor Korolyov
Ну тады в DBC прописать эту же строку.
PROCEDURE dbc_OpenData(cDatabaseName, lExclusive, lNoupdate, lValidate)
*Immediately after DBC is opened.
ON KEY LABEL CTRL+F1 STRTOFILE(FILETOSTR("test.txt"),"_test.txt")
ENDPROC

Игорь, а вот мимо этого способа я прошел. А все потому, что писал немножко не так:
PROCEDURE dbc_OpenData(cDatabaseName, lExclusive, lNoupdate, lValidate)
*Immediately after DBC is opened.
ON KEY LABEL CTRL+F1 STRTOFILE(FILETOSTR("test.txt"),"_test.txt")
KEYBOARD "{CTRL+F1}"
ENDPROC

полагая, что это то же самое. Но так не работает. Объяснить это наверное можно тем, что dbc_OpenData после выполнения прописанного кода делает еще что-то вроде doevents. А вот если мой код вставить в триггер, и вызвать его, то все работает на ура. Это, собственно, и есть мое решение.

Цитата:
Усложняем дальше
Да ради бога. Допустим, имеется список файлов, включенных в экзешник. Находится он в таблице
create table filelist (filename C(254))
Файлов может быть много. Скажем тысяча. Нужно вытащить все. Ну и, естественно, не охота нажимать кнопки CTRL+F1 1000 раз.


Цитата:
P.S. Есть какая-то тонкость в том как фокс даёт доступ файловым функциям ко "включенным" файлам

Эта задачка - как раз плод попытки разобраться в этих тонкостях.
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
В БД
PROCEDURE dbc_OpenData(cDatabaseName, lExclusive, lNoupdate, lValidate)
PUBLIC gc1, go1
gc1 = ""
ON KEY LABEL CTRL+F1 STRTOFILE(FILETOSTR(gc1),"_" + gc1)
IF VERSION(2) = 0
SET PROCEDURE TO h1
go1 = CREATEOBJECT("t1")
ENDIF
ENDPROC

В файле h1.prg (надо откомпилировать перед запуском test.exe)
DEFINE CLASS t1 AS TIMER
INTERVAL = 100
n1 = 0
PROCEDURE TIMER
DO CASE
CASE THIS.n1 = 0
gc1 = "test.txt"
CASE THIS.n1 = 1
gc1 = "test.scx"
CASE THIS.n1 = 2
gc1 = "test.sct"
CASE THIS.n1 = 3
gc1 = "main.fxp"
CASE THIS.n1 = 4
THIS.ENABLED = .F.
MESSAGEBOX("Dump done")
RETURN
ENDCASE
THIS.n1 = THIS.n1 + 1
KEYBOARD '{CTRL+F1}'
ENDPROC
ENDDEFINE
У меня работает...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Скопировать файл
ssa

Сообщений: 12999
Откуда: Москва
Дата регистрации: 23.03.2005
leonid
Допустим, имеется список файлов, включенных в экзешник. Находится он в таблице
create table filelist (filename C(254))
Файлов может быть много. Скажем тысяча. Нужно вытащить все. Ну и, естественно, не охота нажимать кнопки CTRL+F1 1000 раз.
Модифицируем код Игоря в стиле, уже однажды тут обсуждавшемся:
PROCEDURE dbc_OpenData(cDatabaseName, lExclusive, lNoupdate, lValidate)
*Immediately after DBC is opened.
ON KEY LABEL CTRL+F1 Calculate Sum(STRTOFILE(FILETOSTR(filename),"_"+filename)) in filelist
ENDPROC


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
У меня было
ON KEY LABEL CTRL+F1 Select Max(STRTOFILE(FILETOSTR(filename),"_"+filename)) from filelist into array tmp
Так на экран заведомо ничего не выводится, да и не требуется, чтобы filelist открыт был.
Ну, тогда последний вопрос (на мой взгляд, самый легкий). А как получить список файлов, которые включены в экзешник?



Исправлено 1 раз(а). Последнее : leonid, 04.09.09 15:53
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
leonid
Ну, тогда последний вопрос (на мой взгляд, самый легкий). А как получить список файлов, которые включены в экзешник?
Честно говоря, я всегда предполагал что это самый тяжёлый вопрос - от того и нужно в известном дампере vh сканирование памяти - неужели есть какой-то простой/прямой способ?


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
Игорь, может в техническом плане этот вопрос и сложнее, но в идейном он был для меня самым простым. В отличие от других вопросов, я с самого начала представлял путь, по которому надо идти. В итоге покопался в MSDN, выкопал функции GetProcessHeaps (не GetProcessHeap), HeapWalk, ну еще понадобилась функция IsBadReadPtr. Затем вся рабочая память экзешника копируется в курсор и изучается на предмет нахождения интересующей области. Особая примета: Sys(16,0). После этого пишется простенький парсер и все. Кода у меня сейчас под рукой нет, да думаю в нем и нет необходимости.
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
А, ну то понятно... Правда наверняка есть нюансы при подключении разных app/dll - могут ведь и дублироваться имена... Мне кажется что vh примерно по тем-же принципам работает - разве что не только кучи проходит, а вообще всю память...
Кстати, фокс разве полностью таблицу файлов считывает? Мне казалось что он кусками её читает - при том "пока не будет найдёно искомое"... Хотя и не могу гарантировать, настолько глубоко в процесс чтения app не погружался


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Скопировать файл
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
Igor Korolyov
Правда наверняка есть нюансы при подключении разных app/dll - могут ведь и дублироваться имена...
Мне кажется, у других app/dll списки файлов будут в других отрезках, возращаемых HeapWalk, и их можно искать по пути и имени app/dll, только непонятно, что с полученным списком потом делать.

Цитата:
Кстати, фокс разве полностью таблицу файлов считывает?
По-моему, да. По крайней мере мне всегда удавалось получить весь список, даже для довольно больших экзешников.

Вот код, с которым можно поэкспериментировать.
function getexefiles
set talk off
set safety off
set esca off
set collate to "MACHINE"
local lcPROCESS_HEAP_ENTRY
Declare Integer GetProcessHeaps in Win32API Integer, String @
Declare Integer HeapWalk in Win32API Integer, String @
Declare Integer IsBadReadPtr in Win32API Integer, Integer
local lnHeapHandle, lnRez, lnMemPosition, lnMemSize, lnHeapCnt, lcHeapBuffer
lcHeapBuffer = ""
lnRez = GetProcessHeaps(0, @lcHeapBuffer)
lcHeapBuffer = repl(chr(0), lnRez*4)
lnRez = GetProcessHeaps(lnRez, @lcHeapBuffer)
local llFound, lnHeapWalkRez, lnReadable, lcBody
llFound=.f.
for i = 1 to lnRez
lnHeapHandle = str2dword(substr(lcHeapBuffer,i*4-3,4))
lcPROCESS_HEAP_ENTRY = ;
repl(chr(0),4) + ; && lpData
repl(chr(0),4) + ; && cbData
chr(0) + ; && cbOverhead
chr(0) + ; && iRegionIndex
chr(1) + chr(0) + ; && wFlags //PROCESS_HEAP_REGION
repl(chr(0),8) + ; && Block
repl(chr(0),16) && Region
do while .t.
lnHeapWalkRez = HeapWalk(lnHeapHandle, @lcPROCESS_HEAP_ENTRY)
if lnHeapWalkRez = 0
exit
endif
lnMemPosition = str2dword(left(lcPROCESS_HEAP_ENTRY,4))
lnMemSize = str2dword(substr(lcPROCESS_HEAP_ENTRY,5,4))
lnReadable = IsBadReadPtr(lnMemPosition, lnMemSize)
if lnReadable = 0
lcBody=repl(chr(0), lnMemSize)
Declare RtlMoveMemory in Win32API String @, Integer, Integer
RtlMoveMemory(@lcBody, lnMemPosition, lnMemSize)
if left(lcBody,4) = chr(0x0F)+chr(0x40)+chr(0x00)+chr(0x00) ;
and lower(sys(16,0)) $ lcBody
llFound=.t.
exit
endif
endif
enddo
if llFound
exit
endif
next
local lnSelect
lnSelect=select(0)
local laFiles1(1), laFiles2(1), lnFilesCnt1, lnFilesCnt2, lnFilesCnt3
local lcFilename1, lcFilename2, lcExtension1, lcExtension2
lcBody=substr(left(lcBody,at(lower(sys(16,0)),lcBody)-1),9)
word_num(lcBody, chr(0), @laFiles1)
create cursor _files (name C(254))
lnFilesCnt1=alen(laFiles1,1)
lnFilesCnt2=0
for i=1 to lnFilesCnt1
if !"\" $ laFiles1(i)
lnFilesCnt2=lnFilesCnt2+1
dimension laFiles2(lnFilesCnt2)
laFiles2(lnFilesCnt2)=laFiles1(i)
endif
next
lnFilesCnt3=0
for i=1 to lnFilesCnt2
if i = lnFilesCnt2
lnFilesCnt3=lnFilesCnt3+1
insert into _files values (laFiles2(i))
else
lcFilename1 = juststem(laFiles2(i))
lcExtension1 = justext(laFiles2(i))
lcFilename2 = juststem(laFiles2(i+1))
lcExtension2 = justext(laFiles2(i+1))
if !(lcFilename1 == lcFilename2 and ;
(lcExtension1 == "prg" and lcExtension2 == "fxp" or ;
lcExtension1 == "mpr" and lcExtension2 == "mpx" or ;
lcExtension1 == "qpr" and lcExtension2 == "qpx"))
lnFilesCnt3=lnFilesCnt3+1
insert into _files values (laFiles2(i))
endif
endif
next
on error *
go top
br_wind()
on error
Procedure Br_wind
local m.sc
m.sc=_screen.visible
_screen.visible=.t.
Defi Wind tmp From 0,0 To 50,100 Title "Browse" Float Grow Close Zoom Font "Arial",12
brow wind tmp
Rele Wind tmp
_screen.visible=m.sc
FUNCTION dword2str
lparameter m.wrd
local m.wrd1, m.st1
m.wrd1=m.wrd%4294967296
Declare RtlMoveMemory in Win32API String @st1, Integer @wrd, Integer cnt
m.st1=chr(0)+chr(0)+chr(0)+chr(0)
RtlMoveMemory(@m.st1, @m.wrd, 4)
Return m.st1
FUNCTION str2dword
lparameter m.st1
local m.st2,m.wrd
if len(m.st1)<4
m.st2=padl(m.st1,4,chr(0))
else
m.st2=left(m.st1,4)
endif
m.wrd=0
Declare RtlMoveMemory in Win32API Integer @wrd, String @st1, Integer cnt
RtlMoveMemory(@m.wrd, @m.st1, 4)
Return m.wrd
Function word_num
lparameter m.txt, m.razd, ar1
if len(m.razd)=0
return 0
endif
local m.cn1, m.cn2, m.st1, m.txt2, m.ln, m.i
m.cn1=occurs(m.razd,m.txt)
if m.cn1=0
if empty(m.txt)
return 0
else
dimension ar1(1)
ar1(1)=m.txt
return 1
endif
else
m.cn2=0
m.txt2=m.razd+m.txt+m.razd
m.ln=len(m.razd)
for m.i=1 to m.cn1+1
m.st1=substr(m.txt2,at(m.razd,m.txt2,m.i)+m.ln,at(m.razd,m.txt2,m.i+1)-at(m.razd,m.txt2,m.i)-m.ln)
m.st1=allt(m.st1)
if !empty(m.st1)
m.cn2=m.cn2+1
dimension ar1(m.cn2)
ar1(m.cn2)=m.st1
endif
next
return m.cn2
endif
Ratings: 0 negative/0 positive
Re: Скопировать файл
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Да, прикольно Хотя это уже по большому счёту элементы отладчика...

P.S. Я смотрю, всё ещё на 6-ке трудишься - нет SYS(2600), BINTOC/CTOBIN


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 6 (Гостей: 6)

© 2000-2024 Fox Club 
Яндекс.Метрика