Привет. Наверняка слыхали об PadarokEdition и тд. паках. Достоинством их есть большой набор программ. Тягостью - частая несовместимость с интересами конечного пользователя, которому вы чините компютер, или чегось свое. Понятно можно один раз установить тот *.msi или *.exe(sfx), удалить ненужное и запаковать обычным zip. Обновляя конкретную софтину, приходится перепаковывать весь архив. Было [позавчерашней безсонной ночи] решено: -предоставить возможность выбора устанавливаемых компонентов -максимально упростить наращивание -никаких установщиков, писанины ... -то все слова, ниже расписан короткий алго программы, которую вы найдете в архиве пустышке - прототипе оригинального на нашей машине Запускаясь, тулзо ищет каталог "+", да, тот в который все и свалим, но систематично. Не найдя, висит в памяти и вникает из экрана вам в глаза кнопочкою "давай с начала". Заходит в тот каталог, перелистывает в нем все папки(так мы сортируем софт по категориям). Начинает лезть в каждую, спускаясь только на 1 этаж низ, в поисках файлика *.zip(сбрасывается ковырянием сорца). Аккуратным движением DWORD'a ищет одноименный *.txt файл-описание. С соображений экономии читает до 4095+1 байт. Выводим элемент в список, ассоциируя с ним тот коммент. Также показываем размер файла. Наконец, выходим из "+" для возможности рескана. Никаких файлов настроек, что и как запускать нас тоже не интерисует - мы автомата. Регистрация всего набора тулзочек - см. архив... Устал и не сделал последнее - установку, состоящую из циклического подсвечивания активного элемента и вызывания розархиватора, открытия папки назначения. ТС поддерживает запуск за конкретным файлом настроек - это весь фокус. Для этого нужен лончер(запускалка), в нас это totalcmd+.exe с вызовом ShellExecute. По понятным причинам в архив не кидал. Для компиляции нужен только фасм и этот файл. Прежде установите значение LNG на 1 из 4 языков(сейчас там LNG equ UA). Код (Text): тут был старый код - поэтому удален, обновленный смотри ниже Зачем это? - хз, но так проще.
В этой версии появился установщик. Код (Text): тут был старый код - поэтому удален, обновленный смотри ниже
Добавлено возможность создания запускалки. У меня вопрос: IMAGE_DOS_HEADER.MinimumExtraParagraphs - где бы они располагались в ОЗУ?(см. метку "SCRATCH:") Переделывая сорсе, не используйте(осторожно используйте) "db ?", "rb x" тд: http://board.flatassembler.net/topic.php?t=12098 http://board.flatassembler.net/topic.php?t=12098&start=9 Удалил старый код: создание запускалки теперь максимально упрощено Код (Text): ;/* ;enu: Modular Total Commadner - installer for the Total Commander(www.ghisler.net). ; ; On start it searches for a "totalcmd.zip" and its comment file - "totalcmd.zip.txt". ; If found(comments are not important actually), it will be reflected in the package list. ; Then it looks for a "+\" folder. ; If found, lists all its subfolders(depth level=1) and files of those subfolders. ; Matching a file or a folder with an exeption to *.txt files, "+\%FOLDER%.txt" for folders and "+\%FOLDER%\%FILE%.txt" will be read(up to 4096-1 bytes) if found as respective comments. ; ; On setup original TC gets extracted into "%DESTINATION%\totalcmd\" and the rest from "+\" - into "%DESTINATION%\totalcmd\+\". ; We use Igor Pavlov's free for use archiver: 7zG.exe, 7z.dll(www.7-zip.org). ; ; You need "totalcmd.zip" installed only whenever basical service level required. ; ; You might want creating your own tool set: ; -install original Total Commander ; -pack "%commader_path%\" directory's contents into "totalcmd.xxx"(any file type, supported by 7zG.exe) ; -add some cosmetics :) if needed, creating "+\" folder and its subfolders("archivers", "editors", etc just not to mesh) ; put packed programs you want to those subfolders ; create respective comment files(described over) ; -a sample: ; 7zG.exe ; 7z.dll ; mtc.exe ; ------- ; totalcmd.zip ; totalcmd.zip.txt ; +\ ; arch\ ; file1.rar ; file1.rar.txt ; ... ; compute\ ; file1.7z ; file1.7z.txt ; file2.7z ; file2.7z.txt ; ... ; ... ; ; You are free modifying this tool source(mtc.asm). Use fasm(www.flatAssembler.net) to compile it. ; ; Contact email: edemko@rambler.ru ; ;rus: Modular Total Commander - установщик Total Commander(www.ghisler.net). ; ; Запускаясь, ищет файл "totalcmd.zip" и соответствующий комментарий к нему - "totalcmd.zip.txt". ; Найдя, добавляет в список пакетов установки. ; Ищет папку "+\", найдя входит в нее и перелистывает все подпапки, считывая соответствующие комментарии к ним - "%ПАПКА%.txt". ; Заходит в каждую "+\%ПАПКУ%\"(далее не ходит :) и добавляет все имеющиеся файлы в список пакетов установки. ; Соответственно комментарий к файлу с папки "+\%ПАПКУ%\" будет "+\%ПАПКУ%\%ФАЙЛ%.txt". ; Поскольку *.txt-файлы - комментарии, их мы не добавляем(только читаем до 4096-1 байт). ; ; В процессе установки оригинальний TC розархивируется в "%ВЫБРАННЫЙ КАТАЛОГ%\totalcmd\", а ; все остальное - в "%ВЫБРАННЫЙ КАТАЛОГ%\totalcmd\+\". ; Данная версия использует вольный архиватор Игоря Павлова: 7zG.exe, 7z.dll(www.7-zip.org). ; ; Для стандартных функций хватит оригинального "totalcmd.exe", никаких сторонних продуктов можно не устанавливать. ; ; Расширять комплекс очень легко: ; -установите оригинальный Total Commander ; -упакуйте все содержимое директории "%commander_path%\" в "totalcmd.xxx"(любой тип архивов, поддерживаемый 7zG.exe). ; -за желанием создайте папку "+"(так мы классифицируем ПО), а в ней еще подпапки("архиваторы", "редакторы", чего угодно) ; в подпапки положите заархивированные программы на ваш вкус ; создайте файлы описаний(см. выше про *.txt) ; -пример: 7zG.exe ; 7z.dll ; mtc.exe ; ------- ; totalcmd.zip ; totalcmd.zip.txt ; +\ ; arch\ ; file1.rar ; file1.rar.txt ; ... ; compute\ ; file1.7z ; file1.7z.txt ; file2.7z ; file2.7z.txt ; ... ; ... ; ; Для сборки программы-установщика нужен только этот(mtc.asm) файл и fasm(www.flatAssembler.net). ; ; Мой почтовый ящик: edemko@rambler.ru. ;*/ format pe gui 4.0; on '..\stub\stub.exe' include 'win32ax.inc' LNG equ RU match =BY,LNG{ include 'encoding\win1251.inc' STRING1 equ 'Дадатковыя архівы(<ctrl+m1> для выбару):' STRING2 equ 'Каментарый(глядзі файлы *.txt):' STRING3 equ 'Мэтавая тэчка(напр. c:\programs\, клік для выбару):' STRING4 equ 'Абнавіць' STRING5 equ 'Паехалі' STRING6 equ 'Карэгаваць старт "totalcmd.exe":'; } match =EN,LNG{ STRING1 equ 'Detected packages(<ctrl+m1> to un|select):' STRING2 equ 'Comment from respective .txt file:' STRING3 equ 'Destination(e.g. c:\programs\), click to chose:' STRING4 equ 'ReLoad' STRING5 equ 'Start' STRING6 equ 'Command line for "totalcmd.exe":' } match =RU,LNG{ include 'encoding\win1251.inc' STRING1 equ 'Дополнительные архивы(<ctrl+m1> для выбора):' STRING2 equ 'Комментарий(смотри файлы *.txt):' STRING3 equ 'Целевая папка(напр. c:\programs\, клик для выбора):' STRING4 equ 'Обновить' STRING5 equ 'Поехали' STRING6 equ 'Командная строка "totalcmd.exe":' } match =UA,LNG{ include 'encoding\win1251.inc' STRING1 equ 'Додаткове ПЗ(<ctrl+m1> обрати):' STRING2 equ 'Коментар з *.txt-файлу:' STRING3 equ 'Папка призначення(напр. c:\programs\, клік - обрати):' STRING4 equ 'Оновити' STRING5 equ 'Запуск' STRING6 equ 'Командний рядок "totalcmd.exe":' } STRING7 equ '/i=%COMMANDER_PATH%\+\tc\ini\wincmd.ini /f=%COMMANDER_PATH%\+\tc\ini\wcx_ftp.ini' STRING0 equ 'Modular Total Commander' section '' code import executable readable writable library comdlg32,'comdlg32.dll',\ kernel32,'kernel32.dll',\ shell32,'shell32.dll',\ user32,'user32.dll' include 'api\comdlg32.inc' include 'api\kernel32.inc' include 'api\shell32.inc' include 'api\user32.inc' si_ STARTUPINFO pi PROCESS_INFORMATION bi BROWSEINFO 0,0,0,0,1,0,0,0 ;1=только папки wfd WIN32_FIND_DATA buf rb MAX_PATH*2 targetDir rb MAX_PATH ArrOfTxt dd 0 ofn OPENFILENAME \ sizeof.OPENFILENAME,\ ;lStructSize 0,\ ;hwndOwner 0,\ ;hInstance filter,\ ;lpstrFilter 0,\ ;lpstrCustomFilter 0,\ ;nMaxCustFilter 1,\ ;nFilterIndex buf,\ ;lpstrFile MAX_PATH,\ ;sizeof.lpstrFile 0,\ ;lpstrFileTitle 0,\ ;nMaxFileTitle targetDir,\ ;lpstrInitialDir 0,\ ;lpstrTitle OFN_OVERWRITEPROMPT+OFN_LONGNAMES,\ 0,\ ;nFileOffset 0,\ ;nFileExtension 0,\ ;lpstrDefExt 0,\ ;lCustData 0,\ ;lpfnHook 0 ;lpTemplateName filter db '32 bit Portable Executable',0,'*.exe',0 db 0 entry $ invoke DialogBoxParamA,0,IDD_MTC,0,mtc,0 invoke ExitProcess,eax proc mtc uses ebx esi edi, wnd,msg,wparam,lparam mov eax,[msg] .if eax=WM_CLOSE ;enu: free dialog ;rus: выгрузить диалог invoke EndDialog,[wnd],eax ;enu: free comments tree ;rus: выгрузить дерево комментариев call .free_ArrOfTxt_items_ jmp .retz .free_ArrOfTxt_items_: mov eax,[ArrOfTxt] push 0 eax mov ecx,[eax] .free_ArrOfTxt_items: sub ecx,4 jz .free_ArrOfTxt add eax,4 stdcall memory,dword[eax],0 jmp .free_ArrOfTxt_items .free_ArrOfTxt: call memory ret 0 .elseif eax=WM_INITDIALOG ;enu: destinative dir selection: set owner once instead of doing that every time a button pressed ;rus: выбор целевого каталога: назначим родителя только раз замись проделывания это каждое нажатие кнопки mov eax,[wnd] mov [bi.hwndOwner],eax mov [ofn.hwndOwner],eax .wm_initdialog: ;enu: still an empty comments list ;rus: покамись пустой список комментариев каждого пункта IDC_LSTBUSH stdcall memory,0,4 mov byte[eax],4 mov [ArrOfTxt],eax ;enu: searching for main archive, reflecting into the list ;rus: ищем главный архив и выводим в список invoke FindFirstFileA,'totalcmd.zip',wfd cmp eax,-1 je .no_totalcmd.zip invoke FindClose,eax invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_ADDSTRING,0,' |totalcmd.zip' invoke SendDlgItemMessageA,[wnd],IDC_LBLBUSH,LB_SETITEMDATA,0,0 ;enu: fetch its comment ;rus: считать соотв. комментарий call .get_tc_comment_file db 'totalcmd.zip.txt',0 .get_tc_comment_file: pop eax call .add_comment ;enu: entering archives dir "+" ;rus: заходим в "+" - каталог архивов .no_totalcmd.zip: invoke GetCurrentDirectoryA,MAX_PATH,buf cmp eax,MAX_PATH ja .retz mov dword[buf+eax],'\+' invoke SetCurrentDirectoryA,buf test eax,eax jz .retz ;enu: list every SUBDIR and SUBDIR\FILE fetching respective comment files, depth=1 ;rus: заходим в каждый_подкаталог\список_файлов, считывая комментарии в ArrOfTxt, вложенность просмотра = 1 stdcall dirA,.dirA.cally,FILE_ATTRIBUTE_DIRECTORY ;enu: step back making rescan possible(look at IDC_BTNRELOAD) ;rus: возвращаемся назад для возможности повторения(см. IDC_BTNRELOAD) invoke SetCurrentDirectoryA,'..' jmp .retz ;enu: list every SUBDIR... of "+" ;rus: заходим в каждый_подкаталог... каталога "+" .dirA.cally: lea esi,[esp+4+11*4] ;WIN32_FIND_DATA.cFileName push esi invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_ADDSTRING,0,esi invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_SETITEMDATA,eax,$8000'0000 ; test eax,eax -> js .папка ;enu: read "FOLDER.txt" comment ;rus: считать комментарий к папке из "папка.txt" mov edi,buf .txt_name: lodsb cmp al,0 jz .txt_done stosb jmp .txt_name .txt_done: mov eax,'.txt' stosd mov byte[edi],0 mov eax,buf call .add_comment ;enu: enter FOLDER([esp]=esi=folder) and get its files list ;rus: войти в папку([esp]=esi=папка) и получить список файлов invoke SetCurrentDirectoryA push ebx ;! stdcall dirA,.filA.cally,0 pop ebx invoke SetCurrentDirectoryA,'..' ret 0 ;enu: eax -> file name to read(up to 4096-1 bytes) into ArrOfTxt as an element ; eax <- updated ArrOfTxt ; ecx <- [eax] ; edx <- ? ; edi <- fetched comment ; flags <- ? ;rus: eax -> имя файла для считывания его части(до 4096 байт) в ArrOfTxt ; eax <- обновленный ArrOfTxt ; ecx <- [eax] ; edx <- ? ; edi <- комментарий ; flags <- ? .add_comment: xor edi,edi invoke CreateFileA,eax,GENERIC_READ,edi,edi,OPEN_EXISTING,edi,edi cmp eax,-1 je .register_comment push eax invoke GetFileSize,eax,edi test eax,eax jz .register_comment_ mov ecx,4096-1 cmp ecx,eax cmova ecx,eax inc ecx stdcall memory,edi,ecx dec ecx push edi wfd ecx eax dword[esp+4*4] mov edi,eax invoke ReadFile .register_comment_: invoke CloseHandle .register_comment: mov eax,[ArrOfTxt] mov ecx,[eax] add ecx,4 stdcall memory,eax,ecx mov [eax],ecx mov [eax+ecx-4],edi mov [ArrOfTxt],eax ret 0 ;enu: ...and get its files list ;rus: ...и получить список файлов .filA.cally: ;enu: creating a hierarchy: " |name.zip" ;rus: создаем иерархию: " |name.zip" lea esi,[esp+4+11*4] ;WIN32_FIND_DATA.cFileName mov edi,buf mov eax,' |' stosd .nest_name: lodsb stosb cmp al,0 jnz .nest_name ;enu: *.txt-gate ;rus: *.txt-барьер mov eax,[edi-5] or eax,' ' cmp eax,'.txt' jne .filter_ok ret 0 .filter_ok: ;enu: prepend file size: " |name.zip(xxx B)" ;rus: вывести размер файла: " |name.zip(xxx B)" mov eax,[esp+4+8*4] ;WIN32_FIND_DATA.nFileSizeLow xor ecx,ecx .dword2a: inc ecx test cl,11b jnz .no_dummy push " " jmp .dword2a .no_dummy: mov esi,eax mov edx,$cccc'cccd mul edx shr edx,3 lea eax,[edx*8+edx-'0'] xadd edx,eax sub esi,edx push esi test eax,eax jnz .dword2a dec edi mov esi,edi mov al,'|' stosb .dword2a_: pop eax stosb loop .dword2a_ mov eax,' B' stosd ;enu: add file to the tree ;rus: добавить файлик в дерево invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_ADDSTRING,0,buf invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_SETITEMDATA,eax,0 ;enu: fetch inserted file's comment ;rus: получить комментарий о добавленном файлике mov dword[esi],'.txt' mov byte[esi+4],0 mov eax,buf+4 ;' |' jmp .add_comment .elseif eax=WM_COMMAND mov eax,[wparam] .if eax=LBN_SELCHANGE shl 16 or IDC_LSTBUSH ;enu: output record's comment ;rus: вывести комментарий записи invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETCURSEL,0,0 mov ebx,eax mov eax,[ArrOfTxt] lea eax,[eax+4+ebx*4] invoke SendDlgItemMessageA,[wnd],IDC_TXTCOMMENT,WM_SETTEXT,0,dword[eax] ;enu: disallow service items selection ;rus: запретить выбор служебных пунктов invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETITEMDATA,ebx,0 test eax,eax jns .ret1 ;) invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_SETSEL,FALSE,ebx .elseif eax=IDC_BTNRELOAD ;enu: reload the tree ;rus: перегрузить дерево call .free_ArrOfTxt_items_ invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_RESETCONTENT,0,0 jmp .wm_initdialog .elseif eax=IDC_BTNDIR ;enu: chose destinative dir ;rus: выбор целевого каталога mov edi,.retz .idc_btndir: invoke SHBrowseForFolderA,bi test eax,eax jz .ret1 ;) invoke SHGetPathFromIDListA,eax,targetDir invoke SendDlgItemMessageA,[wnd],IDC_TXTDIR,WM_SETTEXT,0,targetDir jmp edi .elseif eax=IDC_BTNGO ;============== ;enu: setup ;rus: установка ;============== ;enu: ensure destinative folder got ;rus: удостовериться в присутствии каталога назначения mov edi,.target_dir_got xor ebx,ebx .target_dir_got: cmp byte[targetDir],bl jz .idc_btndir ;enu: list size -> [wfd], id_now -> ebx ;rus: размер списка -> [wfd], id_сейчас -> ebx invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETCOUNT,ebx,ebx test eax,eax jz .ret1 ;) mov [wfd],eax ;enu: [buf] = '+\' + %FOLDER% + '\' ;rus: [buf] = '+\' + %ПАПКА% + '\' mov word[buf],'+\' .install_loop: ;enu: update [buf] if element is a folder ;rus: если эл. списка - папка, переиначиваем [buf] invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETITEMDATA,ebx,0 test eax,eax jns .keep_path invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETTEXT,ebx,buf+2 mov word[buf+2+eax],'\' jmp .skip .keep_path: ;enu: skip unselected element, focus else ;rus: пропустить элемент списка без выделения, иначе - навести на него фокус invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETSEL,ebx,0 test eax,eax jz .skip invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_SETCARETINDEX,ebx,0 ;enu: temporary text buffer ;rus: временный текстовый буфер sub esp,MAX_PATH*5 mov esi,esp ;enu: try unpacking totalcmd.zip ;rus: если в списке файлов есть totalcmd.zip, распаковать его test ebx,ebx jnz .not_tc cinvoke wsprintfA,esi,'7zG.exe -o"%s\totalcmd\" x "totalcmd.zip"',targetDir jmp .unpack .not_tc: ;enu: extact %FILE% name into [wfd+4+4] ;rus: извлечь имя %ФАЙЛА% в [wfd+4+4] invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_GETTEXT,ebx,wfd+4 mov al,'|' or ecx,-1 lea edi,[wfd+4+4] repne scasb mov byte[edi-1],0 ;enu: merge archiver's command line: '7zG.exe -o"%s\totalcmd\%s" x "%s%s"' ;rus: плетем веревки, шутка, нужно собрать коммандную строку архиватора: '7zG.exe -o"%s\totalcmd\%s" x "%s%s"' cinvoke wsprintfA,esi,'7zG.exe -o"%s\totalcmd\%s" x "%s%s"',targetDir,buf,buf,wfd+4+4 ;enu: run decom/compressor ;rus: запускаем архиватор .unpack: invoke CreateProcessA,0,esi,0,0,0,0,0,0,si_,pi add esp,MAX_PATH*5 invoke WaitForSingleObject,[pi.hProcess],-1 ;enu: cycle along the list ;rus: циклимся по всему списку invoke SendDlgItemMessageA,[wnd],IDC_LSTBUSH,LB_SETSEL,0,ebx .skip: inc ebx cmp ebx,[wfd] jne .install_loop ;enu: explore destination folder ;rus: открыть папку назначения invoke ShowWindow,[wnd],SW_MINIMIZE invoke ShellExecuteA,0,'explore',targetDir,0,0,SW_MAXIMIZE .elseif eax=IDC_BTNSCRATCH ;enu: get file name for the SCRATCH image ;rus: спросить имя для образа SCRATCH mov dword[buf],'tota' mov dword[buf+4],'lcmd' mov dword[buf+8],'+.ex' mov dword[buf+12],'e' invoke GetSaveFileNameA,ofn test eax,eax jz .ret1 ;) ;enu: fetch IDC_TXTSCRATCH.text into SCRATCH._init ;rus: занести IDC_TXTSCRATCH.text в SCRATCH._init invoke SendDlgItemMessageA,[wnd],IDC_TXTSCRATCH,WM_GETTEXT,MAX_PATH,SCRATCH+init ;enu: store SCRATCH image ;rus: сохранить SCRATCH invoke CreateFileA,buf,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 push eax push 0 wfd SECTION_1_RAW. SCRATCH eax invoke WriteFile invoke CloseHandle .endif .endif .retz: xor eax,eax .ret1: ret endp ; if [mem]=[bytes]=0{ ; return ; } ; if ([mem]<>0)&([bytes]<>0){ ; return size([mem],[bytes]) ; } ; if [mem]=0{ ; return get([bytes]) ; } ; if [bytes]=0{ ; free([mem]) ; return ; } proc memory; mem,bytes xchg edx,[esp+4] xchg ecx,[esp+8] pushfd cld test ecx,ecx jz .free test edx,edx jz .get .size: invoke GetProcessHeap ;GetProcessHeap: invoke HeapReAlloc,eax,HEAP_ZERO_MEMORY,edx,ecx ; mov eax,[fs:$18] jmp .exit ; mov eax,[eax+$30] .get: invoke GetProcessHeap ; mov eax,[eax+$18] invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,ecx ; ret jmp .exit .free: test edx,edx jz .exit push eax invoke GetProcessHeap invoke HeapFree,eax,ecx,edx pop eax .exit: popfd mov ecx,[esp+8] mov edx,[esp+4] ret 8 endp ; enu: list directory or file names for the current path. ; cally = is a user defined procedure, called on every fetch. ; Approximate look: ; proc cally ; lea eax,[esp+4+11*4] ; invoke MessageBoxA,0,eax,0,0 ; ret 0 ; endp ; old EAX ; old EBX ; old ECX ; old EDX ; WIN32_FIND_DATA + DWORD aligned tail ; Whenever called, ESP: pointer to <dirsA> EIP after <cally> ; After a call resume EBX. ; options = set FILE_ATTRIBUTE_DIRECTORY's bit to list dirs, or drop that bit(not FILE_ATTRIBUTE_DIRECTORY, 0, etc) to list files. ; On exit FLAGS = ? ; rus: пройтись по списку файлов или папок в поточной для процесса директории. ; cally = вызывается при каждом успешном обнаружении файла(папки). ; Както так: ; proc cally ; lea eax,[esp+4+11*4] ; invoke MessageBoxA,0,eax,0,0 ; ret 0 ; endp ; старый EAX ; старый EBX ; старый ECX ; старый EDX ; WIN32_FIND_DATA, выровненная к DWORD ; При вызове, ESP: указатель на EIP <dirsA> после <cally> ; Выходя, восстановите EBX. ; options = установите бит FILE_ATTRIBUTE_DIRECTORY для просмотра папок, или сбросьте его(not FILE_ATTRIBUTE_DIRECTORY, 0, итд.) - для файлов. ; В конце FLAGS = ? proc dirA; cally, options push eax ebx ecx edx sub esp,(sizeof.WIN32_FIND_DATA + 4) shr 2 shl 2 invoke FindFirstFileA,.wild,esp cmp eax,-1 je .exit mov ebx,eax .loop: test byte[esp + (sizeof.WIN32_FIND_DATA + 4) shr 2 shl 2 + 4*4 + 4*2],FILE_ATTRIBUTE_DIRECTORY jnz .dir_mode test byte[esp],FILE_ATTRIBUTE_DIRECTORY jz .cally jmp .not .dir_mode: test byte[esp],FILE_ATTRIBUTE_DIRECTORY jz .not mov eax,[esp+11*4] and eax,$00ff'ffff cmp eax,'..' je .not cmp ax,'.' je .not .cally:call dword[esp + (sizeof.WIN32_FIND_DATA + 4) shr 2 shl 2 + 4*4 + 4] .not: invoke FindNextFileA,ebx,esp test eax,eax jnz .loop invoke FindClose,ebx .exit: add esp,(sizeof.WIN32_FIND_DATA + 4) shr 2 shl 2 pop edx ecx ebx eax ret 8 .wild: db '*',0 endp ;Пример ручного создания PE32. ;В случае изменений следи за следующими полями: ;- IMAGE_OPTIONAL_HEADER.SizeOfImage ;- SECTION_X.Rva ;format binary as 'exe' SCRATCH: macro padzero value*{db (value - $ and (value-1)) mod (value) dup 0} macro m1 section{ ;увеличить счетчик числа секций load a word from IMAGE_FILE_HEADER.NumberOfSections store word a+1 at IMAGE_FILE_HEADER.NumberOfSections ;задать 2 частые дельты load a dword from section#.Rva section#_RVA = a - section#_RAW section#_BASE = IMAGE_BASE + section#_RVA } DISK_SECTOR = $0000'0200 ;0'000'512 PAGE = $0000'1000 ;0'004'096 IMAGE_BASE = $0040'0000 ;4'194'304 use16 org 0 IMAGE_DOS_HEADER: .Signature dw 'MZ' .BytesOnLastPage dw 64 ;страничка = 512 байт .PagesInFile dw 1 .Relocations dw 0 .SizeOfHeaderInParagraphs dw 64/16 ;параграф = 16 байт .MinimumExtraParagraphs dw 0 .MaximumExtraParagraphs dw 0 .InitialRelativeSS dw 0 .InitialSP dw 64 .Checksum: int $20 ;просто выйти в ДОС .InitialIP dw .Checksum .InitialRelativeCS dw 0 .OffsetToRelocationTable dw 0 .OverlayNumber dw 0 .Reserved1 dw 4 dup 0 .OEMIdentifier dw 0 ;) .OEMInformation dw 0 ;) .Reserverd2 dw 10 dup 0 .OffsetToNewEXEHeader dd 64 ;IMAGE_NT_HEADERS IMAGE_NT_HEADERS: .Signature dd 'PE' IMAGE_FILE_HEADER: .Machine dw $014c ;нужен i386 и выше .NumberOfSections dw 0 ;число секций, ОСТАВЬТЕ ПУСТЫМ - ЗАПОЛНИМ В КОНЦЕ .TimeDateStamp dd %t ;секунд с 1970_01_01, 00:00 .PointerToSymbolTable dd 0 .NumberOfSymbols dd 0 .SizeOfOptionalHeader dw IMAGE_SECTION_HEADER-\ ;размер структуры IMAGE_OPTIONAL_HEADER .Characteristics dw $0002 ;исполняемый файл IMAGE_OPTIONAL_HEADER: .Magic dw $010b ;32'разрядная программа .MajorLinkerVersion db 0 ;поля версии компоновщика, можно... .MinorLinkerVersion db 0 ;...прописать смайлики .SizeOfCode dd 0 .SizeOfInitializedData dd 0 .SizeOfUninitializedData dd 0 .AddressOfEntryPoint dd PAGE+\ ;PAGE(=.SectionAlignment) тут - смещение в ОЗУ к первой секции относительно IMAGE_DOS_HEADER(=0) entry_point-SECTION_1_RAW ;точка входа соответственно .BaseOfCode dd 0 .BaseOfData dd 0 .ImageBase dd IMAGE_BASE ;база загрузки образа; образ начинается с IMAGE_DOS_HEADER :) .SectionAlignment dd PAGE ;расположить секции в ОЗУ по адресам, кратным этому числу .FileAlignment dd DISK_SECTOR ;в физ. файле секции распол. по кратным этому числу адресам .MajorOSVersion dw 0 .MinorOSVersion dw 0 .MajorImageVersion dw 0 ;свое .MinorImageVersion dw 0 ;чегось .MajorSubsystemVersion dw 4 .MinorSubsystemVersion dw 0 .Win32VersionNumber dd 0 .SizeOfImage dd PAGE*2 ;размер всего образа, отображенного в ОЗУ, включая заголовки и секции, округляйте к SectionAlignment, говорит загрузчику о наших размерах .SizeOfHeaders dd SECTION_1_RAW ;дисковый размер образа до первой секции, кругленный(просто выравнивайте первую секцию к ->) к .FileAlignment .Checksum dd 0 .Subsystem dw 2 ;win graphical user interface(гумка :ы), столько под|версий, ах! .Characteristics dw 0 .SizeOfStackReserve dd 1024*1024 ;пространство стека .SizeOfStackCommit dd 0 .SizeOfHeapReserve dd 1024*1024 ;пространство кучи .SizeOfHeapCommit dd 0 .LoaderFlags dd 0 .NumberOfDataDirectories dd 16 ;количество указателей на (предопределенные) секции ниже: .ExportTableRvaAndSize dq 0 ;1, экспорт .ImportTableRvaAndSize dd PAGE,\ ;2, импорт, будем импортировать функции 0;entry_point-SECTION_1_RAW times 14 dq 0 ;3..16 IMAGE_SECTION_HEADER: SECTION_1: .Name dq '' ;ник секции, напр. 'code' или 'maria' .VirtualSize dd 0 .Rva dd PAGE ;вспомните .SectionAlignment, по этому адресу лежит первый байт секции, отраженной в память .SizeOfRawData dd SECTION_1_RAW.-SECTION_1_RAW ;размер физических нанных, выравнивайте секции к .FileAlignment .PointerToRawData dd SECTION_1_RAW ;указатель начала физ. данных, выравнивайте секции к .FileAlignment .PointerToRelocations dd 0 .PointerToLineNumbers dd 0 .NumberOfRelocations dw 0 .NumberOfLineNumbers dw 0 .Characteristics dd $0000'0020+\ ;тут код $2000'0000+\ ;выполняемый $4000'0000+\ ;можно считывать $8000'0000 ;и записывать m1 SECTION_1 padzero DISK_SECTOR ;выровнять к .FileAllignment SECTION_1_RAW: ;таблица импорта dd 0,0,0,kernel_name+SECTION_1_RVA,kernel_table+SECTION_1_RVA dd 0,0,0,shell_name+SECTION_1_RVA,shell_table+SECTION_1_RVA dd 0,0,0,0,0 kernel_name db 'kernel32.dll',0 kernel_table: exit_process dd exit_process_+SECTION_1_RVA beep dd beep_+SECTION_1_RVA dd 0 exit_process_ dw 0 db 'ExitProcess',0 beep_ dw 0 db 'Beep',0 shell_name db 'shell32.dll',0 shell_table: shell_execute dd shell_execute_+SECTION_1_RVA dd 0 shell_execute_ dw 0 db 'ShellExecuteA',0 entry_point: ;точка входа use32 push 5 push 0 call @f init:rb MAX_PATH @@:call @f db 'totalcmd.exe',0 @@:push 0 push 0 call [shell_execute+SECTION_1_BASE] push 0 call [exit_process+SECTION_1_BASE] padzero DISK_SECTOR SECTION_1_RAW.: section '' resource readable IDD_MTC = 0 IDC_LBLBUSH = 1 IDC_LSTBUSH = 2 IDC_LBLCOMMENT = 3 IDC_TXTCOMMENT = 4 IDC_LBLDIR = 5 IDC_TXTDIR = 6 IDC_BTNDIR = 7 IDC_BTNRELOAD = 8 IDC_BTNGO = 9 IDC_GRPSCRATCH = 10 IDC_TXTSCRATCH = 11 IDC_BTNSCRATCH = 12 directory RT_DIALOG,dialogs resource dialogs,\ IDD_MTC,0,idd_mtc dialog idd_mtc,STRING0,40,40,316,294,WS_CAPTION+WS_MINIMIZEBOX+WS_SYSMENU,,,'courier new',8 dialogitem 'static' ,STRING1 ,IDC_LBLBUSH ,3,3,310,9 ,WS_CHILD+WS_VISIBLE dialogitem 'listbox' ,'' ,IDC_LSTBUSH ,3,12,310,96 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER+WS_VSCROLL+LBS_NOINTEGRALHEIGHT+LBS_EXTENDEDSEL+LBS_NOTIFY dialogitem 'static' ,STRING2 ,IDC_LBLCOMMENT ,3,114,310,9 ,WS_CHILD+WS_VISIBLE dialogitem 'edit' ,'' ,IDC_TXTCOMMENT ,3,123,310,50 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER+WS_VSCROLL+ES_READONLY+ES_MULTILINE dialogitem 'static' ,STRING3 ,IDC_LBLDIR ,3,179,310,9 ,WS_CHILD+WS_VISIBLE dialogitem 'edit' ,'' ,IDC_TXTDIR ,3,189,295,12 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER+ES_AUTOHSCROLL+ES_READONLY dialogitem 'button' ,'<' ,IDC_BTNDIR ,301,189,12,12 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER dialogitem 'button' ,STRING4 ,IDC_BTNRELOAD ,3,213,60,14 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER dialogitem 'button' ,STRING5 ,IDC_BTNGO ,253,213,60,14 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER dialogitem 'button' ,STRING6 ,IDC_GRPSCRATCH ,6,264,302,27 ,WS_CHILD+WS_VISIBLE+BS_GROUPBOX+BS_FLAT dialogitem 'edit' ,STRING7 ,IDC_TXTSCRATCH ,12,276,240,12 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER+ES_AUTOHSCROLL dialogitem 'button' ,'<' ,IDC_BTNSCRATCH ,255,276,48,12 ,WS_CHILD+WS_VISIBLE+WS_TABSTOP+WS_BORDER enddialog Ниже пример ручного создания ЕХЕ, положенный в основу данной программы: Код (Text): ;Пример ручного создания PE32. ;В случае изменений следи за следующими полями: ;- IMAGE_OPTIONAL_HEADER.SizeOfImage ;- SECTION_X.Rva format binary as 'exe' SCRATCH: macro padzero value*{db (value - $ and (value-1)) mod (value) dup 0} macro m1 section{ ;увеличить счетчик числа секций load a word from IMAGE_FILE_HEADER.NumberOfSections store word a+1 at IMAGE_FILE_HEADER.NumberOfSections ;задать 2 частые дельты load a dword from section#.Rva section#_RVA = a - section#_RAW section#_BASE = IMAGE_BASE + section#_RVA } DISK_SECTOR = $0000'0200 ;0'000'512 PAGE = $0000'1000 ;0'004'096 IMAGE_BASE = $0040'0000 ;4'194'304 use16 org 0 IMAGE_DOS_HEADER: .Signature dw 'MZ' .BytesOnLastPage dw 64 ;страничка = 512 байт .PagesInFile dw 1 .Relocations dw 0 .SizeOfHeaderInParagraphs dw 64/16 ;параграф = 16 байт .MinimumExtraParagraphs dw 0 .MaximumExtraParagraphs dw 0 .InitialRelativeSS dw 0 .InitialSP dw 64 .Checksum: int $20 ;просто выйти в ДОС .InitialIP dw .Checksum .InitialRelativeCS dw 0 .OffsetToRelocationTable dw 0 .OverlayNumber dw 0 .Reserved1 dw 4 dup 0 .OEMIdentifier dw 0 ;) .OEMInformation dw 0 ;) .Reserverd2 dw 10 dup 0 .OffsetToNewEXEHeader dd 64 ;IMAGE_NT_HEADERS IMAGE_NT_HEADERS: .Signature dd 'PE' IMAGE_FILE_HEADER: .Machine dw $014c ;нужен i386 и выше .NumberOfSections dw 0 ;число секций, ОСТАВЬТЕ ПУСТЫМ - ЗАПОЛНИМ В КОНЦЕ .TimeDateStamp dd %t ;секунд с 1970_01_01, 00:00 .PointerToSymbolTable dd 0 .NumberOfSymbols dd 0 .SizeOfOptionalHeader dw IMAGE_SECTION_HEADER-\ ;размер структуры IMAGE_OPTIONAL_HEADER .Characteristics dw $0002 ;исполняемый файл IMAGE_OPTIONAL_HEADER: .Magic dw $010b ;32'разрядная программа .MajorLinkerVersion db 0 ;поля версии компоновщика, можно... .MinorLinkerVersion db 0 ;...прописать смайлики .SizeOfCode dd 0 .SizeOfInitializedData dd 0 .SizeOfUninitializedData dd 0 .AddressOfEntryPoint dd PAGE+\ ;PAGE(=.SectionAlignment) тут - смещение в ОЗУ к первой секции относительно IMAGE_DOS_HEADER(=0) entry_point-SECTION_1_RAW ;точка входа соответственно .BaseOfCode dd 0 .BaseOfData dd 0 .ImageBase dd IMAGE_BASE ;база загрузки образа; образ начинается с IMAGE_DOS_HEADER :) .SectionAlignment dd PAGE ;расположить секции в ОЗУ по адресам, кратным этому числу .FileAlignment dd DISK_SECTOR ;в физ. файле секции распол. по кратным этому числу адресам .MajorOSVersion dw 0 .MinorOSVersion dw 0 .MajorImageVersion dw 0 ;свое .MinorImageVersion dw 0 ;чегось .MajorSubsystemVersion dw 4 .MinorSubsystemVersion dw 0 .Win32VersionNumber dd 0 .SizeOfImage dd PAGE*3 ;размер всего образа, отображенного в ОЗУ, включая заголовки и секции, округляйте к SectionAlignment, говорит загрузчику о наших размерах .SizeOfHeaders dd SECTION_1_RAW ;дисковый размер образа до первой секции, кругленный(просто выравнивайте первую секцию к ->) к .FileAlignment .Checksum dd 0 .Subsystem dw 2 ;win graphical user interface(гумка :ы), столько под|версий, ах! .Characteristics dw 0 .SizeOfStackReserve dd 1024*1024 ;пространство стека .SizeOfStackCommit dd 0 .SizeOfHeapReserve dd 1024*1024 ;пространство кучи .SizeOfHeapCommit dd 0 .LoaderFlags dd 0 .NumberOfDataDirectories dd 16 ;количество указателей на (предопределенные) секции ниже: .ExportTableRvaAndSize dq 0 ;1, экспорт .ImportTableRvaAndSize dd PAGE,\ ;2, импорт, будем импортировать функции 0;entry_point-SECTION_1_RAW times 14 dq 0 ;3..16 IMAGE_SECTION_HEADER: SECTION_1: .Name dq '' ;ник секции, напр. 'code' или 'maria' .VirtualSize dd 0 .Rva dd PAGE ;вспомните .SectionAlignment, по этому адресу лежит первый байт секции, отраженной в память .SizeOfRawData dd SECTION_1_RAW.-SECTION_1_RAW ;размер физических нанных, выравнивайте секции к .FileAlignment .PointerToRawData dd SECTION_1_RAW ;указатель начала физ. данных, выравнивайте секции к .FileAlignment .PointerToRelocations dd 0 .PointerToLineNumbers dd 0 .NumberOfRelocations dw 0 .NumberOfLineNumbers dw 0 .Characteristics dd $0000'0020+\ ;тут код $2000'0000+\ ;выполняемый $4000'0000+\ ;можно считывать $8000'0000 ;и записывать m1 SECTION_1 SECTION_2: .Name dq 'section2' .VirtualSize dd 0 .Rva dd PAGE*2 ;те пропустить выравнивание 1й секции и саму 1ю секцию .SizeOfRawData dd SECTION_2_RAW.-SECTION_2_RAW .PointerToRawData dd SECTION_2_RAW .PointerToRelocations dd 0 .PointerToLineNumbers dd 0 .NumberOfRelocations dw 0 .NumberOfLineNumbers dw 0 .Characteristics dd $e000'0020 m1 SECTION_2 padzero DISK_SECTOR ;выровнять к .FileAllignment SECTION_1_RAW: ;таблица импорта dd 0,0,0,kernel_name+SECTION_1_RVA,kernel_table+SECTION_1_RVA dd 0,0,0,user_name+SECTION_1_RVA,user_table+SECTION_1_RVA dd 0,0,0,shell_name+SECTION_1_RVA,shell_table+SECTION_1_RVA dd 0,0,0,0,0 kernel_name db 'kernel32.dll',0 kernel_table: exit_process dd exit_process_+SECTION_1_RVA beep dd beep_+SECTION_1_RVA dd 0 exit_process_ dw 0 db 'ExitProcess',0 beep_ dw 0 db 'Beep',0 user_name db 'user32.dll',0 user_table: message_box dd message_box_+SECTION_1_RVA dd 0 message_box_ dw 0 db 'MessageBoxA',0 shell_name db 'shell32.dll',0 shell_table: shell_execute dd shell_execute_+SECTION_1_RVA shell_alabama dd shell_alabama_+SECTION_1_RVA dd 0 shell_execute_ dw 0 db 'ShellExecuteA',0 shell_alabama_ dw 0 db 'ShellAboutA',0 entry_point: ;точка входа use32 push 0 push 0 call @f db 'Шас MessageBoxA чего-то вам покажет...',0 @@:push 0 call [message_box+SECTION_1_BASE] push 0 push caption+SECTION_2_BASE call @f db 'В случае изменений следи за следующими полями:',10,\ '- IMAGE_OPTIONAL_HEADER.SizeOfImage' ,10,\ '- SECTION_X.Rva',0 @@:push 0 call [message_box+SECTION_1_BASE] push 0 push 0 call @f db 'Попытка ShellExecuteA и notepad.exe показать меня без одежды...',0 @@:push 0 call [message_box+SECTION_1_BASE] push 5 push 0 push 0 call @f db 'pe.asm',0 @@:push 0 push 0 call [shell_execute+SECTION_1_BASE] cmp eax,32 mov eax,fail+SECTION_2_BASE mov edx,pervert+SECTION_2_BASE cmova eax,edx push 0 push 0 push eax push 0 call [message_box+SECTION_1_BASE] push 0 push 0 call @f db 'до',0 @@:push 0 call [message_box+SECTION_1_BASE] mov edi,melody+SECTION_2_BASE call edi push 0 call @f db 'www.flatAssembler, www.wasm.ru, edemko@rambler.ru',0 @@:push caption+SECTION_2_BASE push 0 call [shell_alabama+SECTION_1_BASE] push 0 push 0 call @f db 'Пока, ExitProcess ждет',0 @@:push 0 call [message_box+SECTION_1_BASE] push 0 call [exit_process+SECTION_1_BASE] padzero DISK_SECTOR SECTION_1_RAW.: SECTION_2_RAW: caption db 'Пример ручного создания PE32',0 fail db 'Обложались',0 pervert db 'Вот извращенцы',0 melody: push 300 120 call [beep+SECTION_1_BASE] ret 0 padzero DISK_SECTOR SECTION_2_RAW.: ; val = 0..2^64-1 ; merge = 0<bytes<9 of value to show ; example: repeat 8 ; display 13,10 ; ShowHex $FEDCBA9876543210,% ; end repeat macro ShowHex val*, merge*{ if merge > 0 & merge < 9 local .a, .merge .merge = (merge) shl 1 while .merge <> 0 .a = (val) shr ((.merge - 1) * 4) and 1111b or 11'0000b if .a > 11'1001b .a = .a + 111b end if display .a .merge = .merge - 1 end while end if }
нда... Код (Text): @echo off igor\7zG.exe x totalcmd\totalcmd.zip -o"%ProgramFiles%\totalcmd\" for %%1 in (totalcmd\+\arch\ totalcmd\+\compute\ totalcmd\+\drive\ totalcmd\+\editor\ totalcmd\+\media\ totalcmd\+\net\ totalcmd\+\tweak\ totalcmd\+\tc\) do ( for %%2 in (%%1*) do ( echo %%2 igor\7zG.exe x "%%2" -o"%ProgramFiles%\%%1" ) ) explorer /select, "%ProgramFiles%\totalcmd\totalcmd+.exe"
Rockphorr, обязательно посмотрю, спасибо! Зашел сюда, месяц спустя. Рад всех видеть. Разобрался в *.bat-анике. Привожу 2 файла из архива: вступление Код (Text): Modular Total Commander email:edemko@rambler.ru enu: mtc.txt this file mtc.cmd silly cmd.exe-based installer, be aware! tested on win xp pro sp3 igor\ the installer uses Igor Pavlov's archiver TotalCmd\+\*\* 1st * means any folder, 2nd * - any file Igor Pavlov supports compose *\* at your own to apply patches after extraction, put mtc.bat, mtc.cmd, mtc.reg into *\* and the installer will call them TotalCmd\TotalCmd.zip installer calls Igor for original Total Commander TotalCmd\TotalCmd.zip\TotalCmd+.exe makes Total run with "TotalCmd\+\tc\" folder additions TotalCmd\+\tc\!.rar - some info TotalCmd\+\tc\bar.rar - extended total status bars TotalCmd\+\tc\Desktop.rar - TotalCmd\+\tc\ini.rar - total (and total plugs) conf files TotalCmd\+\tc\OpenFileTC.rar - extended total editor select TotalCmd\+\tc\plugin.rar - total plugins folder TotalCmd\+\tc\plugman.rar - extended total plugins configurator TotalCmd\+\tc\ReInit.rar - use it to apply patches without installer TotalCmd\+\tc\sound.rar - total sounds TotalCmd\+\tc\TCShell.rar - adds total to shell TotalCmd\+\tc\Ultra TC Editors.rar - extended total configurators rus: mtc.txt этот файл mtc.cmd установщик, использующий грозный cmd.exe, не пробдите! тестировался под win xp pro sp3 igor\ установщику понравился архиватор Игоря Павлова TotalCmd\+\*\* 1ая звездочка * обозначает любую папку, 2ая * - файл архива, поддерживаемый архиватором составляйте *\* по своему вкусу для внесения патчей архивы могут содержать mtc.bat, mtc.cmd, mtc.reg - установщик их и вызовет TotalCmd\TotalCmd.zip непоковырянный Total Commander TotalCmd\TotalCmd.zip\TotalCmd+.exe запускает тотал с прибамбахами из папки "TotalCmd\+\tc\" TotalCmd\+\tc\!.rar - какая-то информация TotalCmd\+\tc\bar.rar - панельки тотала TotalCmd\+\tc\Desktop.rar - TotalCmd\+\tc\ini.rar - тоталовские (и его плугов) файлы настроек TotalCmd\+\tc\OpenFileTC.rar - запускалка редакторов TotalCmd\+\tc\plugin.rar - плужки тотала TotalCmd\+\tc\plugman.rar - настройщик плагинов тотала TotalCmd\+\tc\ReInit.rar - используй для запуска патчей без установщика TotalCmd\+\tc\sound.rar - звуковая схемма TotalCmd\+\tc\TCShell.rar - добавляет тотал в проводник TotalCmd\+\tc\Ultra TC Editors.rar - настройщики тотала установщик Код (Text): rem enu: start rem rus: старт echo off cls rem enu: title rem rus: заглавие echo. echo :Modular Total Commander rem enu: language select rem rus: выбор языка echo. echo :1=enu 2=rus set /p lang= if "%lang%"=="1" ( set langDummyCmd=dummy cmd, be aware! set langSetDest=specify destination folder or select a variant below set langIgorStarted=extracting files set langDir=dir set langFile=file set langBatCall=contains mtc.bat, calling set langCmdCall=contains mtc.cmd, calling set langRegCall=contains mtc.reg, calling set langMainFile=main program set langDone=done, bye! ) else if "%lang%"=="2" ( set langDummyCmd=грозный cmd, будьте бдительны! set langSetDest=укажите папку назначения или выберите вариант ниже set langIgorStarted=извлекаем файлы set langDir=папка set langFile=файл set langBatCall=содержит mtc.bat, вызываем set langCmdCall=содержит mtc.cmd, вызываем set langRegCall=содержит mtc.reg, вызываем set langMainFile=главная программа set langDone=все, пока! ) rem enu: dummy script warning rem rus: предупредим о своей простоте echo. echo :%langDummyCmd% rem enu: ask for destination folder rem rus: спросить папку назначения echo. echo :%langSetDest% echo 1 = %SystemDrive% echo 2 = %ProgramFiles% echo 3 = %SystemDrive%\temp set /p dest= if "%dest%"=="1" ( set dest=%SystemDrive% ) else if "%dest%"=="2" ( set dest=%ProgramFiles% ) else if "%dest%"=="3" ( set dest=%SystemDrive%\temp ) :set_lang. rem enu: count folders and files rem rus: посчитать папки и файлы set /a drs=0 set /a fls=0 call :loop :cntDrs :cntFls goto :cntDrsFls. :cntDrs set /a drs=drs+1 goto :eof :cntFls set /a fls=fls+1 goto :eof :cntDrsFls. rem enu: extraction rem rus: извлечение echo. echo :%langIgorStarted% set /a drsNow=0 set /a flsNow=0 call :loop :outDrs :outFls goto :outDrsFls. :outDrs set /a drsNow=drsNow+1 echo %langDir% %drsNow%/%drs% = %~1 set destNow=%dest%\%~1 goto :eof :outFls set /a flsNow=flsNow+1 echo %langFile% %flsNow%/%fls% = %~nx1 igor\7zG.exe x %1 -o"%destNow%" set mtc=%destNow%\%~n1\mtc. if exist "%mtc%bat" ( echo %langBatCall% start /wait cmd /c "%mtc%bat" ) if exist "%mtc%cmd" ( echo %langCmdCall% start /wait cmd /c "%mtc%cmd" ) if exist "%mtc%reg" ( echo %langRegCall% reg import "%mtc%reg" >nul ) goto :eof :outDrsFls. rem enu: main file rem rus: главный файл echo. echo :%langMainFile% igor\7zG.exe x totalcmd\totalcmd.zip -o"%dest%\totalcmd" explorer /select,"%dest%\totalcmd\totalcmd+.exe" echo. echo :%langDone% pause goto :eof rem enu: dirs and files walking cycle rem rus: цыкл прохода по каталогам и файлам :loop for /d %%1 in ("totalcmd\+\*") do ( call %1 "%%1" for %%2 in ("%%1\*") do ( call %2 "%%2" ) ) goto :eof code.google.com внушает надежды, но у него, видимо, лимит на выгрузку, а та у нас медленная. Прошу тех у кого быстрые скорости отпостить сюда согласием, дабы перезалить файл. Привожу к сведению, файл в 35 МБ при выгрузке на code.google.com берет вдвое больше. 2011_12_08 файл при выгрузке на code.google.com берет вдвое больше - ? http://fasmme.googlecode.com/files/mtc.part1.rar http://fasmme.googlecode.com/files/mtc.part2.rar