- #include <atl/atlbase.h>
- //.inf文件模板
- const
- AnsiString Templete =
- "; /%Title/%/r/n/
- ; File Name /%DLLName/% File Version= /%DllVersion/%/r/n/
- ; ProgId= /%ProgId/% ClassId= /%DLLClsid/%/r/n/r/n/
- [version]/r/n/
- signature=/"$CHICAGO$/"/r/n/
- AdvancedINF=2.0/r/n/r/n/
- [Add.Code]/r/n/
- /%DLLName/%=/%DLLName/%/r/n/r/n/
- [/%DLLName/%]/r/n/
- file-win32-x86=thiscab/r/n/
- RegisterServer=yes/r/n/
- clsid=/%DLLClsid/%/r/n/
- DestDir=/r/n/
- FileVersion=/%DLLVersion/%/r/n/r/n/
- [Setup Hooks]/r/n/
- AddToRegHook=AddToRegHook/r/n/r/n/
- [AddToRegHook]/r/n/
- InfSection=DefaultInstall/r/n/r/n/
- [DefaultInstall]/r/n/
- AddReg=AddToRegistry/r/n/r/n/
- [AddToRegistry]/r/n/
- HKLM,/"SOFTWARE//Classes//CLSID///%DLLClsid/%//Implemented Categories//{7DD95801-9882-11CF-9FA9-00AA006C42C4}/"/r/n/
- HKLM,/"SOFTWARE//Classes//CLSID///%DLLClsid/%//Implemented Categories//{7DD95802-9882-11CF-9FA9-00AA006C42C4}/"";
- //MackCab 用的中间文件模板,文件附加在后面,不能带路径(估计可以支持8.3短路径)
- const AnsiString MakeCabDirective =
- ".OPTION EXPLICIT ; Generate errors/r/n/
- .Set CabinetNameTemplate=/%CABFile/%/r/n/
- .set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory/r/n/
- .Set CompressionType=MSZIP;** All files are compressed in cabinet files/r/n/
- .Set UniqueFiles=/"OFF/"/r/n/
- .Set Cabinet=on/r/n/
- .Set DiskDirectory1=/%CABFilePath/%/r/n";
- //---------------------------------------------------------------------------
- //取得CoClass的ClassID
- AnsiString __fastcall GetCLSID(AnsiString FileName)
- {
- HRESULT hr;
- AnsiString Result="";
- CComPtr<ITypeLib> spTypeLib;
- USES_CONVERSION;
- hr = LoadTypeLib(A2OLE(FileName.c_str()), &spTypeLib);
- if (FAILED(hr)) return Result;
- UINT n = spTypeLib->GetTypeInfoCount();
- CComBSTR bstrName0;
- hr = spTypeLib->GetDocumentation( -1,
- &bstrName0,
- 0,
- 0,
- 0
- );
- if(FAILED(hr))return Result;
- for (UINT i=0; i<n; ++i)
- {
- CComPtr<ITypeInfo> spTypeInfo;
- hr = spTypeLib->GetTypeInfo(i, &spTypeInfo);
- if (FAILED(hr)) return Result;
- CComBSTR bstrName;
- hr = spTypeInfo->GetDocumentation( -1,
- &bstrName,
- 0,
- 0,
- 0
- );
- if (FAILED(hr)) return Result ;
- TYPEATTR* pta = 0;
- hr = spTypeInfo->GetTypeAttr(&pta);
- if (FAILED(hr)) return Result;
- CComBSTR bstrGuid(pta->guid);
- if (TKIND_COCLASS == pta->typekind )
- {
- Result = AnsiString(bstrGuid);
- spTypeInfo->ReleaseTypeAttr(pta);
- pta = 0;
- return Result;
- }
- spTypeInfo->ReleaseTypeAttr(pta);
- pta = 0;
- }
- return Result;
- }
- //取得ProgID
- AnsiString __fastcall GetProgID(AnsiString FileName)
- {
- HRESULT hr;
- AnsiString Result="";
- CComPtr<ITypeLib> spTypeLib;
- USES_CONVERSION;
- hr = LoadTypeLib(A2OLE(FileName.c_str()), &spTypeLib);
- if (FAILED(hr)) return Result;
- UINT n = spTypeLib->GetTypeInfoCount();
- CComBSTR bstrName0;
- hr = spTypeLib->GetDocumentation( -1,
- &bstrName0,
- 0,
- 0,
- 0
- );
- if(FAILED(hr))return Result;
- for (UINT i=0; i<n; ++i)
- {
- CComPtr<ITypeInfo> spTypeInfo;
- hr = spTypeLib->GetTypeInfo(i, &spTypeInfo);
- if (FAILED(hr)) return Result;
- CComBSTR bstrName;
- hr = spTypeInfo->GetDocumentation( -1,
- &bstrName,
- 0,
- 0,
- 0
- );
- if (FAILED(hr)) return Result ;
- TYPEATTR* pta = 0;
- hr = spTypeInfo->GetTypeAttr(&pta);
- if (FAILED(hr)) return Result;
- CComBSTR bstrGuid(pta->guid);
- int iKind = pta->typekind ;
- if (iKind == TKIND_COCLASS)
- {
- Result = AnsiString(bstrName0)+"."+AnsiString(bstrName);
- spTypeInfo->ReleaseTypeAttr(pta);
- pta = 0;
- return Result;
- }
- spTypeInfo->ReleaseTypeAttr(pta);
- pta = 0;
- }
- return Result;
- }
- //取得文件版本
- AnsiString __fastcall GetVersion(char *szFile)
- {
- DWORD dwHandle;
- char m_szVersion[256];
- DWORD dwVerSize = GetFileVersionInfoSize((char *)szFile, &dwHandle);
- char *pbBuffer = new BYTE[dwVerSize];
- VS_FIXEDFILEINFO *lpVSInfo = NULL;
- UINT uiVerSize = 0;
- if (!pbBuffer)
- {
- return E_OUTOFMEMORY;
- }
- if (GetFileVersionInfo((char *)szFile, 0, dwVerSize, pbBuffer))
- {
- if (VerQueryValue(pbBuffer, "//", (void **)&lpVSInfo, &uiVerSize))
- {
- wsprintf( m_szVersion,
- "%d,%d,%d,%d",
- (lpVSInfo->dwFileVersionMS >> 16) & 0xFFFF,
- lpVSInfo->dwFileVersionMS & 0xFFFF,
- (lpVSInfo->dwFileVersionLS >> 16) & 0xFFFF,
- lpVSInfo->dwFileVersionLS & 0xFFFF
- );
- }
- }
- delete [] pbBuffer;
- return AnsiString(m_szVersion);
- }
- //制作用于发布的CAB包
- void __fastcall MakeCab(AnsiString FileName)
- {
- AnsiString FileVer = GetVersion(FileName.c_str());
- AnsiString ClsID = GetCLSID(FileName);
- AnsiString DLLName = ExtractFileName(FileName);
- AnsiString ProgID = GetProgID(FileName);
- AnsiString Title = "Ocx Inf file Maker";
- AnsiString InfFileName = ChangeFileExt(FileName,".inf");
- AnsiString CabFileName = ChangeFileExt(FileName,".cab");
- AnsiString DDFFileName = ChangeFileExt(FileName,".ddf");
- AnsiString CABDirective = StringReplace( MakeCabDirective,
- "/%CABFile/%",
- ExtractFileName(CabFileName),
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- CABDirective = StringReplace( CABDirective,
- "/%CABFilePath/%",
- ExtractFilePath(CabFileName),
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- )
- + "/"" + FileName + "/""
- + "/r/n/"" + InfFileName + "/"";
- AnsiString InfFile;
- InfFile = StringReplace( Templete,
- "/%Title/%",
- Title,
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- InfFile = StringReplace( InfFile,
- "/%DLLName/%",
- DLLName,
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- InfFile = StringReplace( InfFile,
- "/%DllVersion/%",
- FileVer,
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- InfFile = StringReplace( InfFile,
- "/%ProgId/%",
- ProgID,
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- InfFile = StringReplace( InfFile,
- "/%DLLClsid/%",
- ClsID,
- TReplaceFlags()<<rfReplaceAll<<rfIgnoreCase
- );
- TFileStream *f = new TFileStream(InfFileName,fmCreate);
- try
- {
- char *p = InfFile.c_str();
- int iLen = InfFile.Length();
- while (iLen){
- int iWrote = f->Write(p,iLen);
- p += iWrote;
- iLen -= iWrote;
- }
- }
- __finally
- {
- f->Free();
- }
- //更新.INF的文件时间为.OCX的时间
- HFILE hFile;
- FILETIME mCreationTime;
- FILETIME mLastAccessTime;
- FILETIME mLastWriteTime;
- hFile=_lopen(FileName.c_str(),OF_READWRITE);
- GetFileTime( (HANDLE *)hFile,
- &mCreationTime,
- &mLastAccessTime,
- &mLastWriteTime
- );
- hFile=_lopen(InfFile.c_str(),OF_READWRITE);
- SetFileTime( (HANDLE *)hFile,
- &mCreationTime,
- &mLastAccessTime,
- &mLastWriteTime
- );
- _lclose(hFile);
- f = new TFileStream(DDFFileName,fmCreate);
- try
- {
- char *p = CABDirective.c_str();
- int iLen = CABDirective.Length();
- while (iLen){
- int iWrote = f->Write(p,iLen);
- p += iWrote;
- iLen -= iWrote;
- }
- }
- __finally
- {
- f->Free();
- }
- //执行MakeCAB创建CAB包
- STARTUPINFO StartInfo; // name structure
- PROCESS_INFORMATION ProcInfo; // name structure
- memset(&ProcInfo, 0, sizeof(ProcInfo)); // Set up memory block
- memset(&StartInfo, 0 , sizeof(StartInfo)); // Set up memory block
- StartInfo.cb = sizeof(StartInfo); // Set structure size
- if (!CreateProcess( NULL,
- AnsiString("makecab /f /""+DDFFileName+"/"").c_str(),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExtractFilePath(FileName).c_str(),
- &StartInfo,
- &ProcInfo))
- return;
- WaitForSingleObject(ProcInfo.hProcess,INFINITE);
- CloseHandle(ProcInfo.hThread);
- CloseHandle(ProcInfo.hProcess);
- //更新CAB的文件时间为.OCX的时间
- hFile=_lopen(FileName.c_str(),OF_READWRITE);
- GetFileTime( (HANDLE *)hFile,
- &mCreationTime,
- &mLastAccessTime,
- &mLastWriteTime
- );
- hFile=_lopen(CabFileName.c_str(),OF_READWRITE);
- SetFileTime( (HANDLE *)hFile,
- &mCreationTime,
- &mLastAccessTime,
- &mLastWriteTime
- );
- _lclose(hFile);
- }
示例:
- void __fastcall TfrmMakeCAB::btnMakeClick(TObject *Sender)
- {
- if (dlgOpenOCX->Execute()) {
- AnsiString FileName = dlgOpenOCX->FileName;
- if (SameText(ExtractFileExt(FileName),".OCX")) {
- MakeCab(FileName);
- }
- }
- }