C++ Automation Example

From SysCAD Documentation
Jump to navigation Jump to search

Navigation: User Guide -> COM Automation -> C++ Automation Example

Below is a C++ source code that can be compiled to a console application. The example is similar to the Excel VBA Automation example.

Example

// SysCAD93Console.cpp : This file contains the 'main' function. Program execution begins and ends there.

#include "pch.h"
#include <iostream>
#include <string>

#import "ScdSlv93.tlb"
#import "SysCAD93.tlb" named_guids

void UsualExample()
 {
 HRESULT hRes;
 SysCAD93::IScdApplicationPtr pSysCAD = nullptr;
 SysCAD93::IScdProjectPtr pPrj = nullptr;
 SysCAD93::IScdAppTagsPtr pTags = nullptr;
 SysCADSolver93::IScdSolverPtr pSlv = nullptr;
 SysCADSolver93::IScdProbalPtr pProBal = nullptr;

 //== Set the project name to be loaded..
 _bstr_t bstrScenarionPath = L"c:\\SysCAD138\\Examples\\40 Nickel\\Demo Nickel Copper Project.spf\\";
 _bstr_t bstrScenarionProject = bstrScenarionPath + L"project.spj";

 //== TODO: Test if the project file exists

 try
   {
   //== Start SysCAD..
   std::cout << "Start SysCAD\n";
   hRes = pSysCAD.CreateInstance(SysCAD93::CLSID_ScdApplication);
   if (hRes!=S_OK)
     {
     std::cout << "Start SysCAD failed.  (Run RegAll or ???)\n";
     return;
     }

   //== Get the version number
   std::string VersionStr;
   const long BuildMajor = pSysCAD->VersionNumber[2];
   const long BuildMinor = pSysCAD->VersionNumber[3];
   VersionStr = "SysCAD " + std::to_string(pSysCAD->VersionNumber[0]) + "." + std::to_string(pSysCAD->VersionNumber[1])
     + " Build " + std::to_string(BuildMajor) + "." + std::to_string(BuildMinor);
   std::cout << "Started " << VersionStr << "\n";

   //== Test Build number, and Exit if Build number is less than required Build
   const long RequiredBuildMajor = 138;
   const long RequiredBuildMinor = 23938;
   if (BuildMajor < RequiredBuildMajor || RequiredBuildMinor < RequiredBuildMinor)
     {
     std::cout << "Version " << VersionStr << "is too old.  Require Build " << std::to_string(RequiredBuildMajor) << "." << std::to_string(RequiredBuildMinor) << " or newer!\n";
     pSysCAD.Release(); //Close SysCAD
     return;
     }

   //== TODO: Test if a valid steady state license is available. If not Exit.

   //== Open the project..
   std::cout << "Open project\n";
   pPrj = pSysCAD->OpenProject(bstrScenarionProject);
   if (pPrj)
     {
     //== Get a reference to the objects of interest..
     pTags = pPrj->GetTags();
     pSlv = pPrj->GetSolver();
     pProBal = pSlv->GetProbal();

     //== Example of setting a tag in SysCAD..
     //std::cout << "Set a Tag (PlantModel.EqpDesc)\n";
     pTags->put_TagValue(_bstr_t("PlantModel.EqpDesc"), _variant_t(L"Test"));

     //== Example of retrieving a tag from SysCAD..
     //std::cout << "Get a Tag (PlantModel.System.Version)\n";
     _variant_t VersionDesc;
     pTags->get_TagValue(_bstr_t("PlantModel.System.Version"), &VersionDesc);
     std::cout << "PlantModel.System.Version = " << (_bstr_t)VersionDesc << "\n";

     //----------------------------------------------------------
     //== Next section of code starts the ProBal solver and then loops waiting
     //   for the model to converge. The use of Sleep is important because this
     //   gives CPU access to other applications (ie SysCAD).

     const long MaxLoop = 5000; //maximum number of loops before giving up

     //== Start the ProBal solver..
     std::cout << "Start Solver\n";
     pProBal->Start();
     Sleep(500); //give SysCAD a chance to get started

     std::cout << "Busy Solving";
     long i;
     for (i = 1; i<MaxLoop; i++)
       {
       std::cout << ".";
       //== Wait for 1 second before checking if solved
       Sleep(1000); //"sleep" for one second ( 1000 milliseconds )
       //== Check if solver has stopped..
       if (pProBal->IsStopped)
         {
         break; //ProBal solver has stopped, exit the loop
         }
       }
     std::cout << "\n";

     //== Retrieve the number of iterations to solve
     _variant_t Val;
     pTags->get_TagValue(_bstr_t("PlantModel.Stats.Iterations"), &Val);
     const long Iter = Val;

     if (i==MaxLoop)
       {
       //We did not manage to solve within MaxLoop iterations
       //Bomb out and let user know
       std::cout << "Stop ProBal solver after " << std::to_string(Iter) << " iterations.\n";
       pProBal->Stop();
       }
     else
       {
       //Model solved and stopped correctly
       //== Retrieve the solve time and display as a message
       pTags->get_TagValue(_bstr_t("PlantModel.Stats.SolveTimeDesc"), &Val);
       std::cout << "ProBal solve iterations:" << std::to_string(Iter) << "    SolveTime:" << (_bstr_t)Val << "\n";
       }

     //== Save Scenario
     std::cout << "Save Scenario\n";
     pPrj->SaveScenario("Case001");

     //== Close the SysCAD project without saving the changes
     std::cout << "Close Project\n";
     pSysCAD->CloseProject(VARIANT_FALSE);

     //== To ensure that SysCAD exits correctly, ensure ALL referenced objects are released..
     pProBal.Release();
     pTags.Release();
     pSlv.Release();
     pPrj.Release();
     }
   else
     {
     std::cout << "Open project Failed!\n";
     }

   std::cout << "Release Final\n";
   if (pSysCAD)
     pSysCAD.Release();
   }
 catch (...)
   {
   // Manually release all interfaces
   pProBal.Release();
   pTags.Release();
   pSlv.Release();
   pPrj.Release();
   std::cout << "Release Final\n";
   if (pSysCAD)
     pSysCAD.Release();
   }
 }

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

int main()
 {
 std::cout << "testing SysCAD 9.3 COM Automation...\n"; 
 CoInitialize(nullptr);
 UsualExample();
 std::cout << "Done\n";
 CoUninitialize();
 }
//================================================================================