Microsoft Installer 封装类

来源:互联网 发布:leap计算软件 编辑:程序博客网 时间:2024/06/05 21:57

制作 MSI 和控制 MSI 安装过程的封装类,该类是在线自动升级系统中发布工具和升级客户端的公共部分,具体代码如下:

 

//==================================================================================================

//                MSI 安装函数封装类( Microsoft Installer Wrapper Template Class )

//

//    作者:王志科                                        版权没有,随意转载(请保留该文件头部信息)

//==================================================================================================

 

#pragma once

 

#include "msi.h"

#include "MsiDefs.h"

#include "MsiQuery.h"

 

#pragma comment(lib,"msi")

 

#ifndef CHK_EXP_RET

#define CHK_EXP_RET(exp,ret) if(exp){ return ret; }

#define CHK_EXP_RUN(exp,run) if(exp){ run; }

#endif

 

namespace MSI

{

    //==============================================================================================

    //

    template<bool tManage = true> class HandlerT

    {

    public:

        HandlerT(MSIHANDLE hMsi = NULL) : m_hMsi(hMsi) { }

        ~HandlerT() { if(tManage){ Close(); } }

 

    public:

        void Close(){ if(m_hMsi){ MsiCloseHandle(m_hMsi); m_hMsi = NULL; } }

 

    public:

        void Attach(MSIHANDLE hMsi){ ATLASSERT(m_hMsi != NULL); m_hMsi = hMsi; }

        MSIHANDLE Detach(){ MSIHANDLE hMsi = m_hMsi; m_hMsi = NULL; return hMsi; }

 

    public:

        void operator =(MSIHANDLE hMsi){ Close(); m_hMsi = hMsi; }

        MSIHANDLE* operator &() { Close(); return &m_hMsi; }

        operator MSIHANDLE() { return m_hMsi; }

 

    protected:

        MSIHANDLE m_hMsi;

    };

 

    //==============================================================================================

    //

    template<bool tManage = true> class DatabaseT : public HandlerT<tManage>

    {

    public:

        DatabaseT(MSIHANDLE hDatabase = NULL)

        {

            m_hMsi = hDatabase;

        }

 

        DatabaseT(LPCTSTR lpszDatabase, LPCTSTR szPersist)

        {

            Open(lpszDatabase, szPersist);

        }

 

    public:

        UINT Open(LPCTSTR lpszDatabase, LPCTSTR szPersist)

        {

            return MsiOpenDatabase(lpszDatabase, szPersist, &m_hMsi);

        }

 

        VOID Close(BOOL bCommit = FALSE)

        {

            if(bCommit) Commit();

            HandlerT::Close();

        }

 

        UINT Commit()

        {

            return MsiDatabaseCommit(m_hMsi);

        }

 

        UINT Import(LPCTSTR szFolderPath,LPCTSTR szFileName)

        {

            return MsiDatabaseImport(m_hMsi,szFolderPath,szFileName);

        }

 

        UINT Export(LPCTSTR szTableName,LPCTSTR szFolderPath,LPCTSTR szFileName)

        {

            return MsiDatabaseExport(m_hMsi,szTableName,szFolderPath,szFileName);

        }

 

        UINT Merge(MSIHANDLE hDatabase, LPCTSTR szTableName)

        {

            return MsiDatabaseMerge(m_hMsi,hDatabase,szTableName);

        }

 

        UINT GenerateTransform(MSIHANDLE hDatabase, LPCTSTR szTransformFile)

        {

            return MsiDatabaseGenerateTransform(m_hMsi,hDatabase,szTransformFile,0,0);

        }

 

        UINT ApplyTransform(LPCTSTR szTransformFile, INT iErrorConditions)

        {

            return MsiDatabaseApplyTransform(m_hMsi,szTransformFile,iErrorConditions);

        }

 

        MSIDBSTATE GetState()

        {

            return MsiGetDatabaseState(m_hMsi);

        }

 

        MSICONDITION TableExists(LPCTSTR szTableName)

        {

            return MsiDatabaseIsTablePersistent(m_hMsi,szTableName);

        }

 

        MSICONDITION IsTablePersistent(LPCTSTR szTableName)

        {

            return MsiDatabaseIsTablePersistent(m_hMsi,szTableName);

        }

 

        // RecordT

        UINT PrimaryKeys(LPCTSTR szTableName, MSIHANDLE& hRecord)

        {

            return MsiDatabaseGetPrimaryKeys(m_hMsi,szTableName,&hRecord);

        }

 

        // View

        UINT OpenView(LPCTSTR szQuery, MSIHANDLE* pView)

        {

            return MsiDatabaseOpenView(m_hMsi,szQuery, pView);

        }

 

        // View

        UINT OpenExecuteView(LPCTSTR szQuery, MSIHANDLE* pView)

        {

            UINT nCaller = OpenView(szQuery, pView);

            CHK_EXP_RET(nCaller != ERROR_SUCCESS , nCaller);

            return MsiViewExecute(*pView, NULL);

        }

    };

 

    //==============================================================================================

    //

    template<bool tManage = true> class RecordT : public HandlerT<tManage>

    {

    public:

        RecordT(UINT cParams = 3)

        {

            m_hMsi = MsiCreateRecord(cParams);

        }

 

    public:

        UINT GetFieldCount()

        {

            return MsiRecordGetFieldCount(m_hMsi);

        }

 

        BOOL IsNull(UINT iField)

        {

            return MsiRecordIsNull(m_hMsi,iField);

        }

 

        UINT SetNumber(UINT iField, INT iValue)

        {

            return MsiRecordSetInteger(m_hMsi,iField,iValue);

        }

 

        INT GetNumber(UINT iField)

        {

            return MsiRecordGetInteger(m_hMsi,iField);

        }

 

        BOOL GetString(UINT iField, CString& strValue)

        {

            DWORD dwValue = 4096;

            LPTSTR szValue = strValue.GetBuffer(dwValue);

            UINT nCaller = MsiRecordGetString(m_hMsi,iField,szValue,&dwValue);

            if(nCaller == ERROR_MORE_DATA)

            {

                dwValue += 2;

                strValue.ReleaseBuffer();

                szValue = strValue.GetBuffer(dwValue);

                nCaller = MsiRecordGetString(m_hMsi,iField,szValue,&dwValue);

            }

 

            strValue.ReleaseBuffer();

            return nCaller == ERROR_SUCCESS;

        }

 

        UINT GetString(UINT iField, LPTSTR szValue, LPDWORD dwValue)

        {

            return MsiRecordGetString(m_hMsi,iField,szValue,dwValue);

        }

 

        UINT SetString(UINT iField, LPCTSTR szValue)

        {

            return MsiRecordSetString(m_hMsi,iField,szValue);

        }

 

        UINT GetStream(UINT iField, LPSTR szBuffer,LPDWORD dwBuffer)

        {

            return MsiRecordReadStream(m_hMsi,iField,szBuffer,dwBuffer);

        }

 

        UINT SetStream(UINT iField, LPCTSTR szFilePath)

        {

            return MsiRecordSetStream(m_hMsi,iField,szFilePath);

        }

    };

 

    //==============================================================================================

    //

    template<bool tManage = true> class ViewT : public HandlerT<tManage>

    {

    public:

        ViewT(MSIHANDLE hView = NULL)

        {

            m_hMsi = hView;

        }

 

        ViewT(MSIHANDLE hDatabase, LPCTSTR szQuery)

        {

            Open(hDatabase, szQuery);

        }

 

    public:

        UINT Open(MSIHANDLE hDatabase, LPCTSTR szQuery)

        {

            return MsiDatabaseOpenView(hDatabase,szQuery,&m_hMsi);

        }

 

        BOOL Execute(MSIHANDLE hRecord = NULL)

        {

            return MsiViewExecute(m_hMsi, hRecord);

        }

 

        UINT Fetch(MSIHANDLE& hRecord)

        {

            return MsiViewFetch(m_hMsi, &hRecord);

        }

 

        UINT Modify(MSIMODIFY eModify, MSIHANDLE hRecord)

        {

            return MsiViewModify(m_hMsi,eModify,hRecord);

        }

 

        UINT GetColumnInfo(MSICOLINFO eColumnInfo,MSIHANDLE& hRecord)

        {

            return MsiViewGetColumnInfo(m_hMsi,eColumnInfo,&hRecord);

        }

 

        // 执行了 Execute 之后,那么在下一次执行 Execute 之前必须调用该函数

        UINT Release()

        {

            return MsiViewClose(m_hMsi);

        }

    };

 

    template<bool tManage = true> class SummaryInformationT : public HandlerT<tManage>

    {

    public:

        SummaryInformationT(MSIHANDLE hDatabase, LPCTSTR szDatabase = NULL, UINT uiUpdateCount = 20)

        {

            Open(hDatabase,szDatabase, uiUpdateCount);

        }

 

    public:

        UINT GetPropertyCount(PUINT puiPropertyCount)

        {

            return MsiSummaryInfoGetPropertyCount(m_hMsi, puiPropertyCount);

        }

 

        UINT GetProperty(UINT uProperty,PUINT puiDataType,PINT piValue,PFILETIME pFileTime,LPTSTR szValue,LPDWORD dwValue)

        {

            return MsiSummaryInfoGetProperty(m_hMsi,uProperty,puiDataType,piValue,pFileTime,szValue,dwValue);

        }

 

        UINT SetProperty(UINT uProperty,UINT uDataType,INT iValue,PFILETIME pFileTime,LPTSTR szValue)

        {

            return MsiSummaryInfoSetProperty(m_hMsi,uProperty,uDataType,iValue,pFileTime,szValue);

        }

 

        UINT Open(MSIHANDLE hDatabase, LPCTSTR szDatabase = NULL, UINT uiUpdateCount = 20)

        {

            return MsiGetSummaryInformation(hDatabase,szDatabase, uiUpdateCount, &m_hMsi);

        }

 

        UINT Commit()

        {

            return MsiSummaryInfoPersist(m_hMsi);

        }

 

    public:

        UINT GetPropertyInteger(UINT uProperty,PINT piValue)

        {

            UINT uiDataType = VT_I4;

            return GetProperty(uProperty,&uiDataType,piValue,NULL,NULL,0);

        }

 

        UINT GetPropertyFiletime(UINT uProperty,PFILETIME pFileTime)

        {

            UINT uiDataType = VT_FILETIME;

            return GetProperty(uProperty,&uiDataType,NULL,pFileTime,NULL,0);

        }

 

        UINT GetPropertyString(UINT uProperty,LPTSTR szValue,LPDWORD dwValue)

        {

            UINT uiDataType = VT_LPSTR;

            return GetProperty(uProperty,&uiDataType,NULL,NULL,szValue,dwValue);

        }

 

        UINT SetPropertyInteger(UINT uProperty,INT iValue)

        {

            return SetProperty(uProperty,VT_I4,iValue,NULL,NULL);

        }

 

        UINT SetPropertyString(UINT uProperty,LPWSTR szValue)

        {

            return SetProperty(uProperty, VT_LPSTR, 0, NULL, szValue);

        }

 

        UINT SetPropertyFiletime(UINT uProperty,PFILETIME pFileTime)

        {

            return SetProperty(uProperty,VT_FILETIME,0,pFileTime,NULL);

        }

 

    public:

        VOID Close(BOOL bCommit = FALSE)

        {

            if(bCommit) Commit();

            HandlerT::Close();

        }

    };

 

    //==============================================================================================

    //    安装控制函数

    template<typename T = CWindow > struct InstallerT

    {

    public:

        InstallerT()

        {

            MemberInitialize();

            m_nProgressBar = 0;

            m_nProcessInfo = 0;

        }

 

        ~InstallerT()

        {

            CancelInstaller();

        }

 

    public:

        VOID CancelInstaller()

        {

            m_bCancelInstall = FALSE;

        }

 

        VOID SetExternalUI(DWORD dwMsgFilter)

        {

            MsiSetExternalUI(InstallerCallback, dwMsgFilter, (LPVOID)this);

        }

 

        UINT SetInternalUI(INSTALLUILEVEL nInstallerLevel, HWND* pWindow = NULL)

        {

            return MsiSetInternalUI(nInstallerLevel, pWindow);

        }

 

        //    在命令行中可以设置动作和属性,例如下面将产品安装到 D:/LiveSystem

        //    TEXT("ACTION=INSTALL TARGETDIR=/"D://LiveSystem/"")

        UINT StartInstaller(LPCTSTR lpszPackage, LPCTSTR szCommandLine = NULL)

        {

            return MsiInstallProduct(lpszPackage, szCommandLine);

        }

 

        UINT SetControlID(UINT nProgressBar, UINT nProcessInfo = 0)

        {

            m_nProgressBar = nProgressBar;

            m_nProcessInfo = nProcessInfo;

            return ERROR_SUCCESS;

        }

 

        UINT SetScriptStringID(UINT nScriptStrID = 0)

        {

            m_nScriptStrID = nScriptStrID;

            return ERROR_SUCCESS;

        }

 

    public:

        // 采用默认参数安装指定的包

        UINT InstallPackage(LPCTSTR lpszPackage, LPCTSTR pszCommand = NULL)

        {

            // 准备参数变量

            DWORD dwUILevel = INSTALLUILEVEL_NONE|INSTALLUILEVEL_SOURCERESONLY;

            DWORD dwMessageFilter = INSTALLLOGMODE_USER | INSTALLLOGMODE_INFO

                | INSTALLLOGMODE_ACTIONDATA | INSTALLLOGMODE_OUTOFDISKSPACE

                | INSTALLLOGMODE_COMMONDATA | INSTALLLOGMODE_RESOLVESOURCE

                | INSTALLLOGMODE_INITIALIZE | INSTALLLOGMODE_ACTIONSTART

                | INSTALLLOGMODE_SHOWDIALOG | INSTALLLOGMODE_TERMINATE

                | INSTALLLOGMODE_FILESINUSE | INSTALLLOGMODE_PROGRESS

                | INSTALLLOGMODE_EXTRADEBUG | INSTALLLOGMODE_WARNING

                | INSTALLLOGMODE_FATALEXIT  | INSTALLLOGMODE_ERROR;

 

            MemberInitialize();

            SetExternalUI(dwMessageFilter);

            SetInternalUI((INSTALLUILEVEL)dwUILevel);

            return StartInstaller(lpszPackage, pszCommand);

        }

 

    public:

        // 下面的函数是消息回调

        enum InstallerProgress

        {

            PROGRESS_RESET        = 0,

            PROGRESS_ACTIONINFO    = 1,

            PROGRESS_REPORT        = 2,

            PROGRESS_ADDITION    = 3,

        };

 

        enum InstallerCommonData

        {

            COMMON_DATA_LANGUAGE    = 0,

            COMMON_DATA_CAPTION        = 1,

            COMMON_DATA_CANCELSHOW    = 2,

        };

 

        // premature termination, possibly fatal OOM

        INT OnInstallerFatalExit(UINT uFlags, LPCTSTR lpszMessage)

        {

            T* pT = static_cast<T*>(this);

            return pT->MessageBox(lpszMessage,m_strTitle, uFlags);

        }

 

        // formatted error message

        INT OnInstallerError(UINT uFlags, LPCTSTR lpszMessage)

        {

            T* pT = static_cast<T*>(this);

            return pT->MessageBox(lpszMessage, m_strTitle, uFlags);

        }

 

        // formatted warning message

        INT OnInstallerWarning(UINT uFlags, LPCTSTR lpszMessage)

        {

            T* pT = static_cast<T*>(this);

            return pT->MessageBox(lpszMessage, m_strTitle ,uFlags);

        }

 

        // user request message

        INT OnInstallerUser(UINT uFlags, LPCTSTR lpszMessage)

        {

            // 需要分析 uFlags 来确定返回 IDOK 或者 IDYES 或者其他值

            return (uFlags & 0x0F) == MB_YESNO ? IDYES : IDOK;

        }

 

        // informative message for log

        INT OnInstallerInfo(UINT uFlags, LPCTSTR lpszMessage)

        {

            return IDOK;

        }

 

        // list of files in use that need to be replaced

        INT OnInstallerFilesInuse(UINT uFlags, LPCTSTR lpszMessage)

        {

            // 显示文件被使用的对话框

            return ERROR_SUCCESS;

        }

 

        // request to determine a valid source location

        INT OnInstallerResolveSource(UINT uFlags, LPCTSTR lpszMessage)

        {

            return ERROR_SUCCESS;

        }

 

        // insufficient disk space message

        INT OnInstallerOutOfDiskSpace(UINT uFlags, LPCTSTR lpszMessage)

        {

            return IDOK;

        }

 

        // start of action: action name & description

        INT OnInstallerActionStart(UINT uFlags, LPCTSTR lpszMessage)

        {

            return IDOK;

        }

 

        // formatted data associated with individual action item

        INT OnInstallerActionData(UINT uFlags, LPCTSTR lpszMessage)

        {

            // 如果没有初始化进度条,直接返回

            CHK_EXP_RET( m_nProgressTotal == 0 , IDOK );

 

            T* pT = static_cast<T*>(this);

            pT->SetDlgItemText(m_nProcessInfo, lpszMessage);

 

            if( m_bEnableActionData && m_nProgressBar ) 

            {

                HWND hProgressBar = pT->GetDlgItem(m_nProgressBar);

                SendMessage(hProgressBar, PBM_STEPIT, 0, 0);

            }

            return IDOK;

        }

 

        // progress gauge info: units so far, total

        INT OnInstallerProgress(UINT uFlags, LPCTSTR lpszMessage)

        {

            T* pT = static_cast<T*>(this);

            HWND hProgressBar = pT->GetDlgItem(m_nProgressBar);

 

            LONG nData[4] = { 0 , 0 , 0 , 0 };

            if( ParseProgressString(lpszMessage, nData) )

            {

                if(nData[0] == PROGRESS_RESET)

                {

                    m_nProgressTotal = nData[1];

                    m_bProgressForward = (nData[2] == 0);

                    m_nProgress = m_bProgressForward ? 0 : m_nProgressTotal ;

                    // 设置进度条的工作长度

                    SendMessage(hProgressBar, PBM_SETRANGE32, 0, m_nProgressTotal);

                    // 如果在处理脚本结束进度条,否则重置

                    WPARAM nCurrentPos = m_bProgressScript ? m_nProgressTotal : m_nProgress;

                    SendMessage(hProgressBar, PBM_SETPOS, nCurrentPos , 0);

                    m_nPosition = 0;

                    // 检测新的状态

                    m_bProgressScript = (nData[3] == 1);

 

                    if( m_bProgressScript && m_nProcessInfo && m_nScriptStrID )

                    {

                        TCHAR szScriptString[MAX_PATH] = { TEXT("") };

                        AtlLoadString(m_nScriptStrID, szScriptString, MAX_PATH);

                        pT->SetDlgItemText(m_nProcessInfo, szScriptString);

                    }

                }

                else if(nData[0] == PROGRESS_ACTIONINFO )

                {

                    if( nData[2] && m_nProgressBar )

                    {

                        WPARAM nStep =  m_bProgressForward ? nData[1] : -1 * nData[1] ;

                        SendMessage(hProgressBar, PBM_SETSTEP, nStep, 0);

                    }

                    m_bEnableActionData = nData[2] ? TRUE : FALSE ;

                }

                else if(nData[0] == PROGRESS_REPORT)

                {

                    if( m_nProgressTotal != 0 )

                    {

                        m_nPosition += nData[1];

                        WPARAM nCurrentPos = m_bProgressForward ? m_nPosition : -1 * m_nPosition;

                        SendMessage(hProgressBar, PBM_SETPOS, nCurrentPos, 0);

                    }

                }

                else if(nData[0] == PROGRESS_ADDITION)

                {

 

                }

            }

 

            return m_bCancelInstall ? IDCANCEL : IDOK ;

        }

 

        // product info for dialog: language Id, dialog caption

        INT OnInstallerCommonData(UINT uFlags, LPCTSTR lpszMessage)

        {

            ParseCommonDataString(lpszMessage);

            return IDOK;

        }

 

        // sent prior to UI initialization, no string data

        INT OnInstallerInitialize(UINT uFlags, LPCTSTR lpszMessage /* = NULL */)

        {

            return IDOK;

        }

 

        // sent after UI termination, no string data

        INT OnInstallerTerminate(UINT uFlags, LPCTSTR lpszMessage /* = NULL */)

        {

            return IDOK;

        }

 

        // sent prior to display or authored dialog or wizard

        INT OnInstallerShowDialog(UINT uFlags, LPCTSTR lpszMessage)

        {

            return IDOK;

        }

 

    public:

        INT OnInstallerPrepare(UINT uiMessageType, LPCTSTR lpszMessage)

        {

            if( m_bFirstTimeCall )

            {

                MsiSetInternalUI(INSTALLUILEVEL_BASIC, NULL);

                m_bFirstTimeCall = FALSE;

            }

 

            return ERROR_SUCCESS ;

        }

 

    public:

        // 消息回调的处理函数

        INT InstallerHandler(UINT uiMessageType, LPCTSTR lpszMessage)

        {

            T* pT = static_cast<T*>(this);

 

            // 首先允许进行特殊的消息处理

            INT nPrepare = pT->OnInstallerPrepare(uiMessageType, lpszMessage);

            CHK_EXP_RET( FAILED( nPrepare ) , nPrepare );

 

            // 根据消息类型进行分类处理

            UINT uFlags = (uiMessageType & 0x00FFFFFF);

            switch( (INSTALLMESSAGE)(0xFF000000 & uiMessageType) )

            {

                case INSTALLMESSAGE_FATALEXIT      : return pT->OnInstallerFatalExit     (uFlags, lpszMessage);

                case INSTALLMESSAGE_ERROR          : return pT->OnInstallerError         (uFlags, lpszMessage);

                case INSTALLMESSAGE_WARNING        : return pT->OnInstallerWarning       (uFlags, lpszMessage);

                case INSTALLMESSAGE_USER           : return pT->OnInstallerUser          (uFlags, lpszMessage);

                case INSTALLMESSAGE_INFO           : return pT->OnInstallerInfo          (uFlags, lpszMessage);

                case INSTALLMESSAGE_FILESINUSE     : return pT->OnInstallerFilesInuse    (uFlags, lpszMessage);

                case INSTALLMESSAGE_RESOLVESOURCE  : return pT->OnInstallerResolveSource (uFlags, lpszMessage);

                case INSTALLMESSAGE_OUTOFDISKSPACE : return pT->OnInstallerOutOfDiskSpace(uFlags, lpszMessage);

                case INSTALLMESSAGE_ACTIONSTART    : return pT->OnInstallerActionStart   (uFlags, lpszMessage);

                case INSTALLMESSAGE_ACTIONDATA     : return pT->OnInstallerActionData    (uFlags, lpszMessage);

                case INSTALLMESSAGE_PROGRESS       : return pT->OnInstallerProgress      (uFlags, lpszMessage);

                case INSTALLMESSAGE_COMMONDATA     : return pT->OnInstallerCommonData    (uFlags, lpszMessage);

                case INSTALLMESSAGE_INITIALIZE     : return pT->OnInstallerInitialize    (uFlags, lpszMessage);

                case INSTALLMESSAGE_TERMINATE      : return pT->OnInstallerTerminate     (uFlags, lpszMessage);

                case INSTALLMESSAGE_SHOWDIALOG     : return pT->OnInstallerShowDialog    (uFlags, lpszMessage);

            }

 

            return ERROR_SUCCESS;

        }

 

    protected:

        static INT CALLBACK InstallerCallback(LPVOID lpContext, UINT uiMessageType, LPCTSTR lpszMessage)

        {

            InstallerT< T >* lpInstaller = reinterpret_cast< InstallerT< T >* >(lpContext);

            return static_cast<T*>(lpInstaller)->InstallerHandler(uiMessageType,lpszMessage);

        }

 

    protected:

        void MemberInitialize()

        {

            m_bShowCancel = TRUE;

            m_wLanguage = LANG_NEUTRAL;

            m_wCodePage = GetACP();

 

            m_bProgressForward = TRUE;

            m_bProgressScript = FALSE;

            m_nProgressTotal = 0;

            m_nProgress = 0;

            m_nPosition = 0;

 

            m_bEnableActionData = FALSE;

            m_bCancelInstall = FALSE;

            m_bFirstTimeCall = TRUE;

        }

 

    protected:

        BOOL ParseCommonDataString(LPCTSTR lpString)

        {

            CHK_EXP_RET(lpString == NULL , FALSE );

            CHK_EXP_RET(lpString[0] == 0 , FALSE );

 

            // 分析字符串类型

            lpString = StrStr(lpString, TEXT("1:"));

            CHK_EXP_RET(lpString == NULL , FALSE);

            LONG nCommon = lpString[3] - TEXT('0');

 

            LPCTSTR lpStr2 = StrStr(lpString, TEXT("2:"));

            LPCTSTR lpStr3 = StrStr(lpString, TEXT("3:"));

 

            CHK_EXP_RET(lpStr2 == NULL , FALSE);

 

            if( nCommon == COMMON_DATA_CAPTION )

            {

                LPTSTR lpTail = (LPTSTR)lpStr3;

                if(lpTail != NULL){ *lpTail = 0; }

                m_strTitle = lpString + 2; //Skip "2:"

            }

            else if( nCommon == COMMON_DATA_LANGUAGE )

            {

                m_wLanguage = StrToLong(lpStr2 + 3);

 

                CHK_EXP_RET(lpStr3 == NULL , FALSE);

                m_wCodePage = StrToLong(lpStr3 + 3);

            }

            else if( nCommon == COMMON_DATA_CANCELSHOW )

            {

                LONG nShow = StrToLong(lpStr2 + 3);

                m_bShowCancel = nShow ? TRUE : FALSE;

            }

 

            return TRUE;

        }

 

        BOOL ParseProgressString(LPCTSTR lpString, LONG nData[4])

        {

            ZeroMemory( nData, sizeof(LONG) * 4 );

 

            CHK_EXP_RET(lpString == NULL , FALSE );

            CHK_EXP_RET(lpString[0] == 0 , FALSE );

 

            // 分析字符串类型

            lpString = StrStr(lpString, TEXT("1:"));

            CHK_EXP_RET(lpString == NULL , FALSE);

            nData[0] = lpString[3] - TEXT('0');

 

            // 第一个参数

            lpString = StrStr(lpString, TEXT("2:"));

            CHK_EXP_RET(lpString == NULL , TRUE);

            nData[1] = StrToLong(lpString + 3);

 

            // 第二个参数

            lpString = StrStr(lpString, TEXT("3:"));

            CHK_EXP_RET(lpString == NULL , TRUE);

            nData[2] = StrToLong(lpString + 3);

 

            // 第三个参数

            lpString = StrStr(lpString, TEXT("4:"));

            CHK_EXP_RET(lpString == NULL , TRUE);

            nData[3] = StrToLong(lpString + 3);

 

            return TRUE;

        }

 

    protected:

        // 下面是 CommonData 分析出的数据

        CString m_strTitle;            // 一般是安装的产品标题

        BOOL m_bShowCancel;            //    是否要显示“取消”按钮

        WORD m_wLanguage;            //    当前的语言 

        WORD m_wCodePage;            //    当前的代码页

 

        // 下面是 ProgressInfo 分析出的数据

        BOOL m_bProgressForward;    //    TRUE 表示当前处理进度条是增加的方式

        BOOL m_bProgressScript;        //    TRUE 表示在处理脚本,可以显示“请稍后”

        LONG m_nProgressTotal;        //    进度条总数

        LONG m_nProgress;            //    进度数

        LONG m_nPosition;            //    当前位置

 

        // 其他控制数据

        BOOL m_bEnableActionData;    //    TRUE 表示 INSTALLOGMODE_ACTIONDATA 消息发送进度信息

        BOOL m_bCancelInstall;        //    如果要取消安装将该值设置为 TRUE 

        BOOL m_bFirstTimeCall;        //    是否第一次调用外部界面接口

 

        // 窗口显示信息控件的ID

        UINT m_nProgressBar;        //    进度条控件

        UINT m_nProcessInfo;        //    显示处理信息的控件

        UINT m_nScriptStrID;        //    处理脚本,请稍后

    };

 

    //==============================================================================================

    //    全局的静态函数

    inline UINT GetFileHash(LPCTSTR lpszFileName, DWORD dwOptions, MSIFILEHASHINFO& rMsiFileHashInfo)

    {

        rMsiFileHashInfo.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);

        return MsiGetFileHash(lpszFileName, dwOptions, &rMsiFileHashInfo);

    }

 

    inline UINT GetLastError(CString& strErrorDescription)

    {

        strErrorDescription = TEXT("");

        MSIHANDLE hLastErrorRecord = MsiGetLastErrorRecord();

        CHK_EXP_RET(hLastErrorRecord == NULL , NO_ERROR);

 

        DWORD dwErrorLength = 4096;

        HandlerT<> hRecord(hLastErrorRecord);

        UINT nCaller = MsiFormatRecord(NULL,hRecord,NULL,&dwErrorLength);

        if(nCaller == ERROR_MORE_DATA)

        {

            dwErrorLength ++;

            LPTSTR lpszError = new TCHAR[dwErrorLength];

            nCaller = MsiFormatRecord(NULL,hRecord,lpszError,&dwErrorLength);

            if(nCaller == ERROR_SUCCESS) strErrorDescription = lpszError;

            delete [] lpszError;

        }

        return nCaller;

    }

 

    inline UINT GetFileVersion(LPCTSTR szFilePath, CString& strVersion, CString& strLanguage)

    {

        DWORD dwVersion = 32, dwLang = 32;

        LPTSTR lpszLang = strLanguage.GetBuffer(dwLang);

        LPTSTR lpszVersion = strVersion.GetBuffer(dwVersion);

        UINT nCaller = MsiGetFileVersion(szFilePath,lpszVersion, &dwVersion, lpszLang, &dwLang);

        if(nCaller == ERROR_MORE_DATA)

        {

            // 增加内存空间

            dwLang += 2; dwVersion += 2;

            strVersion.ReleaseBuffer(); lpszVersion = strVersion.GetBuffer(dwVersion);

            strLanguage.ReleaseBuffer(); lpszLang = strLanguage.GetBuffer(dwLang);

            nCaller = MsiGetFileVersion(szFilePath,lpszVersion, &dwVersion, lpszLang, &dwLang);

        }

        else if(nCaller == ERROR_FILE_INVALID)

        {

            // 文件没有版本信息

            nCaller = NO_ERROR;

        }

 

        strLanguage.ReleaseBuffer();

        strVersion.ReleaseBuffer();

        return nCaller;

    }

}

原创粉丝点击