2
\$\begingroup\$

In this code, I am creating a COM object to programatically access internet explorer. In order to access this object's properties and methods, I am writing wrapper functions like navigate or setVisible.

Is there a cleaner or easier way to use COM objects from C? Moreover, can you point out things that I could have done better?

#include <stdio.h>
#include <windows.h>

HRESULT createIE(LPVOID *pDisp)
{
    CLSID clsid;
    HRESULT hr;
    hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsid);
    if(FAILED(hr)) {
       MessageBox(NULL, "Internet Explorer not registered.", "Error",
                  MB_SETFOREGROUND);
       return hr;
    }


    hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER,
                          &IID_IDispatch, pDisp);

    if(FAILED(hr)) {
       MessageBox(NULL, "Couldn't start Internet Explorer.", "Error",
                  MB_SETFOREGROUND);
       return hr;
    }

    return S_OK;
}

HRESULT navigate(IDispatch *pDisp, BSTR *url)
{
    HRESULT hr;
    DISPID dispID;
    VARIANT parm1;

    DISPPARAMS dispParams = { NULL, NULL, 0, 0 };

    LPOLESTR rgszNames[1] = {L"Navigate"};

    pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispID);

    VariantInit(&parm1);
    parm1.vt = VT_BSTR;
    parm1.pbstrVal = url;

    // One argument.
    dispParams.cArgs = 1;
    dispParams.rgvarg = &parm1;

    // Navigate to url
    hr = pDisp->lpVtbl->Invoke(pDisp,
       dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
       &dispParams, NULL, NULL, NULL
    );

    if (FAILED(hr)) {
       char buf[8192];
       sprintf(buf, "IDispatch::Invoke() failed with %08lx", hr);
       MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
       return hr;
    }

    return S_OK;
}

HRESULT setVisible(IDispatch *pDisp, BOOL visibility)
{
    HRESULT hr;
    DISPID dispID;

    DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
    VARIANT parm1;
    DISPID dispidNamed = DISPID_PROPERTYPUT;

    LPOLESTR rgszNames[1] = {L"Visible"};

    pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispID);

    VariantInit(&parm1);
    parm1.vt = VT_I4;
    parm1.lVal = visibility;

    // One argument.
    dispParams.cArgs = 1;
    dispParams.rgvarg = &parm1;

    // Handle special-case for property-puts!
    dispParams.cNamedArgs = 1;
    dispParams.rgdispidNamedArgs = &dispidNamed;

    // Set 'visible' property
    hr = pDisp->lpVtbl->Invoke(pDisp,
       dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
       DISPATCH_PROPERTYPUT | DISPATCH_METHOD,
       &dispParams, NULL, NULL, NULL
    );

    if(FAILED(hr)) {
        char buf[8192];
       sprintf(buf, "IDispatch::Invoke() failed with %08lx", hr);
       MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
       return hr;
    }

    return S_OK;
}

void main(void) {
     IDispatch *pDisp; // Main IDispatch pointer.
     HRESULT hr; // General error/result holder.



    // Initialize OLE Libraries.
    OleInitialize(NULL);

    hr = createIE((void **)&pDisp);

    if (FAILED(hr)) {
            return;
    }

    hr = setVisible(pDisp, TRUE);

    if (FAILED(hr)) {
        return;
    }

    BSTR url = SysAllocString(L"www.google.com");
    hr = navigate(pDisp, url);

    if (FAILED(hr)) {
        return;
    }

     // Uninitialize OLE Libraries.
     OleUninitialize();

}
\$\endgroup\$
  • \$\begingroup\$ You can get IWebBrowser2 instead IDispatch. \$\endgroup\$ – user88359 Oct 30 '15 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.