可执行文件的捆绑和分离

多个文件的捆绑,为了实现上述功能,可以将主程序中加入分解功能,或者使用一个自解压的控制程序来进行文件的分解。下面以一个自解压控制程序来说明问题:
捆绑之后的程序结构如下所示:
 
自解压控制程序
文件原始信息1
文件原始内容1
文件原始信息2
文件原始内容2
解压控制信息
 
每一个捆绑的文件都使用一个结构储存信息,添加到自解压控制程序后面,分解时再由控制程序读出信息并解出文件。
该结构信息如下:
 
typedef struct _SELF_EXTRACT_INFO //每个被捆绑的文件信息
{
 TCHAR cFileName[50];   //文件名
 DWORD nFileSize;       //文件长度
 BOOL bExecute;        //是否解出后运行
}SELF_EXTRACT_INFO, *PSELF_EXTRACT_INFO;
 
可视情况自行增加存储信息,在控制程序中进行对应操作。
 
在所有捆绑的文件以及文件信息都加到自解压文件后,在最后写入一个控制信息结构,记录文件数量等的控制信息。控制信息结构如下:
 
typedef struct _CONTROL_INFO     //控制体信息结构
{
 DWORD nObjectSize;   //母体程序文件长度
 DWORD nBindNum;      //被捆绑文件个数
 DWORD nFileSize;     //捆绑后文件长、用于校验
 DWORD nBindType;     //捆绑方式、压缩、不压缩
 DWORD nExecuteType; //指定文件执行方式,等待、立即返回
}CONTROL_INFO, *PCONTROL_INFO;
 
相应的,增加控制功能可以在此结构中增加对应的成员,并在自解压程序中加入对应控制功能。
下面首先完成自解压控制程序的母体。生成一个完整的程序,之后完成一个捆绑程序,用于生成一个新的程序,内容如文章开头表格所示。
 
自解压控制程序主要代码:
BOOL TForm1::ExtractFiles()
{
  CONTROL_INFO KeyInfo;
  SELF_EXTRACT_INFO BindFile;
  TCHAR szModule[MAX_PATH];
  DWORD Count;
  FILE 
*pfread, *
pfwrite;
  
//
  if(GetModuleFileName(NULL,szModule,MAX_PATH)==0
)
    
return
 FALSE;
  
//
  if((pfread = fopen(szModule,"rb"))==
NULL)
    
return
 FALSE;
  
//by jingzhongrong

  
//获取自身文件长度

  struct _stat st;
  _stat(szModule,
&
st);
  DWORD FileSize 
=
 st.st_size;
  
//

  
//控制体信息结构位置
  DWORD Offset = FileSize-sizeof(CONTROL_INFO);
  
if(Offset<0)  return
 FALSE;
  
//

  
//读取信息
  fseek(pfread,Offset,SEEK_SET);
  fread(
&KeyInfo,1,sizeof
(CONTROL_INFO),pfread);
  
//
校验文件长度
  
//Extract file

  DWORD pos = KeyInfo.nObjectSize;
  
for(DWORD i=1; i<KeyInfo.nBindNum; i++
)
  
{
    
//read

    fseek(pfread,pos,SEEK_SET);
    fread(
&BindFile,1,sizeof
(SELF_EXTRACT_INFO),pfread);
    
//

    
//分解出文件
    if((pfwrite = fopen(BindFile.cFileName,"wb"))==NULL)
    
{
      fclose(pfread);
      
return
 FALSE;
    }


    
int c;
    pos 
= pos + sizeof
(SELF_EXTRACT_INFO);
    fseek(pfread,pos,SEEK_SET);
    
//by jingzhongrong
    Count = 0
;
    
while((c=fgetc(pfread))!=
EOF)
    
{
      fputc(c,pfwrite);
      Count
++
;
      
if(Count ==
 BindFile.nFileSize)
        
break
;
    }

    pos 
= pos + BindFile.nFileSize;
    fclose(pfwrite);
    
//
    if(BindFile.bExecute ==
 TRUE)
    
{
      
this->ExecuteFiles->
Add(AnsiString(BindFile.cFileName));
    }

  }

  
//
  fclose(pfread);
  
return
 TRUE;
}

 程序由BCB完成,带有一些BCB特有的VCL类型,如TStringList、AnsiString。

下面是捆绑的程序,使用该程序进行捆绑生成一个新的程序,该程序便是可以进行自动分解的程序了。还可以加入分解后运行某一个文件的功能。

下面是主要实现代码:

BOOL TForm1::DoBind(BOOL self, AnsiString filename) //自解压
{
  
int ExecuteFileNum = strExecuteFile->
Count;
  
int NonExecuteFileNum = strNonExecuteFile->
Count;
  AnsiString strSelfExtFile 
=
 filename;
  
int FileNum = ExecuteFileNum +
 NonExecuteFileNum;
  
//CONTROL_INFO SELF_EXTRACT_INFO

  SELF_EXTRACT_INFO *pBind = new SELF_EXTRACT_INFO[FileNum+1];
  CONTROL_INFO KeyInfo;
  DWORD nFileSize;
  
struct
 _stat st;
  
//
  FILE *fpread, *
fpwrite;
  
//
  if((fpwrite = fopen(strSelfExtFile.c_str(),"wb"))==
NULL)
  
{
    delete []pBind;
    
return
 FALSE;
  }

  
if(self == TRUE) //自解压
  {
    FileNum
++
;
    AnsiString matrix 
= ExtractFilePath(Application->
ExeName);
    matrix 
= matrix + "MatrixFile.exe"
;
    _stat(matrix.c_str(),
&
st);
    pBind[
0].nFileSize =
 st.st_size;
    
//此处加入母体程序

    if((fpread = fopen(matrix.c_str(),"rb"))==NULL)
    
{
      delete []pBind;
      fclose(fpwrite);
      
return
 FALSE;
    }

    
int c;
    
while((c = fgetc(fpread))!=
EOF)
    
{
      fputc(c,fpwrite);
    }

    fclose(fpread);
  }

  
else
  
{
    _stat(strExecuteFile
->Strings[0].c_str(),&
st);
    pBind[
0].nFileSize =
 st.st_size;
  }

  
//by jingzhongrong
  int
 i;
  
for(i=0; i<ExecuteFileNum; i++
)
  
{
    strcpy(pBind[i
+1].cFileName,strExecuteFile->
Strings[i].c_str());
    _stat(strExecuteFile
->Strings[i].c_str(),&
st);
    pBind[i
+1].nFileSize =
 st.st_size;
    nFileSize 
+=
 st.st_size;
    pBind[i
+1].bExecute =
 TRUE;
  }

  
for(i=0; i<NonExecuteFileNum; i++)
  
{
    strcpy(pBind[i
+1+ExecuteFileNum].cFileName,strNonExecuteFile->
Strings[i].c_str());
    _stat(strNonExecuteFile
->Strings[i].c_str(),&
st);
    pBind[i
+1+ExecuteFileNum].nFileSize =
 st.st_size;
    nFileSize 
+=
 st.st_size;
    pBind[i
+1+ExecuteFileNum].bExecute =
 TRUE;
  }

  KeyInfo.nBindNum 
= FileNum;
  KeyInfo.nObjectSize 
= pBind[0
].nFileSize;
  
if(self==
TRUE)
  
{
    nFileSize 
+= pBind[0
].nFileSize;
  }

  
else
  
{
  }

  KeyInfo.nFileSize 
= nFileSize + sizeof(CONTROL_INFO) + (FileNum-1)*sizeof(SELF_EXTRACT_INFO);
  KeyInfo.nBindType 
= 0
;
  KeyInfo.nExecuteType 
= 1
;
  
//
  FileNum = ExecuteFileNum + NonExecuteFileNum + 1
;
  
for(i=1;i<FileNum;i++
)
  
{
    
if((fpread = fopen(pBind[i].cFileName,"rb"))==
NULL)
    
{
      delete []pBind;
      
return
 FALSE;
    }

    strcpy(pBind[i].cFileName,ExtractFileName(AnsiString(pBind[i].cFileName)).c_str());
    fwrite(
&pBind[i],1,sizeof(SELF_EXTRACT_INFO),fpwrite);
    
int
 c;
    
while((c = fgetc(fpread)) !=
 EOF)
    
{
      fputc(c,fpwrite);
    }

    fclose(fpread);
  }

  fwrite(
&KeyInfo,1,sizeof(CONTROL_INFO),fpwrite);
  fclose(fpwrite);
  delete []pBind;
  
//
  return
 TRUE;
}

上面代码是我直接从程序中复制过来的,没有去修改,程序功能比这篇文章中所写要复杂一点,所以下面说一下代码的主要流程。

先读取自解压控制程序然后写入一个指定的文件中,之后读取要捆绑的文件的文件信息,填充SELF_EXTRACT_INFO结构,之后写入文件,再把捆绑的文件内容接着写入文件,重复知道所有要捆绑的文家全部写入完成,在最后,程序填充控制信息CONTROL_INFO结构,写在文件最后,这是为了自解压控制程序可以读出有关的控制信息。

读出写入文件的主要代码如下:

fwrite(&pBind[i],1,sizeof (SELF_EXTRACT_INFO),fpwrite);
    
int
 c;
    
while((c = fgetc(fpread)) !=
 EOF)
    {
      fputc(c,fpwrite);
    }
    fclose(fpread);

//write by jingzhongrong

last edit by jingzhongrong at 17:51 2007/2/24

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值