3
\$\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();
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Oct 10, 2015 at 12:03
\$\endgroup\$
1
  • \$\begingroup\$ You can get IWebBrowser2 instead IDispatch. \$\endgroup\$ Commented Oct 30, 2015 at 18:07

1 Answer 1

1
\$\begingroup\$

The code is very well written, and very clear, easy to maintain.

I am using a later version of Visual Studio Professional (Visual Studio 2019) and there are warning messages about all of the calls to MessageBox(), the strings need to be cast to the proper type.

Build started...
1>------ Build started: Project: COMie, Configuration: Debug Win32 ------
1>COMie.c
1>COMie.c(10,61): warning C4133: 'function': incompatible types - from 'char [34]' to 'LPCWSTR'
1>COMie.c(10,70): warning C4133: 'function': incompatible types - from 'char [6]' to 'LPCWSTR'
1>COMie.c(18,61): warning C4133: 'function': incompatible types - from 'char [34]' to 'LPCWSTR'
1>COMie.c(18,70): warning C4133: 'function': incompatible types - from 'char [6]' to 'LPCWSTR'
1>COMie.c(54,29): warning C4133: 'function': incompatible types - from 'char [8192]' to 'LPCWSTR'
1>COMie.c(54,45): warning C4133: 'function': incompatible types - from 'char [13]' to 'LPCWSTR'
1>COMie.c(96,29): warning C4133: 'function': incompatible types - from 'char [8192]' to 'LPCWSTR'
1>COMie.c(96,45): warning C4133: 'function': incompatible types - from 'char [13]' to 'LPCWSTR'
1>COMie.c(125,29): warning C4047: 'function': 'BSTR *' differs in levels of indirection from 'BSTR'
1>COMie.c(125,26): warning C4024: 'navigate': different types for formal and actual parameter 2
1>COMie.vcxproj -> COMie.exe
1>Done building project "COMie.vcxproj".
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

answered Mar 1, 2022 at 13:10
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.