最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

visual c++ - Why can't I get MSI installation progress in my MFC - Stack Overflow

programmeradmin3浏览0评论

I am trying to display the progress of an MSI installation in my MFC application, but I am not able to get the progress updates to show in my UI. Here is a snippet of my code:

#include "resource.h"
#include "afxdialogex.h"
#include "CMainDlg.h"
#include "msi.h"
#include "MsiQuery.h"

#define ON_WM_MSI_INSTALLATION_PROGRESS_SET_RANGE (WM_USER + 101)
#define ON_WM_MSI_INSTALLATION_PROGRESS_CHANGED (WM_USER + 102)

IMPLEMENT_DYNAMIC(CMainDlg, CDialogEx)

CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_Main, pParent)
{
}

void CMainDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_ActionTextS, m_ActionTextS);
    DDX_Control(pDX, IDC_PROGRESS1, m_InstallationProgress);
}

BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
    ON_MESSAGE(ON_WM_MSI_INSTALLATION_PROGRESS_SET_RANGE, &CMainDlg::OnMSIInstallationProgressSetRange)
    ON_MESSAGE(ON_WM_MSI_INSTALLATION_PROGRESS_CHANGED, &CMainDlg::OnMSIInstallationProgressChanged)
    ON_BN_CLICKED(IDC_BUTTON1, &CMainDlg::OnBnClickedButton1)
END_MESSAGE_MAP()

struct UIHandlerContext
{
    CWnd* pThis;
};

UIHandlerContext g_context;

int __stdcall InstallUIHandler(LPVOID pvContext, UINT iMessageType, LPCSTR szMessage)
{
    MSIHANDLE hRecord = reinterpret_cast<MSIHANDLE>(szMessage);
    UINT baseMessageType = iMessageType & 0xFF000000; // Fixed bitmask

    TRACE("Received message type: 0x%08X (base: 0x%08X)\n", iMessageType, baseMessageType);

    if (!hRecord)
    {
        TRACE("Invalid record handle\n");
        return ERROR_SUCCESS;
    }

    switch (baseMessageType)
    {
    case INSTALLMESSAGE_PROGRESS:
    {
        int field1 = MsiRecordGetInteger(hRecord, 1);
        int field2 = MsiRecordGetInteger(hRecord, 2);

        TRACE("Progress message - Field1: %d, Field2: %d\n", field1, field2);

        static int totalSteps = 0;
        static int currentProgress = 0;

        if (field1 == 0 && field2 > 0)  // Reset counter
        {
            totalSteps = field2;
            currentProgress = 0;
            TRACE("Setting total steps to: %d\n", totalSteps);
            g_context.pThis->PostMessage(ON_WM_MSI_INSTALLATION_PROGRESS_SET_RANGE, 0, totalSteps);
        }
        else if (field1 == 1)  // Increment
        {
            currentProgress += field2;
            TRACE("Incrementing progress to: %d\n", currentProgress);
            g_context.pThis->PostMessage(ON_WM_MSI_INSTALLATION_PROGRESS_CHANGED, 0, currentProgress);
        }
    }
    break;
    }

    return ERROR_SUCCESS;
}

UINT InstallMSIWithUIHandler(LPCTSTR szMSIPath, CMainDlg* pThis)
{
    g_context.pThis = pThis;

    MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);

    INSTALLUI_HANDLER previousUI = MsiSetExternalUI(
        InstallUIHandler,
        INSTALLLOGMODE_PROGRESS |
        INSTALLLOGMODE_ACTIONSTART |
        INSTALLLOGMODE_ACTIONDATA |
        INSTALLLOGMODE_FATALEXIT |
        INSTALLLOGMODE_ERROR |
        INSTALLLOGMODE_WARNING |
        INSTALLLOGMODE_USER |
        INSTALLLOGMODE_INFO |
        INSTALLLOGMODE_COMMONDATA,
        NULL);

    CString commandLine = L"ALLUSERS=1 REBOOT=ReallySuppress";
    return MsiInstallProduct(szMSIPath, commandLine);
}

CString GetStartupPath()
{
    wchar_t path[MAX_PATH];
    GetModuleFileNameW(NULL, path, MAX_PATH);
    CString fullPath(path);
    int pos = fullPath.ReverseFind(L'\\');
    CString directory = fullPath.Left(pos);
    directory.Replace("\\", "\\\\");
    return directory;
}

LRESULT CMainDlg::OnMSIInstallationProgressSetRange(WPARAM wParam, LPARAM lParam)
{
    int totalRange = (int)lParam;
    CString msg;
    msg.Format("Setting Progress Range: 0 to %d", totalRange);
    MessageBox(msg, "Debug", MB_OK);
    m_InstallationProgress.SetRange32(0, totalRange);
    return 0;
}

LRESULT CMainDlg::OnMSIInstallationProgressChanged(WPARAM wParam, LPARAM lParam)
{
    int progress = (int)lParam;
    CString msg;
    msg.Format("Setting Progress Position: %d", progress);
    MessageBox(msg, "Debug", MB_OK);
    m_InstallationProgress.SetPos(progress);
    return 0;
}

BOOL CMainDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    m_InstallationProgress.SetRange32(0, 100);
    m_InstallationProgress.SetStep(1);
    m_InstallationProgress.SetPos(0);

    return TRUE;
}

void CMainDlg::OnBnClickedButton1()
{
    InstallMSIWithUIHandler(GetStartupPath() + "\\test.msi", this);
}

Despite following the instructions to set up the message handler for the MSI installation progress, I am unable to get the progress updates to reflect in my UI. Any help or suggestions on what might be wrong would be greatly appreciated.

Thank you!

I tried various ways using the INSTALLMESSAGE_PROGRESS message but it doesn't seem to work, what I expect is to get the same progress as the MSI that is displayed just below the ActionText

MSI Installation ProgressBar

My UI ProgressBar

could someone help me?

发布评论

评论列表(0)

  1. 暂无评论