home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / addins / autobld / commands.cpp < prev    next >
C/C++ Source or Header  |  1998-04-02  |  15KB  |  478 lines

  1. // Commands.cpp : implementation file
  2. //
  3.  
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6.  
  7. #include "stdafx.h"
  8. #include "AutoBld.h"
  9. #include "Commands.h"
  10. #include "config.h"
  11. #include <mapi.h>
  12.  
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18.  
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CCommands
  21.  
  22. CCommands::CCommands()
  23. {
  24.     m_pApplication = NULL;
  25.     m_pApplicationEventsObj = NULL;
  26.     m_pDebuggerEventsObj = NULL;
  27.  
  28.     //Because AutoBuild has an event for capturing the buildfinish event, we
  29.     //  need to set some flags to make sure only want to send mail when the
  30.     //  AutoBuild command is invoked, not when you walk up and say "compile"
  31.     m_bAutoBuilding = TRUE;
  32.  
  33.     // if there is a build in progress lets not try to start a second build
  34.     m_bBuildInProgres = FALSE;
  35.  
  36.     m_bTesting = TRUE;
  37.  
  38.     //Here we retrieve all our information for the build from the registry
  39.     m_bSendMail = (BOOL)(AfxGetApp()->GetProfileInt
  40.             (_T("Configure"), _T("SendMail"), 0));
  41.     m_strSendTo = AfxGetApp()->GetProfileString
  42.             (_T("Configure"), _T("SendTo"), _T(""));
  43.     m_strStatusLine = AfxGetApp()->GetProfileString
  44.             (_T("Configure"), _T("StatusText"), _T(""));
  45.     m_bMailOnEach = (BOOL)(AfxGetApp()->GetProfileInt
  46.             (_T("Configure"), _T("MailOnEach"), 1));
  47.     m_bIncBuildResults = (BOOL)(AfxGetApp()->GetProfileInt
  48.             (_T("Configure"), _T("IncludeBuildResults"), 1));
  49.     m_bSendFile = (BOOL)(AfxGetApp()->GetProfileInt
  50.             (_T("Configure"), _T("SendFile"), 0));
  51.     m_strFileToSend = AfxGetApp()->GetProfileString
  52.             (_T("Configure"), _T("FileToSend"));
  53.     m_bCloseWhenDone = (BOOL)(AfxGetApp()->GetProfileInt
  54.             (_T("Configure"), _T("CloseWhenDone"), 0));
  55.  
  56.     //If the user wishes to send mail when all building is complete, a
  57.     //  running count of the number of Warnings/Errors is needed
  58.     m_nTotalErrors = 0;
  59.     m_nTotalWarnings = 0;
  60. }
  61.  
  62. CCommands::~CCommands()
  63. {
  64.     ASSERT (m_pApplication != NULL);
  65.     m_pApplication->Release();
  66. }
  67.  
  68. void CCommands::SetApplicationObject(IApplication* pApplication)
  69. {
  70.     // This function assumes pApplication has already been AddRef'd
  71.     //  for us, which CDSAddIn did in its QueryInterface call
  72.     //  just before it called us.
  73.     m_pApplication = pApplication;
  74.  
  75.     // Create Application event handlers
  76.     XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
  77.     m_pApplicationEventsObj->AddRef();
  78.     m_pApplicationEventsObj->Connect(m_pApplication);
  79.     m_pApplicationEventsObj->m_pCommands = this;
  80.  
  81.     // Create Debugger event handler
  82.     CComPtr<IDispatch> pDebugger;
  83.     if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger))
  84.         && pDebugger != NULL)
  85.     {
  86.         XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
  87.         m_pDebuggerEventsObj->AddRef();
  88.         m_pDebuggerEventsObj->Connect(pDebugger);
  89.         m_pDebuggerEventsObj->m_pCommands = this;
  90.     }
  91. }
  92.  
  93. void CCommands::UnadviseFromEvents()
  94. {
  95.     ASSERT (m_pApplicationEventsObj != NULL);
  96.     m_pApplicationEventsObj->Disconnect(m_pApplication);
  97.     m_pApplicationEventsObj->Release();
  98.     m_pApplicationEventsObj = NULL;
  99.  
  100.     if (m_pDebuggerEventsObj != NULL)
  101.     {
  102.         // Since we were able to connect to the Debugger events, we
  103.         //  should be able to access the Debugger object again to
  104.         //  unadvise from its events (thus the VERIFY_OK below--see stdafx.h).
  105.         CComPtr<IDispatch> pDebugger;
  106.         VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
  107.         ASSERT (pDebugger != NULL);
  108.         m_pDebuggerEventsObj->Disconnect(pDebugger);
  109.         m_pDebuggerEventsObj->Release();
  110.         m_pDebuggerEventsObj = NULL;
  111.     }
  112. }
  113.  
  114.  
  115. /////////////////////////////////////////////////////////////////////////////
  116. // Event handlers
  117.  
  118. // TODO: Fill out the implementation for those events you wish handle
  119. //  Use m_pCommands->GetApplicationObject() to access the Developer
  120. //  Studio Application object
  121.  
  122. // Application events
  123.  
  124. HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
  125. {
  126.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  127.     return S_OK;
  128. }
  129.  
  130. HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
  131. {
  132.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  133.  
  134.     m_pCommands->m_bBuildInProgres = FALSE;
  135.  
  136.     if (m_pCommands->m_bAutoBuilding == TRUE) //See comment in the constructor
  137.     {
  138.         //here we create a mail message, and send it off...
  139.         if ((m_pCommands->m_bSendMail == TRUE) &&
  140.             (m_pCommands->m_bMailOnEach == TRUE))
  141.         {
  142.  
  143.             HINSTANCE hInstMail = ::LoadLibrary("MAPI32.DLL");
  144.             if (hInstMail != NULL)
  145.             {
  146.                 ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*,
  147.                     FLAGS, ULONG);
  148.                 (FARPROC&)lpfnSendMail = GetProcAddress(hInstMail,
  149.                     "MAPISendMail");
  150.                 if (lpfnSendMail != NULL)
  151.                 {
  152.                     MapiMessage message;
  153.                     memset((void*)&message, 0, sizeof(message));
  154.                     message.lpszSubject = const_cast<LPTSTR>
  155.                             ((LPCSTR)m_pCommands->m_strStatusLine);
  156.                     CString strErrWarnCStr;
  157.                     if (m_pCommands->m_bIncBuildResults == TRUE)
  158.                     {
  159.                         CString strErrWarnText;
  160.                         strErrWarnText.Format(IDS_ERRWARNTEXT, nNumErrors,
  161.                                 nNumWarnings);
  162.                         strErrWarnCStr = CString(message.lpszSubject) +
  163.                                 strErrWarnText;
  164.                         message.lpszSubject = const_cast<LPTSTR>
  165.                                 ((LPCSTR)strErrWarnCStr);
  166.                     }
  167.                     CString strToMail;
  168.                     if (m_pCommands->m_bSendFile == FALSE)
  169.                     {
  170.                         strToMail.Format(IDS_DEFAULTMAILBODY,
  171.                                 m_pCommands->m_strBuildingConfigurationName);
  172.                     }
  173.                     else
  174.                     {
  175.                         CString strResult;
  176.                         CStdioFile fileTextToMail;
  177.                         try
  178.                         {
  179.  
  180.                             fileTextToMail.Open(m_pCommands->m_strFileToSend,
  181.                                     CFile::modeRead | CFile::typeText);
  182.                             DWORD dwFileSize = fileTextToMail.GetLength();
  183.                             dwFileSize = fileTextToMail.Read(
  184.                                     strResult.GetBuffer(dwFileSize), dwFileSize);
  185.                             strResult.ReleaseBuffer(dwFileSize);
  186.                             CString strLocal;
  187.                             strLocal.Format(strResult,
  188.                                     m_pCommands->m_strBuildingConfigurationName,
  189.                                     nNumErrors, nNumWarnings);
  190.                             strToMail = strLocal;
  191.                         }
  192.                         catch (...) //If some problem occurrs when working
  193.                                     //  with the file, just send the default
  194.                                     //  message body
  195.                         {
  196.                             if (m_pCommands->m_bTesting == TRUE)
  197.                                 AfxMessageBox(IDS_WARNSENDDEF);
  198.                             strToMail.Format(IDS_DEFAULTMAILBODY,
  199.                                 m_pCommands->m_strBuildingConfigurationName);
  200.                         }
  201.                     }
  202.                     message.lpszNoteText = const_cast<LPTSTR>((LPCSTR)strToMail);
  203.                     message.nRecipCount = 1;
  204.                     message.lpRecips = new MapiRecipDesc;
  205.                     memset(message.lpRecips, 0, sizeof(MapiRecipDesc));
  206.                     message.lpRecips->ulRecipClass = MAPI_TO;
  207.                     CString strTemp2 = CString("SMTP:") + m_pCommands->m_strSendTo;
  208.                     message.lpRecips->lpszName = const_cast<LPTSTR>
  209.                             ((LPCSTR)m_pCommands->m_strSendTo);
  210.                     message.lpRecips->lpszAddress = const_cast<LPTSTR>
  211.                             ((LPCSTR)strTemp2);
  212.  
  213.                     int error = lpfnSendMail(0, (ULONG)0, &message, 0, 0);
  214.  
  215.                     //error is not handled, because you really don't want to
  216.                     //  pop up a message box. Putting up a message box would
  217.                     //  suspend other pending builds until somebody would
  218.                     //  manually click the OK button. You may wish to place
  219.                     //  some sort of logging here, so that the error would be
  220.                     //  dumped to a file.
  221.  
  222.                     // The reason you might get an error is because your email
  223.                     // may require a password. You can log into your email account first,
  224.                     // or create an account that doesn't require a password.
  225.  
  226.                     if (error != SUCCESS_SUCCESS)
  227.                     {
  228.                         if (m_pCommands->m_bTesting == TRUE)
  229.                         {
  230.                             AfxMessageBox(IDS_MAPIERROR);
  231.  
  232.                         }
  233.                         else
  234.                         {
  235.                             // log some other kind of error in a log file
  236.                         }
  237.                     }
  238.  
  239.                     delete message.lpRecips;
  240.                 }
  241.             ::FreeLibrary(hInstMail);
  242.             }
  243.         }
  244.     }
  245.     m_pCommands->m_nTotalErrors += nNumErrors;
  246.     m_pCommands->m_nTotalWarnings += nNumWarnings;
  247.     return S_OK;
  248. }
  249.  
  250. HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
  251. {
  252.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  253.     return S_OK;
  254. }
  255.  
  256. HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch* theDocument)
  257. {
  258.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  259.     return S_OK;
  260. }
  261.  
  262. HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch* theDocument)
  263. {
  264.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  265.     return S_OK;
  266. }
  267.  
  268. HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch* theDocument)
  269. {
  270.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  271.     return S_OK;
  272. }
  273.  
  274. HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch* theDocument)
  275. {
  276.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  277.     return S_OK;
  278. }
  279.  
  280. HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch* theWindow)
  281. {
  282.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  283.     return S_OK;
  284. }
  285.  
  286. HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch* theWindow)
  287. {
  288.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  289.     return S_OK;
  290. }
  291.  
  292. HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
  293. {
  294.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  295.     return S_OK;
  296. }
  297.  
  298. HRESULT CCommands::XApplicationEvents::WorkspaceClose()
  299. {
  300.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  301.     return S_OK;
  302. }
  303.  
  304. HRESULT CCommands::XApplicationEvents::NewWorkspace()
  305. {
  306.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  307.     return S_OK;
  308. }
  309.  
  310. // Debugger event
  311.  
  312. HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch* pBreakpoint)
  313. {
  314.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  315.     return S_OK;
  316. }
  317.  
  318.  
  319. /////////////////////////////////////////////////////////////////////////////
  320. // CCommands methods
  321.  
  322. STDMETHODIMP CCommands::AutoBuildTest()
  323. {
  324.     // don't allow more than one test to go.
  325.     if (m_bBuildInProgres)
  326.         return S_OK;
  327.  
  328.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  329.  
  330.     m_pApplication->EnableModeless(VARIANT_FALSE);
  331.     m_nTotalErrors = 0;
  332.     m_nTotalWarnings = 0;
  333.  
  334.     m_bAutoBuilding = TRUE;    //See comment in the constructor
  335.     m_bBuildInProgres = TRUE;  //See comment in the constructor
  336.  
  337.     long lCount;
  338.     int nNumWorkspaces = AfxGetApp()->GetProfileInt(_T("Configure"),
  339.             _T("NumWorkspaces"), 0);
  340.  
  341.     for (int nWorkspaceNumber = 1 ; nWorkspaceNumber <= nNumWorkspaces ;
  342.             nWorkspaceNumber++)
  343.     {
  344.         char RegKey[50];
  345.         wsprintf(RegKey, "Workspace%d", nWorkspaceNumber-1);
  346.         CComBSTR bszWorkspacePathName = AfxGetApp()->GetProfileString(
  347.                     _T("Configure"), RegKey, "");
  348.  
  349.         CComPtr<IDispatch> pDispDocuments;
  350.         VERIFY_OK(m_pApplication->get_Documents(&pDispDocuments));
  351.  
  352.         CComVariant OleVariant; //By default, the type is VT_EMPTY
  353.  
  354.         CComQIPtr<IDocuments, &IID_IDocuments> pDocuments(pDispDocuments);
  355.  
  356.         CComPtr<IDispatch> pWorkspace;  //Never gets used except in:
  357.         VERIFY_OK(pDocuments->Open(bszWorkspacePathName, OleVariant,
  358.                                         OleVariant, &pWorkspace));
  359.  
  360.         //First, get a pointer to the dispatch for the Projects collection
  361.         CComPtr<IDispatch> pDispProjects;
  362.         // clean out the output files from and old build.
  363.  
  364.         VERIFY_OK(m_pApplication->get_Projects(&pDispProjects));
  365.         CComQIPtr<IProjects, &IID_IProjects> pProjects(pDispProjects);
  366.         //Get the number of projects in the collection
  367.         VERIFY_OK(pProjects->get_Count(&lCount));
  368.         for (long i = 1 ; i < lCount+1 ; i++)
  369.         {
  370.             long lNumConfigs;
  371.             CComVariant Vari = i;
  372.  
  373.             //Get the next project
  374.             CComPtr<IGenericProject> pGenProject;
  375.             VERIFY_OK(pProjects->Item(Vari, &pGenProject));
  376.             CComQIPtr<IBuildProject, &IID_IBuildProject> pProject(pGenProject);
  377.             //Each project has a configuration (Win32 Release, Win32 Debug,
  378.             //  etc.), get the collection of these configurations
  379.             CComPtr<IConfigurations> pConfigs;
  380.             VERIFY_OK(pProject->get_Configurations(&pConfigs));
  381.             VERIFY_OK(pConfigs->get_Count(&lNumConfigs));
  382.             for (long j = 1 ; j < lNumConfigs+1 ; j++)
  383.             {
  384.                 CComVariant Varj = j;
  385.                 //Get each individual configuration
  386.                 CComPtr<IConfiguration> pConfig;
  387.                 VERIFY_OK(pConfigs->Item(Varj, &pConfig));
  388.  
  389.                 CComVariant VarDisp = pConfig;
  390.                 CComBSTR bszStr;
  391.                 VERIFY_OK(pConfig->get_Name(&bszStr));
  392.                 if (m_bMailOnEach == TRUE)
  393.                     m_strBuildingConfigurationName = bszStr;
  394.                 else
  395.                     m_strBuildingConfigurationName += CString(", ") +
  396.                             CString(bszStr);
  397.                 //Build this particular
  398.                 //  configuration, in this project,
  399.                 //  in this Workspace...
  400.                 VERIFY_OK(m_pApplication->Build(VarDisp));
  401.             }
  402.         }
  403.     }
  404.     if (m_bMailOnEach == FALSE)
  405.     {
  406.         //We only wish to send mail when everything is built.
  407.         //  to do this, we just say "from now on we are sending Mail on each
  408.         //  configuration build"
  409.         m_bMailOnEach = TRUE;
  410.         //  then manually call the BuildFinish event, as if a configuration is
  411.         //  done, but this "Configuration" is the entire project
  412.         ASSERT(m_pApplicationEventsObj != NULL);
  413.         m_pApplicationEventsObj->BuildFinish(m_nTotalErrors, m_nTotalWarnings);
  414.         //Reset MailOnEach
  415.         m_bMailOnEach = FALSE;
  416.     }
  417.  
  418.     m_bAutoBuilding = FALSE;    //See comment in the constructor
  419.  
  420.     m_pApplication->EnableModeless(VARIANT_TRUE);
  421.  
  422.     if (m_bTesting == FALSE)
  423.     {
  424.         if (m_bCloseWhenDone == TRUE)
  425.             VERIFY_OK(m_pApplication->Quit());
  426.     }
  427.     else
  428.     {
  429.         if (m_bCloseWhenDone == TRUE)
  430.             AfxMessageBox(IDS_WARNEXIT);
  431.     }
  432.     return S_OK;
  433. }
  434.  
  435. STDMETHODIMP CCommands::AutoBuild()
  436. {
  437.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  438.     m_bTesting = FALSE;
  439.     AutoBuildTest();
  440.     m_bTesting = TRUE;
  441.  
  442.     return S_OK;
  443. }
  444.  
  445. STDMETHODIMP CCommands::AutoBuildConfigure()
  446. {
  447.     AFX_MANAGE_STATE(AfxGetStaticModuleState());
  448.  
  449.     m_pApplication->EnableModeless(VARIANT_FALSE);
  450.  
  451.     CConfigure AutoBuildConfigDlg;
  452.     // stuff all the pre read data values in the dialog before
  453.     // showing it
  454.     AutoBuildConfigDlg.m_bSendMail      = m_bSendMail;
  455.     AutoBuildConfigDlg.m_bCloseWhenDone = m_bCloseWhenDone;
  456.     AutoBuildConfigDlg.m_bMailOnEach    = m_bMailOnEach;
  457.     AutoBuildConfigDlg.m_bIncBuildResults = m_bIncBuildResults;
  458.     AutoBuildConfigDlg.m_bSendFile      = m_bSendFile;
  459.     AutoBuildConfigDlg.m_strFileToSend  = m_strFileToSend;
  460.     AutoBuildConfigDlg.m_strStatusLine  = m_strStatusLine;
  461.     AutoBuildConfigDlg.m_strSendTo      = m_strSendTo;
  462.  
  463.     AutoBuildConfigDlg.DoModal();
  464.     // get the data values back.
  465.     m_bSendMail = AutoBuildConfigDlg.m_bSendMail;
  466.     m_bCloseWhenDone = AutoBuildConfigDlg.m_bCloseWhenDone;
  467.     m_bMailOnEach = AutoBuildConfigDlg.m_bMailOnEach;
  468.     m_bIncBuildResults = AutoBuildConfigDlg.m_bIncBuildResults;
  469.     m_bSendFile = AutoBuildConfigDlg.m_bSendFile;
  470.     m_strFileToSend = AutoBuildConfigDlg.m_strFileToSend;
  471.     m_strStatusLine = AutoBuildConfigDlg.m_strStatusLine;
  472.     m_strSendTo = AutoBuildConfigDlg.m_strSendTo;
  473.  
  474.     m_pApplication->EnableModeless(VARIANT_TRUE);
  475.  
  476.     return S_OK;
  477. }
  478.