|
Hi,
I have creating shared add-in in C# and then am then using Shim on top of it.
Shared add-in has some user defined functins.once you type the UDFs in Excel, it will log in to server using username and password,creates sessions and get the data.
I am planning to move VSTO. Is it possible to introduce VSTO instead of Shim on top of shared add-in?
how can I do it? can any one share the thoughts?
Thanks
|
|
|
|
|
I have (I think for some of you) a simple question. I have an .vcproj project (no ATL support and no MFC support) and a I have an .exe file. Within this .exe file should be an COM Server that runs on WinVista. Now I need an connection from my .vcproj project to that COM server. Is there anywhere an step by step tutorial with that I can do such something? I’ve heard in several forums that it is the easiest way to create an ATL project and implement this .exe file. This works also if I create a new ATL project. A new .h file will be created with all the Methods and so on out of the .exe file.
But what should I do with an non ATL/MFC supported project? Is there also a way to work with such an project and an COM server?
The main problem I have is that I need to work later with some events of the COM server, and this should be also very complicated with no ATL support?
It would be nice if someone could send me some information (Step by Step tutorial / simple example how events could be called and so on). I’ve found some things but no complete running example with an event handling.
Thanks for any hints.
System: WinVista, Visual Studio 2005
|
|
|
|
|
Just add the ATL header files in - that's all you need - that's all that "ATL Support" actually means. Doing stuff with COM without ATL is just too much like hard work.
You remember that Excel connection point sample of mine I linked to? That consists of a single .cpp file, whose 'ATL Support' consists of these three lines:
#include <atlbase.h>
#include <atlstr.h>
#include <atlcom.h>
And the atlstr.h isn't needed for COM.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
modified on Thursday, September 10, 2009 11:35 AM
|
|
|
|
|
Thanks for your help, Stuart. I try now to implement MFC + ATL support and then I can implement all the COM classes out of the .exe file directly with Visual Studio.
Regards,
Jürgen
|
|
|
|
|
Ignore MFC - you don't need it for a simple connection point sink.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
ok, thanks.
Now I made the following steps in Visual Studio:
-> Add Class --->Simple ATL-Object with Connection Points. With that the ATL support was added to my project.
After that the project could be compiled without any problem.
Now I click with the right mouse on the new class I've created with the ATL OBject and choose "Implement interface". With that I can now navigate to the .exe file and implement all the interfaces I need.
And now after that I got the following message after I tried to compile it:
Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(1868) : error C2259: 'ATL::CComObject<Base>': Instance of abstract class could not be built1> with
1> [
1> Base=CEGR_COM
1> ]
1> because of the following member:
1> "HRESULT ICOLE::cSetLanguage(BSTR,VARIANT_BOOL *)": is abstract
1> c:\dev\cw_source\vitra scene\release\configurator.tlh(605): Siehe Deklaration von 'ICOLE::cSetLanguage'
1> "HRESULT ICOLE::cSetDefaultCurrency(BSTR,VARIANT_BOOL *)": ist abstract
.
.
.
.
.
Ok, all these function bodys are now in an TEST_COM.h and in the configurator.tlh file. The TEST_COM.cpp is empty. I don't know why this error message now will come up. The error message will come only for a few of the functions in the .tlh file, not for all.
.
.
.
virtual HRESULT __stdcall get_DimensionZ (
/*[out,retval]*/ double * Value ) = 0;
virtual HRESULT __stdcall put_DimensionZ (
/*[in]*/ double Value ) = 0;
virtual HRESULT __stdcall get_ErrorCode (
/*[out,retval]*/ short * Value ) = 0;
virtual HRESULT __stdcall put_ErrorCode (
/*[in]*/ short Value ) = 0;
virtual HRESULT __stdcall cInitializeProperties ( ) = 0;
// All the functions below will cause an error message
virtual HRESULT __stdcall cSetLanguage (
/*[in]*/ BSTR pLanguage,
/*[out,retval]*/ VARIANT_BOOL * Result ) = 0;
virtual HRESULT __stdcall cSetDefaultCurrency (
/*[in]*/ BSTR pCurrency,
/*[out,retval]*/ VARIANT_BOOL * Result ) = 0;
virtual HRESULT __stdcall cShowCatalogChooser (
/*[out,retval]*/ VARIANT_BOOL * Result ) = 0;
.
.
.
Any ideas?
|
|
|
|
|
I don't think you've gone around this quite right - I thought you wanted to catch events raised by the COM server in the EXE file?
If this understanding is correct, then you don't need to re-implement the interfaces exposed by the EXE's COM server to do that - instead, you just need to instantiate the COM object implemented in the EXE and implement a connection point sink that you link to the instantiated object.
Please let me know if I've understood your situation correctly (although I'll be mostly off-line over the weekend).
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Yes, you understand it correct. I want to catch events from this server in the .exe file.
At first I worked with an .c / .h / .idl file that have been created from the .exe server. With these I could create an ComPtr and I could call some methods with this pointer. This step works in my old project:
CComPtr<icole2> tCOLE;
hr = CoInitialize(0);
hr = CoCreateInstance(CLSID_COLEv2, 0, CLSCTX_LOCAL_SERVER, IID_ICOLE2, (void**)&tCOLE);
tCole->.... //here I could call the methods out of the ICOLE2.
This worked also perfect.
Now I had the problem that I must catch also some events from the server. And here I didn't know how I should go on. Some people on different forums called me to work with atl because this should be easier. So now I tried to do that all with ATL. The main problem now is, that I didn't exactly know what I must do. I didn't found anywhere an example / tutorial that explains everything step by step.
|
|
|
|
|
 Here's a full example using ATL and #import - the comments should be informative, I hope It references the Excel COM server, obviously running in a separate process. It tells Excel it wants to catch application-specific events (as defined by the interface AppEvents), by telling it what object to send the events to.
#include <iostream>
#include <atlcom.h>
#import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces raw_dispinterfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")
_ATL_FUNC_INFO SheetChangeInfo = { CC_CDECL, VT_EMPTY, 2, { VT_DISPATCH, VT_DISPATCH } };
class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag) { done_ = false; }
BEGIN_SINK_MAP(ExcelAppEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
END_SINK_MAP()
void _stdcall SheetChange(IDispatch * Sh, struct Excel::Range * Target)
{
done_ = true;
}
private:
bool& done_;
};
_bstr_t GetActiveWorkbookName(Excel::_ApplicationPtr xl)
{
if (Excel::_WorkbookPtr wb = xl->ActiveWorkbook)
{
try
{
return wb->FullName;
}
catch(_com_error& e)
{
std::cout << "EXCEPTION!!!\n";
std::cerr << CT2CA(e.ErrorMessage()) << std::endl;
bool done;
ExcelAppEventHandler app(done);
if (SUCCEEDED(app.DispEventAdvise(xl)))
{
MSG msg;
while (!done && GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
app.DispEventUnadvise(xl);
return GetActiveWorkbookName(xl);
}
}
}
return _bstr_t();
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(0, COINIT_APARTMENTTHREADED);
{
Excel::_ApplicationPtr xl;
if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
{
std::cout << "Getting name\n";
std::cout << GetActiveWorkbookName(xl) << std::endl;
}
}
CoUninitialize();
return 0;
}
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Juergen_80 wrote: Now I need an connection from my .vcproj project to that COM server. Is there anywhere an step by step tutorial with that I can do such something?
I think that "#import directive" is only what you need if you are simply a client of this COM exe server.
Also don't forget about CoInitialize/CoInitializeEx functions before using COM objects and CoUninitialize after.
With best wishes,
Vita
|
|
|
|
|
Hi!
I have an application in MFC unmanaged code compiled with VS2008. My application call a strong-named com-module, registered with RegAsm myCom.dll /tlb:myCom.tlb /codebase, and gacutil /i myCom.dll. myCom-module is coded in c# and compiled with VS2008.
My customer runs my application on a citrix-server through a citrix-client. For most of my customer all works fine but for a few customer the application fails to call my Com-module when they run my application from there workstation, but if they try with the same login from another computer there is no problem at all.
Any clue how to solve my problem?
Best regards,
Bertil
MSc Bertil Morefält
modified on Thursday, September 10, 2009 10:21 AM
|
|
|
|
|
Well.. the scenario is the same com+ behave different on different environment right ?..
RegAsm command register your com into GAC and you also export the tbl. I need to confirm that weather you using the tlb which is exported in a developer / local environment and use this as references for your custom application.
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi!
In my developer computer I have registered myCom.dll at .\mycomdir\release and in my code I have #import "c:\mycomdir\release\myCom.tlb" raw_interfaces_only
In the application-server I have registered myCom.dll at the applications home-directory. So, both myCom.dll and myCom.tlb resides in the applications home-directory.
Best regards,
Bertil Morefält
MSc Bertil Morefält
|
|
|
|
|
Okay...Probably you set the COM visible = true from app-> assembly info & Register for COM Interop = true.. in this case you not need to register the COM using RegAsm command in your local machine. I think you can try to add your COM project in your setup and deployment project and set the self register = true... It will might be release your extra pain on thinking of various version of Microsoft Windows OS .
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi all,
I have a .NET(C#) DLL which I have to use from Visual Basic 6.0 application. I am using regasm tool to make tlb file and register the dll. Then I can use the tlb file from VB6.
Now I have to make an installer. I have heard that its possible from installer project to make tlb without using regasm tool, but did not get any sample yet.
Is it really possible to register .NET DLL without using regasm? If possible it would be great because I do not need to add any .NET framework in my installer.
If this is possible can anyone please give me a complete sample of this?
Please response.
modified on Saturday, September 12, 2009 4:48 AM
|
|
|
|
|
Yap... It's very easy. you can create an installer of your com+; You just take a setup & deployment project add the primary output files and set the property reg to com true..
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Thank you very much Maruf. That exactly what I wanted.
|
|
|
|
|
You are most welcome.....
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi All,
I’m an absolutely newbie in the COM technology and I have a little tricky question. I hope there’s someone out there who can help me with my problem. I have an .idl / .h / .c file and I integrated them in my VisualStudio 2005 C++ project. After that I’ve searched on the MSDN Library how I can connect an COM Server from my project. I’ve found a little example (http://msdn.microsoft.com/en-us/magazine/cc163361.aspx) and tried to do it on the same way. I’ve created an Csink class and tried to create an instance of this sink object to pass to the server. Now I want to call an function „ OnShowMessageDlg “ out of this Csink class and after that I’ll become the following error message from my compiler:
Linker error: LNK2001: unresolved external symbol public: __thiscall ""public: void __thiscall CSink::OnShowMessageDlg(struct IMsgDlg *,short *)" (?OnShowMessageDlg@CSink@@QAEXPAUIMsgDlg@@PAF@Z)".
Can someone give me a hint what there could be wrong? Or what I must do to use these function? Is the .idl file and the .h file correct? I didn’t find the functions OnShowMessageDlg and OnConfigurationApply in the .h file?
I know, this should be basics I must know. I hope the two books I’ve ordered will arrive as soon as possible.
Please let me know if you need any other information.
Thanks for ANY help.
Juergen
*************************************************************************************************
.idl file
.
.
.
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface ITEST2;
dispinterface ITESTEvents;
.
.
.
[
uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9),
version(1.1),
helpstring("Event dispatch interface for TEST")
]
dispinterface ITESTEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
.
.
.
.
coclass TESTv2 {
[default] interface ITEST2;
[default, source] dispinterface ITESTEvents;
};
*************************************************************************************************
.h file
.
.
.
EXTERN_C const IID DIID_ITESTEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9")
ITESTEvents : public IDispatch
{
};
#else /* C style interface */
typedef struct ITESTEventsVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ITESTEvents * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
.
.
.
*************************************************************************************************
.c file
.
.
.
MIDL_DEFINE_GUID(IID, IID_ITEST2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(IID, DIID_ITESTEvents,0x6775FB91,0xB5BE,0x11D6,0xA9,0x96,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(CLSID, CLSID_TESTv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
.
.
.
*************************************************************************************************
.c++ file
class CSink : public ITESTEvents
{
public:
CSink::CSink() {m_cRef = 0;}
CSink::~CSink() {}
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void **> (this);
if (IsEqualGUID(riid, DIID_ITESTEvents))
*ppvObject = reinterpret_cast<void **> (this);
if (*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
DWORD __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}
DWORD __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo)
{ return E_NOTIMPL; }
STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid,
ITypeInfo FAR* FAR* ppTInfo)
{ return E_NOTIMPL; }
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{ return S_OK; }
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
return S_OK;
}
public:
void OnConfigurationApply(VARIANT_BOOL *pAccept);
void OnShowMessageDlg(IMsgDlg *pIMsg, VARIANT_BOOL *Result);
private:
DISPID m_id;
long m_cRef;
};
void main(){
.
.
.
CComPtr<ITEST2> tTEST;
HRESULT hr;
hr = CoInitialize(0);
if(FAILED(hr)){
CoUninitialize();
return false;
}
hr = CoCreateInstance(CLSID_TESTv2, 0, CLSCTX_LOCAL_SERVER, IID_ITEST2, (void**)&tTEST);
IConnectionPointContainer * ICPointContainer;
hr = tTEST->QueryInterface(IID_IConnectionPointContainer,(void **)&ICPointContainer);
if(SUCCEEDED(hr)){
//CComPtr<IConnectionPoint> ICPoint;
hr = ICPointContainer->FindConnectionPoint(DIID_ITESTEvents, &ICPoint);
if(SUCCEEDED(hr)){
ICPointContainer->Release();
CSink *pSink;
IUnknown *pSinkUnk;
pSink = new CSink;
hr = pSink->QueryInterface (IID_IUnknown,(void **)&pSinkUnk);
hr = ICPoint->Advise(pSinkUnk,&dwAdvise);
VARIANT_BOOL *tDLGResult;
pSink->AddRef();
pSink->OnShowMessageDlg(tMsgDlg, tDLGResult); // ERROR MESSAGE
.
.
}
*************************************************************************************************
|
|
|
|
|
If you have timelimits in learning and implementing the task, you better should use a high-level COM-Wrapper like MFC oder ATL, then you must not implement the standard-interfaced like IUnknown or IDispatch youself. I think there must be lots of examples on codeproject. The error-message tells you to implement the function OnShowMessageDlg(). This is a function call from the com-server into your com-client, so you need an implementation.
|
|
|
|
|
If you have timelimits in learning and implementing the task..
This is the main problem.
The COM server I must use is an .exe file. Is it the easiest way to create an new ATL project? Is there any Wizard with that I can implement the code from the .exe file / COM server in this new project? Until now I use OleView to create the .idl file from the COM server. Can I then use the files from the ATL project in my C++ project?
|
|
|
|
|
The easiest way to use a COM server that has a type library (which should be most of them) is to use #import[^].
The easiest way to implement a connection point sink (a.k.a. an event sink) is to use ATL and create a class derived from IDispEventSimpleImpl. See this post[^] of mine for an example that handles an event raised by Excel.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi All,
I am writing some shell extension that use COM object and faced with the following issue. I need to call some method from COM object but I get this error: "hResult 0x80070542 Either a required impersonation level was not provided, or the provided impersonation level is invalid. HRESULT" The same code works fine in console app, because I manually CoInitializeSecurity before call the method, but in shell extension I cannot call CoInitializeSecurity by myself becase I get error that it was already called. How can I setup neccessery permision for this COM object?
Thanks.
|
|
|
|
|
Hi All,
I’m an absolutely newbie in the COM technology and I have a little tricky question. I hope there’s someone out there who can help me with my problem. I have an .idl / .h / .c file and I integrated them in my VisualStudio 2005 C++ project. After that I’ve searched on the MSDN Library how I can connect an COM Server from my project. I’ve found a little example (http://msdn.microsoft.com/en-us/magazine/cc163361.aspx) and tried to do it on the same way. I’ve created an Csink class and tried to create an instance of this sink object to pass to the server. But the problem now I get from my compiler is the following error message: „error C2259: 'CSink': cannot instantiate abstract class due to following members: 'HRESULT IUnknown::QueryInterface(const IID &,void **)' : is abstract“. The thing I need is that I must call the „ OnShowMessageDlg “ and the „ OnConfigurationApply “ functions out of the .idl file in my main c++ function. I’ve put all the code here below this entry that could help you to become an overview about my problem. Is the solution I’ve tried with the sink object correct or should I use another way to do this?
Please let me know if you need any other information.
Thanks for ANY help.
*************************************************************************************************
.idl file
.
.
.
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface ITEST2;
dispinterface ITESTEvents;
.
.
.
[
uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9),
version(1.1),
helpstring("Event dispatch interface for TEST")
]
dispinterface ITESTEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
.
.
.
.
coclass TESTv2 {
[default] interface ITEST2;
[default, source] dispinterface ITESTEvents;
};
*************************************************************************************************
.h file
.
.
.
EXTERN_C const IID DIID_ITESTEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9")
ITESTEvents : public IDispatch
{
};
#else /* C style interface */
typedef struct ITESTEventsVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ITESTEvents * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
.
.
.
*************************************************************************************************
.c file
.
.
.
MIDL_DEFINE_GUID(IID, IID_ITEST2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(IID, DIID_ITESTEvents,0x6775FB91,0xB5BE,0x11D6,0xA9,0x96,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(CLSID, CLSID_TESTv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
.
.
.
*************************************************************************************************
.c++ file
class CSink : public ITESTEvents
{
private:
DWORD m_dwRefCount;
public:
CSink::CSink() {m_dwRefCount = 0;}
CSink::~CSink() {}
void OnConfigurationApply(VARIANT_BOOL* pAccept);
void OnShowMessageDlg(IMsgDlg* pIMsg, VARIANT_BOOL* Result);
};
void main(){
.
.
.
CSink *pSink;
pSink = new CSink(); // ERROR MESSAGE
.
.
}
*************************************************************************************************
|
|
|
|
|
You need to implement the methods of the interfaces that ITESTEvents inherits from - that's going to be IDispatch, which in turn inherits from IUnknown. That's a fair bit of work...
There are a couple of CodeProject articles that might be of use: here[^] and here[^].
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|