我用的Delphi2007,现在已经做好一个ActiveX,是要放在网页上的。
希望别人IE在访问页面的时候,根据提示进行下载安装,并自动注册。
好像说是得做成CAB才行,然后CAB里还得有个inf文件
但我找遍Delphi2007,也没看到在哪里能做成CAB,就是能做成OCX。
用cabarc命令是能做成CAB,但是里面却没有inf文件,那是不是就不能实现自动注册啊

解决方案 »

  1.   

    好象找不到,不过可以自己写。以前用C++ Builder写过修改CAB内容的,但是没有做得很完善。
      

  2.   

    MSDN的说明
    http://msdn.microsoft.com/en-us/library/aa376858(VS.85).aspx最好的做法是下载flash的cab包,打开看看人家的inf文件怎么写的.
    按照他的写就可以了
      

  3.   

    [code=C/C++]#include <atl\atlbase.h>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}\"";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";//---------------------------------------------------------------------------
    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;
    }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);
    }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
    )
    +  ExtractFileName(FileName)
    + "\r\n" + ExtractFileName(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();
    } 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();
    }
    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); HFILE hFile;
    FILETIME mCreationTime;
    FILETIME mLastAccessTime;
    FILETIME mLastWriteTime;
    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);}
    code]
      

  4.   

    void __fastcall TfrmMakeCAB::btnMakeClick(TObject *Sender)
    {
    if (dlgOpenOCX->Execute()) {
    AnsiString FileName = dlgOpenOCX->FileName;
    if (SameText(ExtractFileExt(FileName),".OCX")) {
    MakeCab(FileName);
    }
    }
      

  5.   

    #include <atl\atlbase.h>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}\"";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";//---------------------------------------------------------------------------
    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;
    }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);
    }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
    )
    +  ExtractFileName(FileName)
    + "\r\n" + ExtractFileName(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();
    } 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();
    }
    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); HFILE hFile;
    FILETIME mCreationTime;
    FILETIME mLastAccessTime;
    FILETIME mLastWriteTime;
    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);}
      

  6.   

    关于:
    [AddToRegistry]
    HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}"
    HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}"可以参考:
    Set the safe for scripting and safe for initialization value in the registry
      

  7.   

    unit UnitMakeCAB;interface
      uses
          ActiveX
        , SysUtils
        , Classes
        , Windows;//.inf文件模板
    const
      Templete =
        '; %Title%'#13#10+
        '; File Name %DLLName%  File Version= %DllVersion%'#13#10+
        '; ProgId= %ProgId% ClassId= %DLLClsid%'#13#10#13#10+
        '[version]'#13#10+
        'signature="$CHICAGO$"'#13#10+
        'AdvancedINF=2.0'#13#10#13#10+
        '[Add.Code]'#13#10+
        '%DLLName%=%DLLName%'#13#10#13#10+
        '[%DLLName%]'#13#10+
        'file-win32-x86=thiscab'#13#10+
        'RegisterServer=yes'#13#10+
        'clsid=%DLLClsid%'#13#10+
        'DestDir='#13#10+
        'FileVersion=%DLLVersion%'#13#10#13#10+
        '[Setup Hooks]'#13#10+
        'AddToRegHook=AddToRegHook'#13#10#13#10+
        '[AddToRegHook]'#13#10+
        'InfSection=DefaultInstall'#13#10#13#10+
        '[DefaultInstall]'#13#10+
        'AddReg=AddToRegistry'#13#10#13#10+
        '[AddToRegistry]'#13#10+
        'HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}"'#13#10+
        'HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}"';//MackCab 用的中间文件模板,文件附加在后面,不能带路径(估计可以支持8.3短路径)
      MakeCabDirective =
        '.OPTION EXPLICIT     ; Generate errors'#13#10+
        '.Set CabinetNameTemplate=%CABFile%'#13#10+
        '.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single  directory'#13#10+
        '.Set CompressionType=MSZIP;** All files are compressed in cabinet files'#13#10+
        '.Set UniqueFiles="OFF"'#13#10+
        '.Set Cabinet=on'#13#10+
        '.Set DiskDirectory1=%CABFilePath%'#13#10;//取得CoClass的ClassID
    function GetCLSID(FileName: String): WideString;
    //取得ProgID
    function GetProgID(FileName: String): String;
    //制作用于发布的CAB包
    procedure MakeCAB(FileName: String);implementation//取得CoClass的ClassID
    function GetCLSID(FileName: String): WideString;
    var
      spTypeLib: ITypeLib;
      spTypeInfo: ITypeInfo;
      pta: PTypeAttr;
      hr: HRESULT;
      Count, I: UINT;begin
      Result := '{00000000-0000-0000-0000-000000000000}';
      hr := LoadTypeLib(PWideChar(WideString(FileName)),spTypeLib);
      if Failed(hr) then Exit;
      Count := spTypeLib.GetTypeInfoCount;
      I := 0;
      while I < Count do begin
        hr := spTypeLib.GetTypeInfo(I, spTypeInfo);
        if Failed(hr) then Exit;
        hr := spTypeInfo.GetTypeAttr(pta);
        if Failed(hr) then Exit;
        if TKIND_COCLASS = pta.typekind then begin
          StringFromGUID2(pta.guid, PWideChar(Result), Length(Result)* sizeof(WideChar));
          spTypeInfo.ReleaseTypeAttr(pta);
          pta := Nil;
          Exit;
        end;
        spTypeInfo.ReleaseTypeAttr(pta);
        pta := Nil;
        Inc(I);
      end;
    end;//取得ProgID
    function GetProgID(FileName: String): String;
    var
      spTypeLib: ITypeLib;
      spTypeInfo: ITypeInfo;
      pta: PTypeAttr;
      hr: HRESULT;
      Count, I: UINT;
      bstrName0, bstrName: WideString;
    begin
      Result := '';
      hr := LoadTypeLib(PWideChar(WideString(FileName)),spTypeLib);
      if Failed(hr) then Exit;
      Count := spTypeLib.GetTypeInfoCount;
      hr := spTypeLib.GetDocumentation(   -1
                                        , @bstrName0
                                        , Nil
                                        , 0
                                        , Nil
                                        );
      if Failed(hr) then Exit;
      I := 0;
      while I < Count do begin
        hr := spTypeLib.GetTypeInfo(I, spTypeInfo);
        if Failed(hr) then Exit;
        hr := spTypeInfo.GetDocumentation(  -1
                                          , @bstrName
                                          , Nil
                                          , 0
                                          , Nil
                                          );
        if Failed(hr) then Exit;
        hr := spTypeInfo.GetTypeAttr(pta);
        if Failed(hr) then Exit;
        if TKIND_COCLASS = pta.typekind then begin
          Result := WideString(bstrName0) + '.' + WideString(bstrName);
          spTypeInfo.ReleaseTypeAttr(pta);
          pta := Nil;
          Exit;
        end;
        spTypeInfo.ReleaseTypeAttr(pta);
        pta := Nil;
        Inc(I);
      end;
    end;//取得文件版本
    function GetVersion(FileName: String): String;
    var
    dwHandle: DWORD ;
    m_szVersion: array[0..255] of char;
    dwVerSize: DWORD;
    pbBuffer: PChar;
    lpVSInfo: PVSFixedFileInfo;
    uiVerSize: UINT;
    begin
      Result := '0,0,0,0';
      uiVerSize := 0;
      dwVerSize  := GetFileVersionInfoSize(PChar(FileName), &dwHandle);
      lpVSInfo := Nil;
      pbBuffer := AllocMem( dwVerSize);
    if (pbBuffer = Nil) then Exit;
    if (GetFileVersionInfo(PChar(FileName), 0, dwVerSize, pbBuffer)) then begin
    if (VerQueryValue(pbBuffer, '\', Pointer(lpVSInfo), uiVerSize)) then begin
    Result := Format( '%d,%d,%d,%d',
                [ (lpVSInfo^.dwFileVersionMS shr 16) and $FFFF,
                  lpVSInfo^.dwFileVersionMS and $FFFF,
                  (lpVSInfo^.dwFileVersionLS shr 16) and $FFFF,
                  lpVSInfo^.dwFileVersionLS and $FFFF
                            ]
              );
        end;
      end; FreeMem(pbBuffer);
    end;
      

  8.   

    //制作用于发布的CAB包
    procedure MakeCAB(FileName: String);
    var
      CABFileName, DDFFileName, InfFileName: String;
      F: TFileStream;
      P: PChar;
      iLen, iWrote: Integer;  Title, DLLName, ProgID, ClsID, FileVer: String;  CABDirective, InfFile: String;  _hfile: HFILE;
    mCreationTime, mLastAccessTime, mLastWriteTime: FILETIME; StartInfo: STARTUPINFO ; // name structure
    ProcInfo: PROCESS_INFORMATION ; // name structure
    begin
      CoInitialize(Nil);
      try
        FileVer := GetVersion(FileName);
        ClsID := GetCLSID(FileName);
        DLLName := ExtractFileName(FileName);
        ProgID := GetProgID(FileName);
        Title := 'Ocx Inf file Maker';
        InfFileName := ChangeFileExt(FileName, '.inf');
        CabFileName := ChangeFileExt(FileName, '.cab');
        DDFFileName := ChangeFileExt(FileName, '.ddf');    CABDirective := StringReplace( MakeCabDirective,
                                        '%CABFile%',
                                        ExtractFileName(CabFileName),
                                        [rfReplaceAll, rfIgnoreCase]
                                        );
        CABDirective := StringReplace( CABDirective,
                                        '%CABFilePath%',
                                        ExtractFilePath(CabFileName),
                                        [rfReplaceAll, rfIgnoreCase]
                                        )
                        + '"' + FileName + '"'
                        + #13#10'"' + InfFileName + '"';    //如果还有其它附加文件需要打包请在这里增加一个CallBack
        //直接按每文件一行往上附加    InfFile := StringReplace(  Templete,
                                  '%Title%',
                                  Title,
                                  [rfReplaceAll, rfIgnoreCase]
                                  );
        InfFile := StringReplace( InfFile,
                                  '%DLLName%',
                                  DLLName,
                                  [rfReplaceAll, rfIgnoreCase]
                                  );
        InfFile := StringReplace( InfFile,
                                  '%DllVersion%',
                                  FileVer,
                                  [rfReplaceAll, rfIgnoreCase]
                                  );
        InfFile := StringReplace( InfFile,
                                  '%ProgId%',
                                  ProgID,
                                  [rfReplaceAll, rfIgnoreCase]
                                  );
        InfFile := StringReplace( InfFile,
                                  '%DLLClsid%',
                                  ClsID,
                                  [rfReplaceAll, rfIgnoreCase]
                                  );    //写入INF文件
        f := TFileStream.Create(InfFileName,fmCreate);
        try
          p := PChar(InfFile);
          iLen := Length(InfFile);
          while (iLen > 0) do begin
            iWrote := f.Write(p^, iLen);
            Inc(p, iWrote);
            Dec(iLen, iWrote);
          end;
        finally
          f.Free;
        end;    //如果还有其它附加文件请在这里增加一个CallBack
        //文件通常有两类:1.需要注册的;2.不需要注册的.
        //另外就是文件可能安装目录有两种:1.当前目录(即随机目录);2.特定目录(可以使用环境变量)
        //写Inf文件请按照.Ini格式,比如TIniFile类或者API来操作等
        //更新.INF的文件时间为.OCX的时间
        _hFile := _lopen(PChar(FileName), OF_READWRITE);
        GetFileTime(  THANDLE(_hFile),
                      @mCreationTime,
                      @mLastAccessTime,
                      @mLastWriteTime
                      );
        _lclose(_hFile);    _hFile := _lopen(PChar(InfFile), OF_READWRITE);
        SetFileTime( THANDLE(_hFile),
                      @mCreationTime,
                      @mLastAccessTime,
                      @mLastWriteTime
                      );
        _lclose(_hFile);    //写入DDF文件,供工具程序MakeCab.exe使用
        f := TFileStream.Create(DDFFileName,fmCreate);
        try
          p := PChar(CABDirective);
          iLen := Length(CABDirective);
          while (iLen > 0) do begin
            iWrote := f.Write(p^, iLen);
            Inc(p, iWrote);
            Dec(iLen, iWrote);
          end;
        finally
          f.Free;
        end;    //执行MakeCAB创建CAB包    fillchar(ProcInfo, sizeof(ProcInfo), 0); // Set up memory block
        fillchar(StartInfo, sizeof(StartInfo), 0); // Set up memory block
        StartInfo.cb := sizeof(StartInfo); // Set structure size
        if Not CreateProcess( Nil,
                              PChar('makecab /f "' + DDFFileName + '"'),
                              Nil,
                              Nil,
                              False,
                              0,
                              Nil,
                              PChar(ExtractFilePath(FileName)),
                              StartInfo,
                              ProcInfo) then
          Exit;    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
        CloseHandle(ProcInfo.hThread);
        CloseHandle(ProcInfo.hProcess);    //更新CAB的文件时间为.OCX的时间
        _hFile := _lopen(PChar(FileName), OF_READWRITE);
        GetFileTime(  THANDLE(_hFile),
                      @mCreationTime,
                      @mLastAccessTime,
                      @mLastWriteTime
                      );
        _lclose(_hFile);    _hFile := _lopen(PChar(CabFileName), OF_READWRITE);
        SetFileTime( THANDLE(_hFile),
                      @mCreationTime,
                      @mLastAccessTime,
                      @mLastWriteTime
                      );
        _lclose(_hFile);
      finally
        CoUninitialize;
      end;end;
    end.
      

  9.   

    使用示例:
    uses
        UnitMakeCAB;
    procedure TForm3.Button1Click(Sender: TObject);
    var
      FileName: String;
    begin
      if OpenDialog1.Execute then begin
        FileName := OpenDialog1.FileName;
        if SameText(ExtractFileExt(FileName), '.ocx') then begin
          MakeCAB(FileName);
        end;
      end;
    end;
      

  10.   

    发现僵哥太强了。
    问一下:
    关于: 
    [AddToRegistry] 
    HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}" 
    HKLM,"SOFTWARE\Classes\CLSID\%DLLClsid%\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}" 这里的7DD95801-9882-11CF-9FA9-00AA006C42C4是什么,是固定的吗?
      

  11.   

    数字签名问题,应该怎么解决呢?
    现在发现浏览器会拦截我的ocx,而且就算设置了浏览器信任站点和自定义设置里对Activex的启动,但有些反病毒软件也会自动拦截。
    如果有数字签名应该会解决这个问题。
      

  12.   

    僵哥,用了一下你的Delphi代码,可能是我哪里没设置好,发现问题如下:
    1、点击makecab按钮,会把主程序窗口再弹出一个。
    2、只生成了inf文件,但没生成cab文件
    3、生成的inf文件里,FileVersion=0,0,0,0,是不是我应该设置ActiveX的版本为自动增长?
      

  13.   

    你应该是没有设置版本.先查看一下inf文件当中的数据对不对,另外确认生成的.ddf文件,如果确认无误的话,进入命令行状态并切换到该目录
    执行:
    [code=BatchFile]makecab.exe /f xxx.ddf[/code]
      

  14.   

    //MackCab 用的中间文件模板,文件附加在后面,不能带路径(估计可以支持8.3短路径)
    这条注释是有问题的,忘改了.
    实际上是对于长路径需要使用双引号将路径引起来。另外,我测试的系统是Win2003,不知道是否存在MakeCab.exe版本的问题。最最最为关键的是,你不能把自己的程序命名为MakeCab.exe...
      

  15.   

    找到原因了,
    1、因为我把这个工程生成的exe也命名为makecab.exe了。所以程序默认会执行我这个makecab.exe而不是系统的那个。
    2、因为执行的是我的makecab.exe,所以不会生成cab。
    3、ActiveX项目的project-options-version info,选中include version infomation in project就可以了 
      

  16.   

    僵哥对数字签名熟悉不?听说.net里是有的,但是Delphi IDE里好像没有。
      

  17.   

    可以使用 .net的SignTool.exe进行数字签名,但是需要的是,要么购买商业数字证书,或者申请免费的数字证书等。也可以自己搭设CA服务平台。关键是要求用户端能够认可为授信证书才可以。
      

  18.   

    比如你可以下载OpenSSL,自己为自己生成一个根证书,并且导入到系统当中。再使用该证书进行签名。然后执行你的Web页面看看效果。
      

  19.   

    免费的IE默认是不承认的.购买的ie直接承认证书有效.
    不承认的情况下你得修改ie设置才行.
      

  20.   

    我现在的做法,是让用户把相应网址设置为信任站点,并且设置“自定义级别”,把里面与AcitveX有关的选项设置为不是“禁用”状态,但这样实在是不理想,对于最终用户来说,有点麻烦。
    做成CAB自带inf安装信息,通过页面下载安装也和直接OCX效果一样会被IE禁用吗?现在来看,购买数字签名是不太可能了,只能想其他的办法。
    大家还有什么好的建议,是我们自己可以通过技术实现的呢?
      

  21.   


    简单的做法就是提供安装包,让用户手动安装.不买数字签名想通过ie安装比较困难.要不你给ie打补丁,让ie不验证数字签名.