65.9K
CodeProject 正在变化。 阅读更多。
Home

批处理 VC 项目向导

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (6投票s)

2007年11月7日

CPOL

2分钟阅读

viewsIcon

45783

downloadIcon

928

像“BCGControl Bar Pro Build Wizard”一样,使用向导构建所有项目,包括输出。

Screenshot - Snap.png

引言

这是一个非常有用的工具,用于为您的团队构建串行项目,当您的软件包含许多使用VC++ 6.0、VC++ 2003、VC++ 2005以及VC++ 2008创建的组件时。同时,您可以创建批处理文件来执行一些附加任务,例如增加项目的版本号、复制/删除文件以及计算最终输出二进制文件的MD5值等。

您可以通过选择项目并从“状态”图标获取编译状态来编译它们,甚至可以在编译过程中停止构建过程。当然,您可以选择查看编译的运行时输出。

背景

最近,我有机会管理一个包含许多VC++项目的项目。我们不得不先一个个地编译它们,后来我们使用批处理文件来做这件事。但这需要很长时间才能得到最终结果,而且控制流程很差:如果其中一个项目失败了,我们就不得不重新编译所有项目。因此,我搜索了网络并了解到CodeJock和BCGSoft都有它们的GUI构建向导,并想到为什么不为我们创建一个通用的呢?所以,它来了。^)^

Using the Code

在这个工具中,我们使用了一些通用的东西,包括INI读取器、控制台重定向器和XListCtrl。所有初始化都从……开始

CBuildWizDlg::OnInitDialog(): 

InitListCtrl(&m_List);
FillListCtrl(&m_List);

// Toggle the state of output
OnDetail();

// Center Main Dialog.
CenterWindow();
m_log.m_pWnd = this;

// Set the Header Control
m_HeaderCtrl.SetTitleText(m_objSet.m_stuBWS_COMM.szPrjName);
m_HeaderCtrl.SetDescText(m_objSet.m_stuBWS_COMM.szComments);

m_HeaderCtrl.SetIconHandle(AfxGetApp()->LoadIcon(IDI_MSDEV));
m_HeaderCtrl.Init(this);
m_HeaderCtrl.MoveCtrls(this);

// Init the Build Envirement.
InitBuildEnv();

以下是关于我们列表控件初始化的详细信息

// Create the Project List items from the BuildWiz.ini.
void CBuildWizDlg::FillListCtrl(CXListCtrl *pList)
{
    // Read Settings From INI
    m_objSet.InitSettings();

    //
    CString        strTitle;
    strTitle.Format("BuildWiz - script by %s ", 
                    m_objSet.m_stuBWS_COMM.szAuthor);
    SetWindowText(strTitle);

    pList->LockWindowUpdate();
    // ***** lock window updates while filling list *****
    
    pList->DeleteAllItems();
    
    CString                str = _T("");
    int                    nItem, nSubItem;
    STU_BWS_ITEM        bwsItem;

    for(nItem = 0; nItem < m_objSet.m_stuBWS_COMM.nItems; nItem ++)
    {
        for (nSubItem = 0; nSubItem < BWS_COLS; nSubItem++)
        {
            str = _T("");
            bwsItem = m_objSet.m_arrBWItems.GetAt(nItem);

            // Text
            if (nSubItem == 0)                // Enable
                str.Format("%s", bwsItem.szComponent);
            else if (nSubItem == 1)                // Label
                str.Format("%s", bwsItem.szComments);
            else if (nSubItem == 2)                // Status
            {
                str = _T(" ");
                pList ->SetItemImage(nItem, nSubItem, BLDWIZ_STATUS_NA);
            }

            // Do it.
            if (nSubItem == 0)
            {
                pList->InsertItem(nItem, str);

                if(strnicmp(bwsItem.szStatus, "yes", 3) == 0)
                    pList->SetCheckbox(nItem, nSubItem, ITEM_STATUS_CHECKED);
                else if(strnicmp(bwsItem.szStatus, "no", 2) == 0)
                    pList->SetCheckbox(nItem, nSubItem, ITEM_STATUS_UNCHECKED);
                else
                    pList->SetCheckbox(nItem, nSubItem, ITEM_STATUS_HIDDEN);
            }
            else
                pList->SetItemText(nItem, nSubItem, str);

        }

    }
    
    pList->UnlockWindowUpdate();    // ***** unlock window updates *****
}

为了构建项目,我们需要编译器的一些环境,例如“include”、“lib”、“path”;我们这样做是在……

// Set the Env: 'include', 'lib', 'path'.
void CBuildWizDlg::InitBuildEnv()
{
    TCHAR        tszEnv[MAX_ENVVAR_LEN + 1] = {0};
    CString        strEnv;

    // Include
    if(strlen(m_objSet.m_stuBWS_COMM.szIncDir) > 0)
    {
        GetEnvironmentVariable("INCLUDE", tszEnv, sizeof(tszEnv));
        strEnv.Format("%s;%s", m_objSet.m_stuBWS_COMM.szIncDir, tszEnv);
        SetEnvironmentVariable("INCLUDE", strEnv);
    }

    // Library 
    if(strlen(m_objSet.m_stuBWS_COMM.szLibDir ) > 0)
    {
        GetEnvironmentVariable("LIB", tszEnv, sizeof(tszEnv));
        strEnv.Format("%s;%s", m_objSet.m_stuBWS_COMM.szLibDir, tszEnv);
        SetEnvironmentVariable("LIB", strEnv);
    }

    // Path 
    if(strlen(m_objSet.m_stuBWS_COMM.szExeDir) > 0)
    {
        GetEnvironmentVariable("PATH", tszEnv, sizeof(tszEnv));
        strEnv.Format("%s;%s", m_objSet.m_stuBWS_COMM.szExeDir, tszEnv);
        SetEnvironmentVariable("PATH", strEnv);
    }

    // 'BWBaseDir' variable
    if(strlen(m_objSet.m_stuBWS_COMM.szBaseDir) > 0)
    {
        SetEnvironmentVariable("BWBASEDIR", m_objSet.m_stuBWS_COMM.szBaseDir);
    }
    else
        SetEnvironmentVariable("BWBASEDIR", "");


    // Change the current directory.
    if(strlen(m_objSet.m_stuBWS_COMM.szBaseDir) > 0)
    {
        if(!SetCurrentDirectory(m_objSet.m_stuBWS_COMM.szBaseDir))
            OutputDebugString("\nError! Base Directory is invalid.");
        else
        {
            
        }
    }
}

由于某种原因,我们必须对msdev.exe.bat.cmd使用“重定向”技术;但是,对于VS2005的devenv.exe,我们必须使用“管道”技术。您可以在“CBuildWizDlg::OnBuild()”函数中看到它们。

// This is the Piper.
    CTraceCollector objTracer(&m_log);
    objTracer.Run();

    // Here we start build and create a redirected application.
    if(!RunScript(m_objSet.m_stuBWS_COMM.szPreCompile))
    {
     ... ...

如何使用此工具

首先,您应该了解一些关于BuildWiz.ini的信息。有一个[common]部分用于项目的通用设置,并且对于产品中的每个项目,都有许多[item?]部分。我确信的是,一旦您查看了demo BuildWiz.ini后运行BuildWiz.exe,您就应该知道每个标签的含义。

请先下载二进制文件。

关注点

  • BuildWiz支持VC++ 6.0和VC++ 2005项目,我认为MinGW、Cygin、C51也受支持。
  • 我们同时使用了管道和重定向技术。
  • 可以改进BuildWiz以支持用户自定义的环境变量。
  • 作为项目经理,您可以使您的软件构建比以往更快更容易。:)
  • 它在构建源代码时为您提供了更多控制。

历史

  • 2008-05-16: 版本1.2。BuildWiz.ini现在支持'BaseDir={PWD}'。
  • 2008-01-23: 版本1.1。BuildWiz.ini现在支持%basedir%变量。
  • 通过使用这个新变量,我们可以简化.ini文件。

  • 2007-10-08: 首个版本。(这是我在CodeProject上的第三篇文章。)
© . All rights reserved.