如何创建 CAB 文件和如何从文件、内存和资源中解压缩 CAB 文件

制作 MSI 安装程序少不了 CAB 文件,CAB 文件可以对需要安装程序进行压缩,以达到快速分发新程序的目的,通过参考高人的代码和 MSDN 整理了一套 Cabinet 文件的操作实现类,使用这些类可以:
  1、将多个文件制作为一个 CAB 文件
  2、将一个目录直接打包为 CAB 文件
  3、将磁盘上的 CAB 文件中解包出文件
  4、从内存中的 CAB 数据流中解包出文件 
  5、从程序的 CAB 资源中解包出文件
  6、通过策略模式可以对 CAB 文件中的数据进行加解密

通过该套封装类,已经实现了制作单文件的安装程序 Setup.exe ,该程序使用 /Create 参数启动时根据指定的目录打包为一个 CAB 文件并将该文件加入到特定的资源中生成一个用于安装的 Setup.exe(同一个程序,如果没有指定参数那么根据有无 CAB 资源来决定是进行“安装”还是“卸载”),在程序中添加资源很简单,参考下面的例子代码:

    //--------------------------------------------------------------------------
    
//    概述:
    
//        根据指定的程序和 CAB 文件创建安装程序
    
//    参数:
    
//        szInstall    - [ IN ]    生产的目标安装程序路径
    
//        szPackage    - [ IN ]    安装程序使用的 CAB 文件路径
    
//        szProgram    - [ IN ]    原始的安装程序路径
    BOOL CreateSetup(LPTSTR szInstall, LPTSTR szPackage, LPTSTR szProgram);
  下面是该函数的实现:
BOOL CPagePackage::CreateSetup(LPTSTR szInstall, LPTSTR szPackage, LPTSTR szProgram)
{
    
//    复制安装程序到目标路径处
    BOOL bCopy = CopyFile(szProgram, szInstall, FALSE);
    CHK_EXP_RET( FALSE 
== bCopy , ShowSystemError() );

    
//    打开 CAB 文件
    HANDLE hFile = CreateFile(szPackage, GENERIC_READ, 00, OPEN_ALWAYS, 00);
    CHK_EXP_RET( hFile 
== INVALID_HANDLE_VALUE , ShowSystemError() );
    BasicHelper::CHandleManager xAutoFileManager( hFile );

    
//    创建 CAB 文件到共享内存映射的句柄
    HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 00, NULL );
    CHK_EXP_RET( hMapping 
== NULL , ShowSystemError() );
    BasicHelper::CHandleManager xMapping( hMapping );

    CONST LPCTSTR szResName 
= MAKEINTRESOURCE( 1 );
    CONST WORD wLanguage 
= MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);

    
//    获取 CAB 文件大小
    DWORD dwSize = GetFileSize( hFile, ERROR_SUCCESS + NO_ERROR );
    CHK_EXP_RET( dwSize 
== INVALID_FILE_SIZE , ShowSystemError() );

    
//    将 CAB 文件映射到共享内存中
    LPVOID lpBuffer = MapViewOfFile(hMapping, FILE_MAP_READ, 000);
    CHK_EXP_RET( lpBuffer 
== NULL , ShowSystemError() );

    
//    准备将 CAB 文件内容添加到安装程序中
    HANDLE hUpdate = BeginUpdateResource(szInstall, FALSE);
    CHK_EXP_RET( hUpdate 
== NULL , ShowSystemError() );

    
//    将 CAB 文件内容更新到目标安装程序的资源中
    UpdateResource(hUpdate, RT_RCDATA, szResName, wLanguage, lpBuffer, dwSize);
    EndUpdateResource(hUpdate, FALSE);
    UnmapViewOfFile(lpBuffer);
    
return NO_ERROR + TRUE;
}
  呵呵,最后附上 CAB 文件完整的实现文件:
CabinetImpl.h
posted @ 2009-03-17 09:06  王志科  阅读(5249)  评论(3编辑  收藏  举报