Uruchomianie programu exe przechowywanego w zasobach

dział ogólny

Uruchomianie programu exe przechowywanego w zasobach

Nowy postprzez arturhalaczkiewicz » niedziela, 19 października 2014, 22:05

Witam,
piszę graficzną nakładkę na konwerter https://www.ffmpeg.org/about.html na własne potrzeby (mam dość klepania ciągle tego samego :) )
Ale chciałbym żeby plik wykonywalny był portable, więc wymyśliłem że ffmeg.exe (i zip.exe) umieszczę w zasobach programu i w miarę potrzeby je wykopiuję na dysk, uruchomię i skasuje. Ale ffmeg ma >28mb i taka metoda wydaje mi się mało elegancka :( Więc wymyśliłem, że może dałoby się URUCHOMIĆ program będący w zasobach programu? Mam nadzieję że wyrażam się jasno, dotychczas wykopiowyję z zasobów programu ffmeg.exe i przez ShellExecuteEx go wywyołuję, czekam aż się skończy mielić (WaitForSingleObject) i robię coś dalej. Ale nie chciałbym uruchamiać ffmeg.exe z dysku, tylko bezpośrednio z pamięci. Taki RAMDISK z dawnych czasów? Macie jakiś pomysł?
~a
Avatar użytkownika
arturhalaczkiewicz
Bladawiec
Bladawiec
 
Posty: 13
Dołączył(a): piątek, 16 grudnia 2011, 13:48
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: windows 7
Kompilator: builder 6 prof
Gadu Gadu: 0
    Windows 7Firefox

Re: Uruchomianie programu exe przechowywanego w zasobach

Nowy postprzez Cyfrowy Baron » poniedziałek, 20 października 2014, 04:51

Nie da się uruchomić programu będącego w zasobach. Trzeba go przedtem wypakować.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Uruchomianie programu exe przechowywanego w zasobach

Nowy postprzez polymorphism » poniedziałek, 20 października 2014, 12:07

A kto powiedział, że aplikacja portable jest w jednym pliku wykonywalnym? Portable znaczy tyle, że aplikacja do uruchomienia nie wymaga uprzedniej instalacji i - choć nie zawsze - wszystkie dane konfiguracyjne trzyma w "przenośnym" katalogu (wirtualizacja?) a nie w rejestrze systemowym czy w folderze użytkownika (np. %appdata%).

Jeśli mnie pamięć nie myli, są kreatory do tworzenia aplikacji portable - nie wiem, czy są jakieś darmowe, ale poszukaj.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: Uruchomianie programu exe przechowywanego w zasobach

Nowy postprzez Cyfrowy Baron » poniedziałek, 20 października 2014, 15:37

Są kreatory darmowe - nie najlepsze, ale są. Jednak taka aplikacja portable ma to do siebie, że jest dystrybuowana w jednym pliku, ale po uruchomieniu wypakowuje się do jednego katalogu, często tworząc podkatalogi. Jeżeli jednak potrafisz programować, to nie ma sensu używanie takich kreatorów, gdyż sam może wszystko umieścić w zasobach.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Uruchomianie programu exe przechowywanego w zasobach

Nowy postprzez arturhalaczkiewicz » poniedziałek, 20 października 2014, 21:21

Dziękuję za sugestię.
Jeżeli chodzi o "nie da się" - to jednak się da :)
Tutaj jest bardzo fajna rutynka: http://www.rohitab.com/discuss/topic/31681-c-run-program-from-memory-and-not-file/
Po przerobieniu na moje potrzeby, działa!
Jeżeli zaś chodzi o portable - to faktycznie, źle doprecyzowałem. Zależało mi na pojedynczym pliku ze wszystkim który mogę uruchomić na dowolnym komputerze nie myśląc o instalacji, bibliotekach i ffmegu. Moja wina :)
~a

Jakby ktoś potrzebował dla potomnych tej rutynki, poniżej postać w jakiej kompiluje się na bcb6 i działa.

ID - nazwa zasobu
Parameters - parametry z jakimi wywoływany jest program
WaitForFinish - bool czy procedura ma czekać na zakończenie działania procesu czy iść dalej

przykładowe wywołanie z jakim wszystko mi działa:
Kod: Zaznacz cały
ResourcesRun(ID_FFMPEG, "-i audio.wave -pix_fmt rgb24  -r 25.00   -i obrazki%04d.tga  -y -s 1920x1080 -r 25.00 -ar 44100 -vcodec mpeg4 -qscale 5 film.mov", true);


a to rutynka:

KOD cpp:     UKRYJ  
#include <windows.h>
#include <iostream>

typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE,PVOID);
NtUnmapViewOfSectionF NtUnmapViewOfSection = (NtUnmapViewOfSectionF)GetProcAddress(LoadLibrary(  "ntdll.dll"),"NtUnmapViewOfSection");


void ResourcesRun(unsigned short ID, AnsiString Parameters, bool WaitForFinish)
{
    HGLOBAL hResData;
    HRSRC   hResInfo;
    void    *pvRes;
    DWORD dwSize;
    char* pImage;
    HMODULE hModule = GetModuleHandle(NULL);
    hResInfo = FindResource(hModule, MAKEINTRESOURCE(ID/*nazwa zasobu*/), RT_RCDATA);

    if(!hResInfo)
    {
            Application->MessageBox("Nie można przeprowadzić operacji. Taki zasób nie istnieje!","BŁĄD!", MB_OK | MB_ICONSTOP);
            return;
    }

    hResData = LoadResource(hModule, hResInfo);
    pvRes = LockResource(hResData);
    dwSize = SizeofResource(hModule, hResInfo);
    pImage = (char*)malloc (dwSize);
    memset(pImage,0,dwSize);
    memcpy (pImage, pvRes, dwSize);

    DWORD dwWritten = 0;
    DWORD dwHeader = 0;
    DWORD dwImageSize = 0;
    DWORD dwSectionCount = 0;
    DWORD dwSectionSize = 0;
    DWORD firstSection = 0;
    DWORD previousProtection = 0;
    DWORD jmpSize = 0;
 
    IMAGE_NT_HEADERS INH;
    IMAGE_DOS_HEADER IDH;
    IMAGE_SECTION_HEADER Sections[1000];
 
    PROCESS_INFORMATION peProcessInformation;
    STARTUPINFO peStartUpInformation;
    CONTEXT pContext;
 
    char* pMemory;
    char* pFile;
    char pPath[MAX_PATH];

    GetModuleFileName(NULL,pPath,MAX_PATH);
    char* lfMemory;
    int fSize;
    FILE* pLocalFile = fopen(pPath,"rb");
    fseek(pLocalFile,0,SEEK_END);
    fSize = ftell(pLocalFile);
    rewind(pLocalFile);
    lfMemory = (char*)malloc(fSize);
    fread(lfMemory,1,fSize,pLocalFile);
    fclose(pLocalFile);
    memcpy(&IDH,lfMemory,sizeof(IDH));
    memcpy(&INH,(void*)((DWORD)lfMemory+IDH.e_lfanew),sizeof(INH));
    free(lfMemory);

    DWORD localImageBase = INH.OptionalHeader.ImageBase;
    DWORD localImageSize = INH.OptionalHeader.SizeOfImage;
 
    memcpy(&IDH,pImage,sizeof(IDH));
    memcpy(&INH,(void*)((DWORD)pImage+IDH.e_lfanew),sizeof(INH));
         
    dwImageSize = INH.OptionalHeader.SizeOfImage;
    pMemory = (char*)malloc(dwImageSize);
    memset(pMemory,0,dwImageSize);
    pFile = pMemory;
 
    dwHeader = INH.OptionalHeader.SizeOfHeaders;
    firstSection = (DWORD)(((DWORD)pImage+IDH.e_lfanew) + sizeof(IMAGE_NT_HEADERS));
    memcpy(Sections,(char*)(firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections);
 
    memcpy(pFile,pImage,dwHeader);
 
    if((INH.OptionalHeader.SizeOfHeaders % INH.OptionalHeader.SectionAlignment)==0)
        jmpSize = INH.OptionalHeader.SizeOfHeaders;
    else
    {
        jmpSize = INH.OptionalHeader.SizeOfHeaders / INH.OptionalHeader.SectionAlignment;
        jmpSize += 1;
        jmpSize *= INH.OptionalHeader.SectionAlignment;
    }
 
    pFile = (char*)((DWORD)pFile + jmpSize);
 
    for(dwSectionCount = 0; dwSectionCount < INH.FileHeader.NumberOfSections; dwSectionCount++)
    {
        jmpSize = 0;
        dwSectionSize = Sections[dwSectionCount].SizeOfRawData;
        memcpy(pFile,(char*)(pImage + Sections[dwSectionCount].PointerToRawData),dwSectionSize);
         
        if((Sections[dwSectionCount].Misc.VirtualSize % INH.OptionalHeader.SectionAlignment)==0)
            jmpSize = Sections[dwSectionCount].Misc.VirtualSize;
        else
        {
            jmpSize = Sections[dwSectionCount].Misc.VirtualSize / INH.OptionalHeader.SectionAlignment;
            jmpSize += 1;
            jmpSize *= INH.OptionalHeader.SectionAlignment;
        }
        pFile = (char*)((DWORD)pFile + jmpSize);
    }
 
 
    memset(&peStartUpInformation,0,sizeof(STARTUPINFO));
    memset(&peProcessInformation,0,sizeof(PROCESS_INFORMATION));
    memset(&pContext,0,sizeof(CONTEXT));
 
    peStartUpInformation.cb = sizeof(peStartUpInformation);
    if(CreateProcess(pPath, Parameters.c_str()/*parametry do wywołania programu*/, NULL ,NULL,false,CREATE_SUSPENDED, NULL,NULL,&peStartUpInformation,&peProcessInformation))
    {
        pContext.ContextFlags = CONTEXT_FULL;
        GetThreadContext(peProcessInformation.hThread,&pContext);
        if(INH.OptionalHeader.ImageBase==localImageBase&&INH.OptionalHeader.SizeOfImage<=localImageSize)
            VirtualProtectEx(peProcessInformation.hProcess,(LPVOID)(INH.OptionalHeader.ImageBase),dwImageSize,PAGE_EXECUTE_READWRITE,&previousProtection);
        else
        {
            NtUnmapViewOfSection(peProcessInformation.hProcess,(PVOID)(localImageBase));
                        VirtualAllocEx(peProcessInformation.hProcess,(LPVOID)(INH.OptionalHeader.ImageBase),dwImageSize,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
        }
        WriteProcessMemory(peProcessInformation.hProcess,(void*)(INH.OptionalHeader.ImageBase),pMemory,dwImageSize,&dwWritten);
        WriteProcessMemory(peProcessInformation.hProcess,(void*)(pContext.Ebx + 8),&INH.OptionalHeader.ImageBase,4,&dwWritten);
        pContext.Eax = INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint;
        SetThreadContext(peProcessInformation.hThread,&pContext);
        VirtualProtectEx(peProcessInformation.hProcess,(void*)(INH.OptionalHeader.ImageBase),dwImageSize,previousProtection,0);
        bool res = ResumeThread(peProcessInformation.hThread);
        // Wait For Finish?
        if (WaitForFinish && res) WaitForSingleObject(peProcessInformation.hProcess, INFINITE);

    }
    free(pMemory);

}
 
Avatar użytkownika
arturhalaczkiewicz
Bladawiec
Bladawiec
 
Posty: 13
Dołączył(a): piątek, 16 grudnia 2011, 13:48
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: windows 7
Kompilator: builder 6 prof
Gadu Gadu: 0
    Windows 7Firefox


Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 57 gości

cron