danw11
asked on
Receiving Of COM Events within a C program
Hello:
I have the below C code. I need for the OnUpdateComplete() and OnDownloadComplete() methods (shown in the code below) to be fired when the respective events for them are fired from the #imported COM program.
Here is the program. What extra code do I need to do this. I believe I need to be able to handle connection point sinks and I have found the following URL:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcconSupportingIDispEventImpl.asp,
but I am wondering if I can get some extra help here as I have no experience with COM, yet I have to get this to work.
Here is my code that compiles but I need to add the necessary connection point sinks for this to work. Can anybody help me with this? Also, please supply any #includes that I may need.
Thank you,
Dan
#import "c:\Program Files\Common Files\InstallShield\Update Service\ag ent.exe" named_guids no_namespace
#include <atlbase.h>
#include "CBstrImpl.h"
#include <iostream>
bool downloadComplete = false;
bool updateComplete = false;
using std::cout;
void OnDownloadComplete(long nResult)
{
downloadComplete = true;
}
void OnUpdateComplete(long nReturnCode)
{
updateComplete = true;
}
void errormsg(HRESULT hr, LPCTSTR desc=NULL)
{
LPVOID lpMsgBuf = NULL;
TCHAR pszError[1024];
if (desc == NULL)
{
// get system description for the error
::FormatMessage(FORMAT_MES SAGE_ALLOC ATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSE RTS,
NULL,
hr,
0,
reinterpret_cast<LPTSTR>(& lpMsgBuf), 0, NULL);
if(lpMsgBuf)
{
::wsprintf(pszError, "%s", reinterpret_cast<char*>(lp MsgBuf));
::LocalFree(lpMsgBuf);
}
else
{
::wsprintf(pszError, "Error: %X", hr);
}
}
else
wsprintf(pszError, "Error: Code:0x%x, %s", hr, desc);
::MessageBox(0, pszError, "Error", MB_OK);
exit(0);
}
int main(int argc, char* argv[])
{
/*
// Used for testing DownloadEx()
char buf[1000];
GetTempPath(1000, buf); // Get DOS style path name of temp directory
char buf1[1000];
GetLongPathName(buf, buf1, 1000); // Get long Windows style path for temp directory.
*/
::CoInitialize(NULL);
CComPtr<IUpdate> m_spUpdate;
CComPtr<IAgentEx> m_spAgent;
CComPtr<IUpdates> m_spUpdates;
//CComPtr<IUpdate> m_spUpdate;
CComBSTR m_ProductCode ("{FE4ACC45-03DE-4CD0-A202 -B67826A1F 8CD}");
try
{
HRESULT hr = m_spAgent.CoCreateInstance (CLSID_Age nt);
if (!SUCCEEDED(hr))
errormsg(hr);
m_spUpdates = m_spAgent->EnumUpdates(m_P roductCode .m_str);
if (m_spUpdates->Count == 0)
::MessageBox(0, "No Updates found", "Info", MB_OK);
for (long i = 0; i < m_spUpdates->Count; i++)
{
CComVariant vtItem;
hr = m_spUpdates->get_Item(i+1, &vtItem);
if (!SUCCEEDED(hr))
errormsg(hr);
m_spUpdate= com_cast<IUpdate>(vtItem.p unkVal);
CComBSTR title=m_spUpdate->QueryVal ue(Title). copy();
CComBSTR startDate = m_spUpdate->QueryValue(Sta rtDate).co py();
/*
CComBSTR url = m_spUpdate->QueryValue(Dow nloadUrl). copy();
*/
CBstr bstrTitle( title.Copy(), true);
CBstr bstrDate (startDate.Copy(), true);
if (bstrTitle.Find( _T("BaseData")) >= 0 && (bstrDate.Left(10)).Compar eNoCase(_T ("2006-05- 31")) > 0)
{
//numInstallCounter++;
m_spUpdate->Download(VARIA NT_TRUE);
while (! downloadComplete)
{
cout << "Download Not Complete";
Sleep(3000);
}
cout << "Download Complete!";
m_spUpdate->Execute();
while (! updateComplete)
{
cout << "Update Not Complete";
Sleep(3000);
}
cout << "Update Complete!";
/*
CComBSTR sz=m_spUpdate->QueryValue( DownloadSi ze).copy() ;
CComBSTR msg="Update Title: ";
msg.AppendBSTR(title);
msg.AppendBSTR(sz);
msg.Append(", Download Size:");
msg.Append(" KB");
msg.Append(", Date: ");
msg.AppendBSTR(startDate);
msg.Append("URL: ");
msg.AppendBSTR(url);
::MessageBoxW(0, msg, L"Title", MB_OK);
*/
}
}
} catch (_com_error e)
{
USES_CONVERSION;
CComPtr<IErrorInfo> spError;
CComBSTR serr;
if (S_OK == ::GetErrorInfo(0, &spError))
{
spError->GetDescription(&s err);
errormsg(e.Error(), W2CA(serr));
}
errormsg(e.Error(), e.ErrorMessage());
}
::CoUninitialize();
return 0;
}
I have the below C code. I need for the OnUpdateComplete() and OnDownloadComplete() methods (shown in the code below) to be fired when the respective events for them are fired from the #imported COM program.
Here is the program. What extra code do I need to do this. I believe I need to be able to handle connection point sinks and I have found the following URL:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcconSupportingIDispEventImpl.asp,
but I am wondering if I can get some extra help here as I have no experience with COM, yet I have to get this to work.
Here is my code that compiles but I need to add the necessary connection point sinks for this to work. Can anybody help me with this? Also, please supply any #includes that I may need.
Thank you,
Dan
#import "c:\Program Files\Common Files\InstallShield\Update
#include <atlbase.h>
#include "CBstrImpl.h"
#include <iostream>
bool downloadComplete = false;
bool updateComplete = false;
using std::cout;
void OnDownloadComplete(long nResult)
{
downloadComplete = true;
}
void OnUpdateComplete(long nReturnCode)
{
updateComplete = true;
}
void errormsg(HRESULT hr, LPCTSTR desc=NULL)
{
LPVOID lpMsgBuf = NULL;
TCHAR pszError[1024];
if (desc == NULL)
{
// get system description for the error
::FormatMessage(FORMAT_MES
FORMAT_MESSAGE_FROM_SYSTEM
FORMAT_MESSAGE_IGNORE_INSE
NULL,
hr,
0,
reinterpret_cast<LPTSTR>(&
if(lpMsgBuf)
{
::wsprintf(pszError, "%s", reinterpret_cast<char*>(lp
::LocalFree(lpMsgBuf);
}
else
{
::wsprintf(pszError, "Error: %X", hr);
}
}
else
wsprintf(pszError, "Error: Code:0x%x, %s", hr, desc);
::MessageBox(0, pszError, "Error", MB_OK);
exit(0);
}
int main(int argc, char* argv[])
{
/*
// Used for testing DownloadEx()
char buf[1000];
GetTempPath(1000, buf); // Get DOS style path name of temp directory
char buf1[1000];
GetLongPathName(buf, buf1, 1000); // Get long Windows style path for temp directory.
*/
::CoInitialize(NULL);
CComPtr<IUpdate> m_spUpdate;
CComPtr<IAgentEx> m_spAgent;
CComPtr<IUpdates> m_spUpdates;
//CComPtr<IUpdate> m_spUpdate;
CComBSTR m_ProductCode ("{FE4ACC45-03DE-4CD0-A202
try
{
HRESULT hr = m_spAgent.CoCreateInstance
if (!SUCCEEDED(hr))
errormsg(hr);
m_spUpdates = m_spAgent->EnumUpdates(m_P
if (m_spUpdates->Count == 0)
::MessageBox(0, "No Updates found", "Info", MB_OK);
for (long i = 0; i < m_spUpdates->Count; i++)
{
CComVariant vtItem;
hr = m_spUpdates->get_Item(i+1,
if (!SUCCEEDED(hr))
errormsg(hr);
m_spUpdate= com_cast<IUpdate>(vtItem.p
CComBSTR title=m_spUpdate->QueryVal
CComBSTR startDate = m_spUpdate->QueryValue(Sta
/*
CComBSTR url = m_spUpdate->QueryValue(Dow
*/
CBstr bstrTitle( title.Copy(), true);
CBstr bstrDate (startDate.Copy(), true);
if (bstrTitle.Find( _T("BaseData")) >= 0 && (bstrDate.Left(10)).Compar
{
//numInstallCounter++;
m_spUpdate->Download(VARIA
while (! downloadComplete)
{
cout << "Download Not Complete";
Sleep(3000);
}
cout << "Download Complete!";
m_spUpdate->Execute();
while (! updateComplete)
{
cout << "Update Not Complete";
Sleep(3000);
}
cout << "Update Complete!";
/*
CComBSTR sz=m_spUpdate->QueryValue(
CComBSTR msg="Update Title: ";
msg.AppendBSTR(title);
msg.AppendBSTR(sz);
msg.Append(", Download Size:");
msg.Append(" KB");
msg.Append(", Date: ");
msg.AppendBSTR(startDate);
msg.Append("URL: ");
msg.AppendBSTR(url);
::MessageBoxW(0, msg, L"Title", MB_OK);
*/
}
}
} catch (_com_error e)
{
USES_CONVERSION;
CComPtr<IErrorInfo> spError;
CComBSTR serr;
if (S_OK == ::GetErrorInfo(0, &spError))
{
spError->GetDescription(&s
errormsg(e.Error(), W2CA(serr));
}
errormsg(e.Error(), e.ErrorMessage());
}
::CoUninitialize();
return 0;
}
ASKER
chip3d:
I really need some specific help on my problem. I read this article and many others and I just don't have the expertise within the given timeframe to solve this. I would be willing to pay consulting fee for someone to do this.
Dan
I really need some specific help on my problem. I read this article and many others and I just don't have the expertise within the given timeframe to solve this. I would be willing to pay consulting fee for someone to do this.
Dan
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Chip:
Thanks. I will test this out in a few days and see if it works for me. I will report back and let you know.
Dan
Thanks. I will test this out in a few days and see if it works for me. I will report back and let you know.
Dan
I think this article could help you to solve your problem...
http://www.codeproject.com/com/JBCOMNotify.asp