VOLE is an open-source C++ library that dramatically simplifies the business of driving
COM servers (via the IDispatch interface) from C++.
VOLE is highly robust.
VOLE is very flexible, taking and returning normal C++ types,
such as int, double, std::string,
std::wstring, and so on.
VOLE is 100% header only.
VOLE is compiler-independent, and has been verified to work with the
following compilers:
1. This code creates an instance of pantheios.COM.LoggerManager, then obtains from it an instance of the Console logger, and then logs a simple message to it, obtains a couple of properties from it, and then logs another message.
using vole::object;
object loggerManager = object::create("pantheios.COM.LoggerManager");
object logger = loggerManager.invoke_method<object>(L"GetLogger", L"Console", L"VOLE pantheios.COM test");
logger.invoke_method<void>(L"Log", 3, L"The answer is: ", 43);
std::string processId = logger.get_property<std::string>(L"ProcessIdentity");
long backEndId = logger.get_property<long>(L"BackEndId");
logger.invoke_method<void>(L"Log", 4, "abc(", L"DEF", "): ", 2319, " - ", 19.19, L" - ", std::string("yada!").c_str());
2. This code drives use the openrj.COM server to open a Record-JAR database file and enumerate its contents:
#include <vole/vole.hpp>
#include <comstl/error/errorinfo_desc.hpp>
#include <comstl/util/initialisers.hpp>
int main(int argc, char *argv[])
{
using std::cout;
using std::cerr;
using std::endl;
try
{
comstl::com_init init;
if(argc < 2)
{
cout << "USAGE: openrj.com.text.exe <db-file>" << endl;
}
else
{
using vole::object;
using vole::collection;
// Create the COM server, via its ProgID "openrj.COM.database"
char const *dbFile = argv[1];
collection db = object::create("openrj.COM.database");
// Open the given file
db.invoke_method<void>(L"OpenFile", dbFile);
// Use the collection::Count property to get the number of records
// in the database file, and access the File property via
// object::get_property<>()
long numRecords = db.Count;
std::string fileName = db.get_property<std::string>(L"File");
cout << "Database in file '" << fileName << "' contains " << numRecords << " record(s)" << endl;
// Enumerate through the records of the database, via the STL-compatible
// collection::iterator class, accessed through the
// collection::begin() and collection::end() methods
{ for(collection::iterator b = db.begin(); b != db.end(); ++b)
{
// "Convert" the returned VARIANT into a collection
collection record(*b);
long numFields = record.Count;
cout << " Record has " << numFields << " field(s)" << endl;
// Enumerate through the fields of the record, via the STL-compatible
// collection::iterator class, accessed through the
// collection::begin() and collection::end() methods
{ for(collection::iterator b2 = record.begin(); b2 != record.end(); ++b2)
{
// "Convert" the returned VARIANT into an object
object field(*b2);
// Access the Name and Value properties of the
// field, via object::get_property<>()
std::string name = field.get_property<std::string>(L"Name");
std::string value = field.get_property<std::string>(L"Value");
cout << " " << name << "=" << value << endl;
}}
}}
}
}
catch(vole::vole_exception &x)
{
cerr << x.what() << ": " << comstl::errorinfo_desc() << endl;
}
catch(std::exception &x)
{
cerr << x.what() << endl;
}
return 0;
}
3. This code creates use a commercial COM Component of Synesis Software to enumerate the NT Services on the host system:
using vole::object;
using std::endl;
using std::wcout;
object ServiceManager = object::create("SynesisSoftware.WindowsNt.ServiceManager");
long timeout = ServiceManager.get_property<long>(L"Timeout");
object Services = ServiceManager.get_property<object>(L"Services");
long numServices = Services.get_property<long>(L"Count");
{ for(long i = 0; i < numServices; ++i)
{
object Service = Services.get_property<object>(L"Item", i);
comstl::bstr ServiceName = Service.get_property<comstl::bstr>(L"ServiceName");
comstl::bstr DisplayName = Service.get_property<comstl::bstr>(L"DisplayName");
wcout << L"[" << ServiceName << L"] " << DisplayName << endl << endl;
}}