【问题标题】:ANSI C: how can I include and then extract .exe file in my application (pack .exe into .exe)?ANSI C:如何在我的应用程序中包含然后提取 .exe 文件(将 .exe 打包成 .exe)?
【发布时间】:2012-10-12 00:18:39
【问题描述】:

我正在编写一个创建 Windows 服务的程序。所以我需要两个 .exe 文件——一个用于程序,创建服务,另一个用于服务本身。但我想将这两个文件合二为一。我有以下想法 - 打开 .exe 文件,我想在文本编辑器中打包(服务应用程序),然后将其内容复制到某个字符串。然后我需要在所需目录中创建一个空的 .exe 文件并将字符串写入该文件。但我想这不是一个好主意。解决我的问题的最佳方法是什么?

提前致谢。

【问题讨论】:

  • 使用 Windows 服务安装程序?
  • 复制到文本编辑器是最糟糕的想法。它不会保留非 ASCII 字符。无论如何,可执行文件不是原始机器代码,连接两个文件是行不通的。
  • 嗯,首先,ANSI C 不知道 .exe 文件是什么。 Visual Studio 编译器 - 可能还有其他编译器 - 允许您将资源打包到生成的可执行文件中,因此您只需放置一个包含您需要的 exe 的存档,然后从您运行的 exe 中解压缩它。虽然我还是不太明白你到底想做什么。
  • 你可以合并它们。程序可以将自己注册(或卸载)为服务。
  • 我在下面发布了一个 Seki 建议的示例——它是用 C++ 编写的

标签: c windows


【解决方案1】:

为了好玩,我编写了一个使用您的方法的“启动器”程序。它可以工作,我用 zoomin.exe 作为有效负载对其进行了测试。

创建启动器可执行文件后,在Notepad++ 中打开它和有效负载文件(在我的例子中是zoomin.exe),然后复制(使用编辑|选择性粘贴|复制二进制内容和粘贴二进制内容菜单选项)。

您可以通过在 Notepad++ 中搜索“File Goes Here”和“End”,在启动器文件中找到有效负载所在的位置。

请注意,我确实以任何方式推荐这个,它很繁琐,容易出错,并且很容易被不同的编译器设置破坏。如前所述,我过去解决此问题的方法是将有效负载添加为资源,这更易于维护。

#include <stdio.h>

#define SIZE_OF_ZOOMIN_EXE 11264
char buffer[SIZE_OF_ZOOMIN_EXE] = "File Goes Here";
char end_of_buffer[] = "End";

int main()
{
    FILE *fp = fopen("myzoomin.exe", "wb");
    fwrite(buffer, sizeof(buffer), 1, fp);
    fclose(fp);
    return 0;
}

这是我用 C++ 编写的自安装服务的 main() 函数。此外,该程序允许以交互方式运行服务。

int main( int argc, char *argv[] ) 
{ 
    SERVICE_TABLE_ENTRY   DispatchTable[] = 
    { 
        { SERVICE_NAME,      Eng3ServiceStart      }, 
        { NULL,              NULL          } 
    }; 

    try {
        if (argc >= 2) {
            if (argc >= 3)
                if (!(logfile = fopen(argv[2], "a")))
                    logfile = stdout;

            if (0 == _stricmp(argv[1], "install")) {
                DeleteEng3Service(); // ignore return value -- don't care if error
                return CreateEng3Service();
            }
            else if (0 == _stricmp(argv[1], "uninstall"))
                return DeleteEng3Service() ;

        } 

        // not installing or uninstalling, start the service,
        // passing it all the command-line arguments.
        if (!StartServiceCtrlDispatcher( DispatchTable ) ) {
            if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
                fprintf(logfile, "Failed to connect to service. Starting in console mode.\n");
                return svcmain(argc, argv);
            }
            throw sys_ex();
        }

    } catch (exception& ex ) {
        fprintf(logfile, ex.what());
    }
} 

【讨论】:

  • 非常感谢您提供如此详细的答案。尽管我已经使用 Visual Studio 中的资源编写了我的程序(这很容易),但我认为您的答案对将来的某些人会很有用:-)
【解决方案2】:

应该可以将二进制数据作为resouce 添加到win32 可执行文件中。

使用win32 resource functions这应该是可行的。

谷歌搜索提出了这个:http://www.codeproject.com/Articles/4221/Adding-and-extracting-binary-resources

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多