在软件开发过程中,经常需要将多个文件打包成一个单一的.cab文件,并且对这些文件进行代码签名。虽然.cab格式看起来已经有些过时,但它仍然是微软在需要将文件打包到安装程序中时的首选格式。本文将介绍如何使用MakeCab工具以及C++编程语言来实现这一过程。
.cab文件格式是由微软创建的,用于将安装程序的一部分文件打包到磁盘中。尽管这种格式已经有些过时,但直到今天,创建.cab文件时仍然会生成名为"Disk1"、"Disk2"等的文件夹。本文将介绍一种简化的方法,通过一个简单的函数调用来实现文件打包。
在Secured Globe, Inc.中,使用了一些基础构建块。首先是一个执行命令的函数,该函数可以模拟在CMD中输入并执行命令,收集结果并将其显示回来。如果发生错误,它会生成一个友好的错误描述。
bool DoRun(WCHAR *command) {
DWORD retSize;
LPTSTR pTemp = NULL;
TCHAR Command[BUFSIZE] = L"";
DeleteFile(RESULTS_FILE);
_tcscpy_s(Command, L"/C ");
_tcscat_s(Command, command);
_tcscat_s(Command, L">");
_tcscat_s(Command, RESULTS_FILE);
wprintf(L"Calling:\n%s\n", Command);
bool result = ShellExecute(GetActiveWindow(), L"OPEN", L"cmd", Command, NULL, 0L);
Sleep(1000);
if (result) {
std::FILE *fp = _wfopen(RESULTS_FILE, L"rb");
if (fp) {
std::string contents;
std::fseek(fp, 0, SEEK_END);
contents.resize(std::ftell(fp));
std::rewind(fp);
std::fread(&contents[0], 1, contents.size(), fp);
std::fclose(fp);
CString temp1 = (CString)(CStringA)(contents.c_str());
wprintf(L"Result:\n%s\n", temp1.GetBuffer());
}
} else {
retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&pTemp, 0, NULL);
return (L"Error: %s\n", pTemp);
}
}
在CreateCabFromFiles函数中,定义了一些常量,然后使用这些常量来创建.cab文件。这个函数接受一个目标.cab文件名和文件数量,然后创建一个包含所有文件名的列表文件,并调用MakeCab工具来打包这些文件。
#define RESULTS_FILE L"result.txt"
#define FILELIST_FILE L"files.txt"
#define MAKECAB_COMMAND L"makecab /d CabinetName1=%s /f %s"
#define CAB_DEF_FOLDER L"disk1"
bool CreateCabFromFiles(LPWSTR TargetCab, int argc, ...) {
va_list ptr;
va_start(ptr, argc);
FILE *fp = _wfopen(FILELIST_FILE, L"w");
if (fp) {
for (int i = 0; i < argc; i++) {
LPWSTR *filetowrite = va_arg(ptr, LPWSTR *);
fwprintf(fp, L"%s\n", filetowrite);
}
fclose(fp);
CString command;
command.Format(MAKECAB_COMMAND, TargetCab, FILELIST_FILE);
if (DoRun(command.GetBuffer())) {
if (CopyFile(CAB_DEF_FOLDER + (CString)L"\\" + TargetCab, TargetCab, FALSE)) {
wprintf(L"Created cab file: %s\n", TargetCab);
DeleteFile(CAB_DEF_FOLDER + (CString)L"\\" + TargetCab);
RemoveDirectory(CAB_DEF_FOLDER);
DeleteFile(FILELIST_FILE);
return true;
}
}
}
return true;
}
为了节省打开"disks"并查找创建的.cab文件的需要,以及删除为了正确"喂养"MakeCab而创建的文件,这个函数的清理工作包括以下步骤:
CreateCab(L"drivers.cab", 3, L"drv.sys", L"drv.inf", L"drv.cat");