Найти - Пользователи
Полная версия: Зашить в исполняемую программу дополнительный файл (файлы)
Начало » Python для новичков » Зашить в исполняемую программу дополнительный файл (файлы)
1
key
Задача: создать один exe, содержащий в себе интерпретатор питоновский + некоторый набор файлов.
Тобишь, чтобы юзер запускал программу не имея интерпретатора питоновского и в гуи была одна кнопка “сделать хорошо”, по нажатию на которую будет идти распаковка файлов (зашитых внутрь исполняемой программы).

Вопрос по большей части интересует каким образом можно зашить файлы, с которыми придется работать, внутрь исполняемой программы?
JOHN_16
модули cx_freeze, PyInstaller
key
один вопрос, как потом обращаться к файлу зашитому в этот экзешник?
Shaman
cx_freeze/PyInstaller сами всё распакуют и запустят
doza_and
Shaman
cx_freeze/PyInstaller сами всё распакуют и запустят
Наверное не совсем так?
cx_freeze Делают запускаемый exe.
А автор топика похоже хочет инсталятор с кнопкой “сделать хорошо”. Один раз распаковка и потом чтобы все работало хорошо. Тогда http://nsis.sourceforge.net/Main_Page или аналогичные вещи.
Shaman
doza_and
Может и так. Чего именно хочет автор не совсем понятно.
key
Наверное не правильно выразился, задача стоит в написании архиватора/разархиватора.
Пример есть такие файлы: 1.jpg, 2.txt, 3.png, собираем все в один файл files.archive, теперь собираем питоновское приложение как один program.exe и запаковываем туда files.archive.
Что мы имеем? Один program.exe файл, в котором питоновский интерпретатор + архивный файл (очень важно один файл, а не несколько), далее нажимаем кнопку “распаковать” и файлы 1.jpg, 2.txt, 3.png распаковываются.

Это своего рода патчер, который ищет директорию, где установлена игра и заменяем там файлы и закрывает запущенное приложение игры, чтобы заменить полностью. Текущие проблемы:
1. если давать в .rar или zip и т.д., то не у всех он есть (да и такие бывают);
2. не могут найти папку с игрой;
3. не понимают, что сперва надо закрыть игру, а потом патчить.
и т.д.

Очень важно дать один .exe, который “сделает как надо все сам”, игроку не надо знать, где игра, что заменять, закрывать и т.д.

Какие есть предложения?
doza_and
Предлагаю не делать кнопку “Сделать хорошо”. Ума не приложу как это просто сделать (может html приложить).
Если посмотрите формат исполняемого модуля, то данные можно просто записать в конец исполняемого файла. А при распаковке будете делать то что вам нужно. Обычно эту задачу решает инсталятор (и генератор дистрибутивов). Так что есть резон смотреть на данную мною вам ссылку.

Если нужен уникальный велосипед, то вот коленочная версия:

#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
const int KB = 1024;
const int MB = KB*KB;
int main(int argc,char** argv)
{
    string file_name;
    unsigned exe_size=2617721096;
    unsigned i;
    ifstream si(argv[0],ios::binary);
    si.seekg(exe_size);
    unsigned len;
    char* buf;
    buf=new char[MB];
    char ch;
    while(1)
    {
        si.read((char*)&len,4);
        if(!si) break;
        file_name.resize(len);
        si.read((char*)file_name.data(),len);
        si.read((char*)&len,4);
        {
            ofstream so(file_name.c_str(),ios::binary);
            for(;;)
            {
                int buf_len=len>MB ? MB:len;
                si.read(buf,buf_len);
                so.write(buf,buf_len);
                len-=buf_len;
                if(len==0) break;
            }
      }
    }
    delete [] buf;
/// some extra code .....
    return 0;
}

И наконец питон:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import argparse
import struct
import subprocess as sp
def transform_magic(input_file,output_file, append_file_list, magic_const=2617721096):
    data=open(input_file,"rb").read()
    f_size=len(data)
    oldsubstring = struct.pack("I",magic_const)
    newsubstring = struct.pack("I",f_size)
    data1 = data.replace(oldsubstring,newsubstring)
    with open(output_file,"wb") as f:
        f.write(data1)
        blk_size=1024*1024
        for fnm in append_file_list:
            tmp = struct.pack("I",len(fnm))
            f.write(tmp)
            f.write(fnm)
            siz=os.stat(fnm).st_size
            tmp = struct.pack("I",siz)
            f.write(tmp)
            with open(fnm,"rb") as fi:
                while 1:
                    data=fi.read(blk_size)
                    if len(data)==0:
                        break
                    f.write(data)
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        prog="packager :)")
    parser.add_argument("-o", "--output", default='.', help=u"name of output file")
    parser.add_argument("-i","--input", help=u"name of input file")
    parser.add_argument("-a", "--append", nargs="*", help=u"files to append")
    args = parser.parse_args()
    transform_magic(args.input,args.output, args.append)

Порядок работы такой - компилируем исполняемый модуль. Питон скриптом дописываем внешние файлы.
cl /MT inst.cpp
python substmagic.py -i inst.exe -a 7z.exe python.msi arch_of_jpeg.7z -o inst_1.exe
При компиляции не забываем делать статический рантайм (проверьте при помощи dumpbin зависимости). Для новомодных cl указываем совместимость с WindowsXp,windows95 ну и так далее.
Кстати. Если в конец дописывать архив типа zip (у которого есть оглавление в конце), то есть шанс что менеджеры архивов позволят просматривать этот архив.

Содержащий интерпретатор:
int check_python()
{
   const int MAX_NAME=20;
   char buf[MAX_NAME]={0};
    system("python --version 2>python_version.txt");
    {
        ifstream si("python_version.txt");
        si.read(buf,MAX_NAME);
    }
//    remove("python_version.txt");
    if(strstr(buf,"Python")!=nullptr)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

Инсталяция питона:
msiexec.exe /i python_installer\python.msi TARGETDIR=c:\temp\install\fooX

Ну и так далее … велосипед как известно бывает бесконечен.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB