2016-05-01 4 views
1

Ich schrieb einen C++ - Installer Bootstrapper für meine Anwendung (harte Voraussetzung, da ich die vollständige Kontrolle über das Format der Datei benötigt). Jetzt versuche ich herauszufinden, wie ich mein MSI mit möglichst wenig Overhead in meine Bootstrap-EXE einbetten kann. All meine Suche zeigt mir das Gegenteil (wie man eine EXE in ein MSI einbindet).Wie ein MSI in meine Bootstrapper-Exe einbetten

Dieses Installationsprogramm muss offline arbeiten, damit ich meinen Bootstrapper nicht einfach die Datei herunterladen kann.

Ich könnte es natürlich als Bytestream in meiner Quelldatei einbetten, aber das verursachte eine Menge Overhead auf die Größe der Datei.

Antwort

2

Es ist ziemlich üblich, Daten als Ressource in der Binärdatei einzubetten und sie zu extrahieren. Diese Art der Sache:

http://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource

http://www.codeproject.com/Articles/4221/Adding-and-extracting-binary-resources

IIRC, wird der Compiler die Daten bei der Erstellung mit den richtigen Kniffen einbetten, so dass Sie nur um sie extrahieren müssen.

Hier ist ein Beispiel für das Extrahieren der Daten.

#include "stdafx.h" 
#include "resource.h" 
#include <iostream> 
#include <fstream> 
#include <iterator> 
#include <vector> 
#include <Windows.h> 
#include <shellapi.h> 

using namespace std; 

void extract_bin_resource(std::wstring strCustomResName, int nResourceId, std::string strOutputPath) 
{ 
    HGLOBAL hResourceLoaded; // handle to loaded resource 
    HRSRC hRes;    // handle/ptr to res. info. 
    char *lpResLock;  // pointer to resource data 
    DWORD dwSizeRes; 
    std::string strOutputLocation; 
    std::string strAppLocation; 

    hRes = FindResource(NULL, MAKEINTRESOURCE(nResourceId), strCustomResName.c_str()); 

    hResourceLoaded = LoadResource(NULL, hRes); 
    lpResLock = (char *)LockResource(hResourceLoaded); 
    dwSizeRes = SizeofResource(NULL, hRes); 

    std::ofstream outputFile(strOutputPath.c_str(), std::ios::binary); 
    outputFile.write((const char *)lpResLock, dwSizeRes); 
    outputFile.close(); 
} 

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { 
    // Extract the bundled installer 
    extract_bin_resource(L"MSI", IDR_MSI1, "installer.msi"); 

    // Execute the installer 
    SHELLEXECUTEINFO ShExecInfo = { 0 }; 
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 
    ShExecInfo.hwnd = NULL; 
    ShExecInfo.lpVerb = NULL; 
    ShExecInfo.lpFile = L"msiexec.exe"; 
    ShExecInfo.lpParameters = L"/i installer.msi"; 
    ShExecInfo.lpDirectory = NULL; 
    ShExecInfo.nShow = SW_SHOW; 
    ShExecInfo.hInstApp = NULL; 
    ShellExecuteEx(&ShExecInfo); 
    WaitForSingleObject(ShExecInfo.hProcess, INFINITE); 

    // Delete the installer 
    DeleteFile(L"installer.msi"); 

    return 0; 
} 
+0

Bei einer 52-MB-Datei werden 10 MB Overhead hinzugefügt. Irgendeine Idee, wie man das reduziert? –

+0

Macht nichts, es war wegen mir im Debug-Modus zu bauen –