Archived Forum Post

Index of archived forum posts

Question:

How to Write a Self-Extractor (for the Windows OS)

Feb 04 '13 at 10:39

Here's the idea: Instead of using Chilkat Zip or "Zip 2 Secure EXE" to create a self-extracting EXE, you would write your own C++ app that is the self-extracting EXE. It would open the .zip that's been appended onto the end of its own EXE. This gives you full control over the user interface of the self-extractor, and makes all things possible. The requirement is that your self-extractor is written in C++ and does not require any external DLLs to run. (It might even be best to write it in VC++ 6.0 to eliminate the dependencies on the VC++ runtimes you'll encounter with VC++ 2010, 2012, etc.)

I'll show an extremely simple example. The example requires the use of Chilkat v9.4.0 because the OpenZip method has been modified to always scan forward in a file to find the start of a .zip (assuming the .zip does not start at byte 0). This allows a .exe with an appended .zip to be passed to OpenZip.

The self-extractor application opens the .zip that is appended to its own EXE. This example is a very simple console C++ Win32 app, but one could write something more sophisticated with a user interface. The GetModuleFilename Win32 Platform SDK function allows the program to find the path of its own executable. After getting the path, it opens the .exe and unzips.

    #include <windows.h>
    #include <stdio.h>

#include <CkZip.h>

int selfExtract(void)
    {
    char myExePath[1024];
    GetModuleFileName(0,myExePath,1024);

    CkZip zip;

    bool success = zip.UnlockComponent("myUnlockCode");
    if (!success)
    {
    printf("%s\n",zip.lastErrorText());
    return 1;
    }

    success = zip.OpenZip(myExePath);
    if (!success)
    {
    printf("%s\n",zip.lastErrorText());
    return 1;
    }

    int numUnzipped = zip.Unzip(".");
    if (numUnzipped < 0)
    {
    printf("%s\n",zip.lastErrorText());
    return 1;
    }

    zip.CloseZip();

    return 0;
    }

int main(int argc, char* argv[])
{
    return selfExtract();
}

The procedure is to first build this program (i.e. create the EXE), then append the .zip to the end of the .exe. Here's a simple C++ program using Chilkat to append a .zip to a .exe:

#include <windows.h>

#include <ckbytedata.h>
#include <ckfileaccess.h>

// This program appends a .zip to the end of a .exe
// The .exe must be a multiple of 4 bytes in length.  If it is not, null bytes are
// appended to make the size a multiple of 4.
int main(int argc, char* argv[])
    {
    const char *exeFile = "C:/Ck2000/intelApps/MyAppInstaller/Release/MyAppInstaller.exe";

CkFileAccess fac;
    int exeSize = fac.FileSize(exeFile);
    int nZeros = 4 - (exeSize % 4);
    if (nZeros < 4)
        {
        CkByteData zeros;
        zeros.appendCharN(0,nZeros);
        // Append the zeros to the .exe
        zeros.appendFile(exeFile);
        }

// Append the .zip to the .exe
    CkByteData zipData;
    zipData.loadFile("c:/aaworkarea/hamlet.zip");
    zipData.appendFile(exeFile);

return 0;
    }

After the .zip has been appended, the .exe can be run and it will unzip the attached .zip. Maybe this is too much if you're not a C++ programmer, but it's a good way to create a self-extracting EXE with unrestricted potential.


Answer

This was not really a question, but just a post with information. :)