I am new to COM, I am trying to create a simple c++ console Calendar app. Here is my code:
// CalendarProps.cpp
//
// DClient.cpp - Dispatch client implementation
// This client connects to the component "Êàëåíäàðü"
// through the dispinterface.
//
#include <windows.h>
#include <stdio.h>
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
#pragma region Create the component
//
DWORD clsctx;
clsctx = CLSCTX_INPROC_SERVER;
HRESULT hr = OleInitialize(NULL);
if (FAILED(hr))
{
printf("Failed to initialize Ole. Code %X \n", hr);//+
return 1;
}
// Get the CLSID for the application.
wchar_t progid1[] = L"MSCAL.Calendar.7";//ProgId - component Id
CLSID clsid;
hr = ::CLSIDFromProgID(progid1, &clsid);
if (FAILED(hr))
{
printf("Failed to get CLSID.Code %X \n", hr);//+
return 1;
}
// Create the component.
IDispatch* pIDispatch = NULL;
hr = ::CoCreateInstance(clsid,
NULL,
clsctx,
IID_IDispatch,
(void**)&pIDispatch);
if (FAILED(hr))
{
printf("Create instance failed.Code %X \n", hr);//+
OleUninitialize();
return 1;
}
printf("CoCreateInstance succeeded.\n");//+
#pragma endregion
#pragma region Get Day
printf("===============get Day==================\n");
// First we need to get the IDs for the function names.
printf("Get DispID for property \"Day\".\n");//+
DISPID dispid1;
OLECHAR* name1 = (OLECHAR*)L"Day";//*
hr = pIDispatch->GetIDsOfNames(IID_NULL,
&name1,
1,
GetUserDefaultLCID(),
&dispid1);
if (FAILED(hr))
{
printf("Query GetIDsOfNames failed. Code %X \n", hr);//+
pIDispatch->Release();
return 1;
}
// DISPPARAMS
DISPPARAMS param1;
param1.cArgs = 0; // Number of arguments
param1.rgvarg = NULL; // Arguments
param1.cNamedArgs = 0; // Number of named args
param1.rgdispidNamedArgs = NULL; // Named arguments
// "Day"
VARIANTARG varres1;
::VariantInit(&varres1); // Initialize the VARIANT
varres1.vt = VT_I2; // Type of VARIANT data
varres1.iVal = 0; // Data for the VARIANT
printf("Get property \"Day\".\n");//+
hr = pIDispatch->Invoke(dispid1,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_PROPERTYGET,
¶m1,
&varres1,//*
NULL,
NULL);
if (FAILED(hr))
{
printf("Invoke call failed.Code %X \n", hr);//+
pIDispatch->Release();
return 1;
}
// Display the returned Value//*
if (varres1.vt == VT_I2)//*
{
printf("Day from Calendar: %d", varres1.iVal);//+
}
printf("\n=========================================\n\n");
/////////////////////////////////////////////////////////
#pragma endregion
#pragma region Put Year
//HRESULT hr2 = OleInitialize(NULL);
printf("===============put Year==================\n");
// First we need to get the IDs for the function names.
printf("Get DispID for property \"Year\".\n");//+
DISPID dispid2;
OLECHAR* name2 = (OLECHAR*)L"Year";//*
hr = pIDispatch->GetIDsOfNames(IID_NULL,
&name2,
1,
GetUserDefaultLCID(),
&dispid2);
if (FAILED(hr))
{
printf("Query GetIDsOfNames failed.Code %X \n", hr);//+
pIDispatch->Release();
return 1;
}
// Allocate and initialize a VARIANT argument.
VARIANTARG vargs2;//*
::VariantInit(&vargs2); // Initialize the VARIANT.
vargs2.vt = VT_I2; // Type of VARIANT data
vargs2.iVal = 2023; // Data for the VARIANT
DISPID dispid = DISPID_PROPERTYPUT; // !!!!!!
DISPPARAMS param2;
param2.cArgs = 1; // Number of arguments
param2.rgvarg = &vargs2; // Arguments
param2.cNamedArgs = 1; // Number of named args !!!
param2.rgdispidNamedArgs = &dispid; // Named arguments !!!!
printf("Put the property \"Year\".\n");//+
hr = pIDispatch->Invoke(dispid2,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_PROPERTYPUT,
¶m2,
NULL,
NULL,
NULL);
if (FAILED(hr))
{
printf("Invoke call failed.Code %X \n", hr);//+
pIDispatch->Release();
return 1;
}
#pragma endregion
#pragma region Display the new Year value
// Display the new Year value
// DISPPARAMS Year
param2.cArgs = 0; // Number of arguments
param2.rgvarg = 0; // Arguments
param2.cNamedArgs = 0; // Number of named args
param2.rgdispidNamedArgs = 0; // Named arguments
VARIANTARG varres2;//*
::VariantInit(&varres2); // Initialize the VARIANT.//*
varres2.vt = VT_I2; // Type of VARIANT data//*
varres2.iVal = 0; // Data for the VARIANT//*
printf("Get the property \"Year\"\n");//+
hr = pIDispatch->Invoke(dispid2,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_PROPERTYGET,
¶m2,
&varres2,
NULL,
NULL);
if (FAILED(hr))
{
printf("Invoke call failed.Code %X \n", hr);
pIDispatch->Release();
return 1;
}
// Display the returned Year value
if (varres2.vt == VT_I2)
{
printf("Property Year in component Calendar: %d", vargs2.iVal);
}
printf("\n=========================================\n\n");
// Release the dispatch interface.
#pragma endregion
#pragma region Removing a Component
// Release the dispatch interface.
pIDispatch->Release();
// Uninitialize the OLE library.
OleUninitialize();
#pragma endregion
return 0;
}
I have create a reg.file with the stored ProdId and merged it successfully:
wchar_t progid1[] = L"MSCAL.Calendar.7";//ProgId - component Id
the file has:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MSCAL.Calendar.7] @="MSCAL.Calendar.7"
[HKEY_CLASSES_ROOT\MSCAL.Calendar.7\CLSID] @="{here I generated GUID using VS GUID tool}"
When I try to run my app, I am getting any issue: issue
Please, help me to find an issue!
I am expecting the COM to be created and my app to be running.
The answer from @Igor Tandetnik was right, I do not need to register any other ProdId, coz mine example is already installed on my machine.
There would also need to be a key HKEY_CLASSES_ROOT\CLSID{Your actual GUID here}, and under that key, the details of where and how the component is actually implemented. Taking a step back, MSCAL.Calendar.7 sounds like some component provided by Microsoft - why are you making up a GUID for it? If it's installed on your machine, the necessary registry entries should already be present. If it's not installed on your machine, then making up random registry keys won't magically conjure it up.