Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Создание кода программы


Автор: Bima 25.8.2006, 08:04
Ситуация такая:
Нужно в программе создать блок, который бы на поле Мемо, или какое другое выводил файл в виде массива.
Во второй программе (в коде) нужно этот массив назад преобразовать в файл.

Что бы понять ситуацию яснее, объясню на примере. Есть текстовый файл (программа должна обрабатывать любые файлы), я его открываю первой программой и она в поле Мемо показывает мне код типа такого:

Код

char StrMain[154]=... // здесь должны быть коды файла


Я этот код вставляю во вторую программу и она мне по нажатию на определенную кнопку делает точно такой же файл в указаном месте.

Может, кто сталкивался с такой проблемой?

Автор: Gordon 25.8.2006, 08:53
А если просто скопировать файл?

Автор: Bima 25.8.2006, 09:02
На другом компьютере, где будет работать вторая программа, это файла не будет!
Он должен сам создаться (один в один)

Автор: Artemon 25.8.2006, 12:41
Используй именованные каналы или сокеты.
поиск по google

Автор: Bima 25.8.2006, 12:59
Блин, что мне теперь для этого сеть создавать?

А если на компьютере сети нет. Вариант домашнего???

Автор: 586 25.8.2006, 13:28
Код
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

char *pMem=0;
DWORD cb;

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 LARGE_INTEGER li;
 DWORD dwRead;
 if(OpenDialog1->Execute())
 {
  HANDLE f=CreateFile(OpenDialog1->FileName.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  if(f==(HANDLE)-1)
  {
   MessageBoxA(Handle, SysErrorMessage(GetLastError()).c_str(), "Failed to open file", 16);
  } else {
   GetFileSizeEx(f, &li);
   cb=li.LowPart;
   pMem=new char[cb];
   ReadFile(f, pMem, cb, &dwRead, 0);
   CloseHandle(f);
  }
 }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
 DWORD dwWritten;
 if(SaveDialog1->Execute())
 {
  HANDLE f=CreateFile(SaveDialog1->FileName.c_str(), GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  if(f==(HANDLE)-1)
   MessageBoxA(Handle, SysErrorMessage(GetLastError()).c_str(), "Failed to save file", 16);
  else {
   WriteFile(f, pMem, cb, &dwWritten, 0);
   if(!dwWritten)
    MessageBoxA(Handle, SysErrorMessage(GetLastError()).c_str(), "Failed to write file", 16);
   CloseHandle(f);
  }
 }
}

После нажатия кнопки Button1 у тебя будет массив байт pMem и его размер - cb. Чего хочешь с ним - то и делай.

Автор: Bima 25.8.2006, 13:36
Все замечательно.
Функций ввода вывода очень много, что-то подобное я сам написал, вот только при выводе на экран (Мемо) они будут отображаться совсем по другому, и если их вставить в КОД программы (хочу подчеркнуть именно в код второй программы), то при записи этого массива будет различаться с исходником.

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

Автор: 586 25.8.2006, 13:42
Цитата(Bima @  25.8.2006,  14:36 Найти цитируемый пост)
удобочитаемый код

hex dump?

Автор: Bima 25.8.2006, 13:55
то есть?
Цитата

hex dump

можно примерчик в студию
хотя бы в общих чертах

Автор: 586 25.8.2006, 14:18
Цитата(Bima @  25.8.2006,  14:55 Найти цитируемый пост)
то есть?

как в hex-редакторе
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Автор: Bima 25.8.2006, 14:32
Ну что то в этом виде....
Если можно будет его перевести (я пишу про массив) из char в hex и потом обратно, то этот вариант подойдет.

У кого нибудь есть идеи как это сделать?
можно конечно по символу брать
Код

Sprintf (a "%h" pMem[i]);

Но мне кажется это будет долго, и я не знаю, как назад преобразовать в массив.
к тому же, как этот дамп записывать в коде программы?

Автор: 586 25.8.2006, 14:36
Цитата(Bima @  25.8.2006,  15:32 Найти цитируемый пост)
как назад преобразовать в массив
А для чего это?

Цитата(Bima @  25.8.2006,  15:32 Найти цитируемый пост)
как этот дамп записывать в коде программы? 
Не понял

Автор: Bima 25.8.2006, 14:43
ну допустим делаю я инстолятор (на самом деле это не так, но задача похожа). Мне в одной программе (далее по тексту я буду называть ее "второй") нужно, что бы программа сама из себя создала несколько файлов. То есть в самом коде программы должны быть присутствовать данные всех файлов (не только текстовых).
Для этого "первая программа" должна подготовить данные для второй программы.

версии копирования и распаковки файлов не подойдут. Архиваторы тоже не подходят, по независящи от меня условиям.

Автор: 586 25.8.2006, 14:47
Цитата(Bima @  25.8.2006,  15:43 Найти цитируемый пост)
нужно, что бы программа сама из себя создала несколько файлов. То есть в самом коде программы должны быть присутствовать данные всех файлов (не только текстовых).

Цитата(Bima @  25.8.2006,  09:04 Найти цитируемый пост)
Нужно в программе создать блок, который бы на поле Мемо, или какое другое выводил файл в виде массива.

Зачем тогда его в Memo выводить и делать такое непонятное преобразование??

Цитата(Bima @  25.8.2006,  15:43 Найти цитируемый пост)
Для этого "первая программа" должна подготовить данные для второй программы.

Это как?

Автор: Bima 25.8.2006, 14:56
Цитата

Зачем тогда его в Memo выводить??


вот допустим есть текстовый файл, который имеет внутри все три цифры - "123"
первой программой я читаю его и она у меня формирует строку в Мемо:
Код

char StrMain[3]="123"; 


потом при разработке второй программы я вставляю ее (полученную строчку) в код программы. После этого, вторая программа запишет этот массив StrMain в файл, который не будет отличаться от того, который я считывал первой программой.

Это все я рассказал на примере текстового файла. Но если взять исполняемый файл, там есть не печатанные символы, их Мемо не поймет. В результате, файл создастся не такой, как оригинальный.

Автор: 586 25.8.2006, 15:09
Цитата(Bima @  25.8.2006,  15:56 Найти цитируемый пост)
Но если взять исполняемый файл, там есть не печатанные символы, их Мемо не поймет. В результате, файл создастся не такой, как оригинальный

Ты хочешь просмотреть exe-шник в Memo. Или ещё отредактировать сохранить в файл??? Ничего не понял.

Автор: Bima 25.8.2006, 15:18
Цитата

Ты хочешь просмотреть exe-шник в Memo. Или ещё отредактировать сохранить в файл??? Ничего не понял. 

Я не хочу его просматривать!!! и тем более не хочу его редактировать
Мне нужно создать код, что бы он создавал точно такие же файлы, который я читаю первой программой. Что у них находится внутри, мне не интересно. Файлы могут быть ЛЮБЫЕ (txt, exe, bin, cab, rar и т.д.).

Мемо нужен для того, что бы вывести туда информацию, точнее сгенерированный код для будущей программы. я просто не знаю, более удобного варианта... (ну можно на крайний случай вывести в RichText).
Проблема не в считывании и записывании файла, а в преобразовании в текстовый вид, а потом назад в бинарный. Вариант преобразования в шеснадцатитиричную форму меня бы устроил, только как все это сделать (желательно быстро). Скорость, нужна, что бы вторая программа не 20 минут думала, что бы переворить внутреннюю информацию и создать файл в 10 кб.

Автор: 586 25.8.2006, 15:22
Цитата(Bima @  25.8.2006,  16:18 Найти цитируемый пост)
а потом назад в бинарный

Если ты его редактировать не собираешься, какой смысл тогда переводить его обратно.

Автор: Bima 25.8.2006, 15:25
ок.
как мне создать код программы, который делал бы мне файл ну скажем cmd.exe (из стандартной поставки винды) ???

Автор: 586 25.8.2006, 15:29
Цитата(Bima @  25.8.2006,  16:25 Найти цитируемый пост)
как мне создать код программы, который делал бы мне файл ну скажем cmd.exe (из стандартной поставки винды) ??? 

Из чего он должен его делать? Где исходные данные?

Автор: Bima 25.8.2006, 15:33
исходные данные: файл cmd.exe. На этом же компьютере установлен ВСВ.
Задача: нужно создать программу, что бы на другом компьютере, она создала ТОЧНО ТАКОЙ-ЖЕ ФАЙЛ cmd.exe (примем, что его там нет).

Автор: dumb 26.8.2006, 02:18
мдя... вот почему порой целесообразно писать о том, чего хочется добиться в результате.

где-то тут на форуме есть около миллиона топиков о сохранении файлов в ресурсы. ключевые слова для поиска: FindResource, LoadResource

Автор: Bima 26.8.2006, 07:28
В принципе тему можно считать закрытой, хотя вопрос не решили, как я хотел.
Тема создавалась для того, чо бы скрыть файл в другом файле, а если быть точнее, то несколько файлов.  При создании ресурсов, любой мало-мальский редактор ресурсов может спокойно вытянуть все эти файлы из exe-ка. Своего рода это инсталятор, который делает еще кучу функций, по защите программы. А при создании ресурсов, эту программу можно очень легко вскрыть  smile 

Автор: dumb 26.8.2006, 14:13
ресурсы - не единственное решение, но в данном случае, пожалуй, самое оптимальное.
шифруй ресурсы.

Автор: Bima 26.8.2006, 14:34
а что, есть возможность на лету их зашифровать и расшифровать?

Автор: 586 26.8.2006, 18:43
Кажется, я тебя понял. Вот код:
Код
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void proc1(char *ch)
{
    HANDLE f, hMap;
    void *pMap;
        char *err, *buff;
        LARGE_INTEGER li;
        DWORD ddd;
    f=CreateFile(ch, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if(f!=(HANDLE)-1)
    {
        hMap=CreateFileMapping(f, 0, PAGE_READONLY, 0, 0, 0);
        if(hMap)
        {
                        pMap=MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
            if(pMap)
            {
                              GetFileSizeEx(f, &li);
                              ddd=li.LowPart;
                              buff=new char[ddd*4+20+ddd/128];
                              buff[0]=0;
                              lstrcat(buff, "unsigned char data[]={");
                              __asm {
                                mov esi, dword ptr pMap
                                mov edi, buff
                                add edi, 22
                                mov ecx, ddd
                              loc_1:
                                lodsb
                                mov bl, 100
                                xor ah, ah
                                div bl
                                or al, al
                                setz dl
                                jz loc_2
                                add al, 48
                                stosb
                              loc_2:
                                mov al, ah
                                xor ah, ah
                                mov bl, 10
                                div bl
                                or al, al
                                jnz loc_6
                                or dl, dl
                                jnz loc_3
                              loc_6:
                                add al, 48
                                stosb
                              loc_3:
                                mov al, ah
                                add al, 48
                                stosb
                                mov al, ','
                                stosb
                                test cx, 11111111b
                                jne loc_4
                                mov ax, 0x0A0D
                                stosw
                              loc_4:
                              loop loc_1
                                dec edi
                                mov ax, ';}'
                                stosw
                                xor al, al
                                stosb
                              }
                              UnmapViewOfFile(pMap);
                              Form1->Memo1->Text=buff;
                              delete buff;
            } else MessageBoxA(Form1->Handle, "Can't map view of file.", 0, 16);
            CloseHandle(hMap);
        } else MessageBoxA(Form1->Handle, "Can't create file mapping.", 0, 16);
        CloseHandle(f);
    } else {
        FormatMessage(0x1100, 0, GetLastError(), 0, (char*)&err, 0, 0);
                MessageBoxA(Form1->Handle, err, "Can't open target file", 16);
    }
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 proc1("C:\\timer.exe");
}

На форме Memo1, Button1.
Скорость хорошая - ~ 1.2 мб/сек
Конвертирует файл в код типа:
Код

char data[]={...};

Автор: stmamont 26.8.2006, 21:06
Сообщение мое стерлось.
Теперь расписывать не буду.
Предыдущий пост - круто , но не понятно, можно комментарии что там проиходит?

Можно еще попробвать MIME - кодирование.
Можно попробовать покопать как делают исталляторы (хотя б идею)
Можно воспользоваться каким нибудь инсталлятором (NSIS например).
Возможно он поможет полностью тебе. (он скриптовый, и может быть ничего не придется кодить)))

А вообще асм рулит) (но не понятно(()

Автор: 586 26.8.2006, 22:40
Цитата(stmamont @  26.8.2006,  22:06 Найти цитируемый пост)
можно комментарии что там проиходит

Да ничего сложного. Достаточно открыть справочник по асм.
Код
void proc1(char *ch)
{
    HANDLE f, hMap;
    void *pMap;
        char *err, *buff;
        LARGE_INTEGER li;
        DWORD ddd;
    f=CreateFile(ch, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if(f!=(HANDLE)-1)
    {
        hMap=CreateFileMapping(f, 0, PAGE_READONLY, 0, 0, 0);
        if(hMap)
        {
            pMap=MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
            if(pMap)
            {
                GetFileSizeEx(f, &li);                // определение размера файла
                ddd=li.LowPart;                    // младшая часть размера (4 байта) сохраняется отдельно (для __asm вставки)
                buff=new char[ddd*4+20+ddd/128];        // выделение памяти (здесь будет строка, только работать с ней будем напрямую)
                buff[0]=0;                    // очистка строки
                lstrcat(buff, "unsigned char data[]={");    // ...
                __asm {
                        mov esi, dword ptr pMap   
                        mov edi, buff
                        add edi, 22        // позиция, где будет записываться строка
                        mov ecx, ddd        // для цикла loop
                loc_1:
                        lodsb            // читает байт по адресу esi, заносит его в регистр al и увеличивает esi на единицу
        // здесь происходит преобразование числа в строку
                        mov bl, 100        // на что будем делить
                        xor ah, ah        // обнуляет регистр ah (старшую часть регистра ax)
                        div bl            // делит регистр ax на bl  (ax/100)
                        or al, al        // проверка, равен ли al нулю (if(al) ...)
                        setz dl            // заносит результат в регистр dl
                        jz loc_2        // if(!al) goto loc_2; (если это 0, то он не записывается, поскольку, например, 10 и 010 - это разные числа (разная система счисления)
                        add al, 48        // al+='0';
                        stosb            // записывает регистр al по адресу edi, и увеличивает его на единицу
                loc_2:
                        mov al, ah        // ah - остаток от деления, помещается в al
                        xor ah, ah        // ah обнуляется
                        mov bl, 10        // на что вудет делиться
                        div bl            // ax/bl
                        or al, al
                        jnz loc_6        // if(al) goto loc_6; (ноль добавляется)
                        or dl, dl        // проверка предыдущего условия
                        jnz loc_3        // if(dx) goto loc_3; (если число >=100, то ноль не убирается)
                loc_6:
                        add al, 48        // al+='0';
                        stosb            // ...
                loc_3:
                        mov al, ah        // помещение остатка в регистр al для stosb
                        add al, 48        // al+='0';
                        stosb
                        mov al, ','
                        stosb            // добавление символа ',' в конец строки
                        test cx, 11111111b    // *
                        jne loc_4
                        mov ax, 0x0A0D
                        stosw            // добавление символа "\n", то есть начало новой строки
                loc_4:
                        loop loc_1        // цикл: if(ecx!=0) goto loc_1;
                        dec edi            // edi--;  (убирает лишнюю запятую)
                        mov ax, ';}'
                        stosw            // добавление "};" в конец строки
                        xor al, al
                        stosb            // завершение строки
                }
                UnmapViewOfFile(pMap);
                Form1->Memo1->Text=buff;
                delete buff;            // освобождение памяти
            } else MessageBoxA(Form1->Handle, "Can't map view of file.", 0, 16);
            CloseHandle(hMap);
        } else MessageBoxA(Form1->Handle, "Can't create file mapping.", 0, 16);
        CloseHandle(f);
    } else {
        FormatMessage(0x1100, 0, GetLastError(), 0, (char*)&err, 0, 0);
                MessageBoxA(Form1->Handle, err, "Can't open target file", 16);
    }
}

-------
*  test cx, 11111111b - устраняет проблему со вставкой строки в Билдер (поскольку строка будет длинная (>1024 символов) то выскакивает ошибка), не придумал ничего, лучше этого. Если в регистре ecx 8 первых бит равны 1, то в строку добавляется символ "\n".

Автор: Bima 28.8.2006, 09:08
Супер.
586 ОГРОМНОЕ СПАСИБО
Это то, что нужно!!!!

Великолепное решение задачи, и скорость отличная!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)