Re: Init COM interfaces
 
Wow, thanks Alf for the help.
but mine main problem was the following line of your code:
WordAppObject   wordApp;
i.e. I didn't know the type of my COM (WordAppObject in you case).
Thanks for your concern and time,
Alex
On Apr 2, 4:09 pm, "Alf P. Steinbach" <al...@start.no> wrote:
* Alex:
The only documentation I have is some example in VB:
Dim oI As Object
oI = CreateObject("SomeCOM.SomeInterface")
oI.Init()
[snip]
  > But this VB example doesn't give me any idea about this COM class
name.  So my question is - do I have to ask this COM distributors for
some additional information - Interface Classes/Namespaces, GUIDs...?
Or something can be done just knowing that this COM object was
registered and ProgID is "SomeCOM.SomeInterface" ?
Well you have already solved the problem and got good advice.
But I was inspired by your question to do a bit of coding, it's so long ag=
o!
So herewith, the most (well, OK, at least a very) inefficient way to outpu=
t the
text "Microsoft Word".  Perhaps this can be useful to someone else, even=
 if the
functionality and error handling etc. is rather incomplete.  And perhaps=
 I or
others can learn something from comments about how to do this in an easier=
 way
(of course not using type lib, since that's the point) or errors, whatever=
..
Cheers,
- Alf
<output comment="After a little waiting period... :-)">
     Microsoft Word
</output>
<code filename="main.cpp">
#include    <cassert>
#include    <iostream>
#include    <ostream>
#include    <stdexcept>
#include    <string>
#include    "OleAutomationObject.hpp"
bool throwX( char const s[] ) { throw std::runtime_error( s ); }
class WordAppObject: public alfs::OleAutomationObject
{
private:
     void quit()
     {
         try
         {
             call( L"Quit", 3 );     // 3 defaulted argu=
ments.
         }
         catch( std::exception const& )
         {
             assert( "Word application object failed to quit=
" && 0 );
             std::abort();
         }
     }
public:
     WordAppObject(): alfs::OleAutomationObject( L"Word.Application"=
 ) {}
     ~WordAppObject() { quit(); }
     std::wstring name() const { return getAsStdString( L"Name" ); }=
};
struct ComUsage
{
     ComUsage()
     {
         (SUCCEEDED( CoInitialize(0) )) || throwX( "CoInitialize=
 failed" );
     }
     ~ComUsage() { CoUninitialize(); }
};
void cppMain()
{
     ComUsage        com;
     WordAppObject   wordApp;
     std::wcout << wordApp.name() << std::endl;
}
int main()
{
     try
     {
         cppMain();
         return EXIT_SUCCESS;
     }
     catch( std::exception const& x )
     {
         std::cerr << "!" << x.what() << std::endl;
         return EXIT_FAILURE;
     }}    // main
</code>
<code filename="OleAutomationObject.hpp">
#ifndef OLE_AUTOMATION_OBJECT
#define OLE_AUTOMATION_OBJECT
#include    "wrapper/windows_h.h"
#include    <ole2.h>            // IDispatch
#include    <comdef.h>          // _com_ptr_t, _variant_t, _=
bstr_t
#include    <vector>
#include    <stdexcept>
#include    <string>
namespace alfs
{
     namespace detail
     {
         // Exception helper, should really be in a file of its =
own:
         bool throwX( char const s[] ) { throw std::runtime_erro=
r( s ); }
         std::string narrow( wchar_t const wide[] )
         {
             std::string result( 2*wcslen(wide), '\0' );
             size_t const n = wcstombs( &result[0], wide, =
result.size() );
             (n != size_t(-1)) || throwX( "alfs::narrow: f=
ailed" );
             result.resize( n );
             return result;
         }
         bool throwHRX( char const s[], HRESULT hr )
         {
             throw std::runtime_error( s + narrow( _com_erro=
r( hr
).ErrorMessage() ) );
         }
         _COM_SMARTPTR_TYPEDEF( IDispatch, __uuidof(IDispatch) )=
;    // IDispatchPtr
     }    // namespace detail
     class DispatchParams
     {
     private:
         std::vector<VARIANTARG> myArgValues;
         std::vector<DISPID>     myNamedArgIds;
         DISPPARAMS              myParams;
     public:
         static VARIANTARG defaultParam()
         {
             VARIANTARG v = {};
             v.vt = VT_ERROR;
             v.scode = DISP_E_PARAMNOTFOUND;
             return v;
         }
         DispatchParams( int nParameters )
             : myArgValues( nParameters == 0? 1 : nParam=
eters, defaultParam() )
             , myNamedArgIds( 1 )
         {
             myParams.rgvarg             = &my=
ArgValues[0];
             myParams.rgdispidNamedArgs  = &myNamedArgId=
s[0];
             myParams.cArgs              = n=
Parameters;
             myParams.cNamedArgs         = 0;
         }
         DISPPARAMS* ptr() { return &myParams; }
     };
     class OleAutomationObject
     {
     private:
         detail::IDispatchPtr    myDispatch;
         enum CallTypeEnum
         {
             methodCall      = DISPATCH_METHOD,
             propertyGet     = DISPATCH_PROPERTYGET,
             propertyPut     = DISPATCH_PROPERTYPUT,
             propertyPutRef  = DISPATCH_PROPERTYPUTREF
         };
         _variant_t invokeAs(
             CallTypeEnum        callType,
             wchar_t const       name[],
             DispatchParams&     params
             ) const
         {
             using namespace detail;
             EXCEPINFO       exceptionInfo      =
 = {};
             _variant_t      returnValue;
             unsigned        erronousArgIndex   =
 = 0;
             DISPID const dispId = dispIdOf( name );
             HRESULT const hr = myDispatch->Invoke(
                 dispId,
                 IID_NULL,           // reserv=
ed
                 0,                  /=
/ locale id
                 static_cast<WORD>( callType ),
                 params.ptr(),
                 &returnValue,       // VARIANT FA=
R*  pVarResult
                 &exceptionInfo,     // EXCEPINFO FA=
R*  pExcepInfo
                 &erronousArgIndex
                 );
             (SUCCEEDED( hr )) || throwHRX( "OleAutomationOb=
ject: Invoke: ", hr );
             return returnValue;
         }
     public:
         OleAutomationObject( wchar_t const progId[], DWORD serv=
erType =
CLSCTX_ALL )
             : myDispatch( progId, 0, serverType )
         {
             using namespace detail;
             (myDispatch != 0) || throwX( "OleAutomationOb=
ject::<init> failed" );
         }
         DISPID dispIdOf( wchar_t const name[] ) const
         {
             using namespace detail;
             DISPID  dispId  = 0;
             HRESULT const hr = myDispatch->GetIDsOfNames(=
                 IID_NULL,           // reserv=
ed
                 const_cast<wchar_t**>( &name ),
                 1,                  /=
/ count of names
                 0,                  /=
/ locale id
                 &dispId
                 );
             (SUCCEEDED( hr )) ||
                 throwHRX( "OleAutomationObject::dispIdO=
f: GetIDsOfNames: ", hr );
             return dispId;
         }
         _variant_t call( wchar_t const methodName[], DispatchPa=
rams& params )
         {
             return invokeAs( methodCall, methodName, params=
 );
         }
         _variant_t call( wchar_t const methodName[], int nArgs =
)
         {
             DispatchParams  params( nArgs );
             return call( methodName, params );
         }
         _variant_t get( wchar_t const propertyName[] ) const
         {
             // E.g. WordApp.Name requires non-zero arg poin=
ters.  Silly.
             DispatchParams  params( 0 );
             return invokeAs( propertyGet, propertyName, par=
ams );
         }
         _bstr_t getAsBString( wchar_t const propertyName[] ) co=
nst
         {
             return get( propertyName );
         }
         std::wstring getAsStdString( wchar_t const propertyName=
[] ) const
         {
             return getAsBString( propertyName ).operator wc=
har_t const*();
         }
     };
}
#endif
</code>