|
Dear All,
Can anybody tell that how we can create a inprocess COM server program using C++?.
I know the basic thinks. but i cant get any articles regarding that where should i start program and how can i proceed further?
Please help me.
|
|
|
|
|
Sakthiu wrote: but i cant get any articles regarding that where should i start program and how can i proceed further?
Here[^]are some.
|
|
|
|
|
Thankyou so much.. let me gothrough this.
If I will have any questions, I let you know.
Thanks.
|
|
|
|
|
The past few day I have been trying to implement an event callback system within a VC++6.0 COM DLL. The DLL will then be referenced within a VB6 project.
I started off by creating a simple ATL Com project. The project only contain my two newly created COM object (StatusListener, StatusEvents). The StatusEvents object contains all the empty functions and will be overriden by a class in the VB6 project. The StatusListener object contains the Advise function which takes in an instance of the VB6 projects derived StatusEvents class. Once that takes place any update in the COM are sent directly back to the VB6 project via the derived class.
All of that was expected, the problem comes in when I tryin to implement the same functionality into a preexisting ATL COM project. Everything builds fine and the DLL is created. I reference the DLL and Implement the StatusEvents class in a VB6 client. When I try to Create and instance of either StatusListener or StatusEvents I get the following error msg.
"Compile error 429" "ActiveX Component can't create object"
I have put my Test DLL and client here:
ATL Com Tests.zip
Any suggestions would be most welcome.
|
|
|
|
|
Baldelicious82 wrote: All of that was expected, the problem comes in when I tryin to implement the same functionality into a preexisting ATL COM project.
Can you explain this? Do you mean to say, are adding same interfaces to preexisting project ?
Have you taken care, its should be mentioned in .idl ,too?
|
|
|
|
|
I am recreating the two ATL Objects within the preexisting DLL.
|
|
|
|
|
I'd really recommend using the Automation events mechanism: define a dispatch interface containing the events you will be firing, implement IConnectionPoint on a C++ class using IConnectionPointImpl and on the main object itself using IConnectionPointContainerImpl.
The Visual Studio environment should generate the right code for you if you check the 'Support Connection Points' checkbox on the Attributes tab when creating a new ATL COM object (VC6, may be different in newer versions). It automatically creates an _IMyObjectEvents interface, assuming you specified MyObject as the COM class name in the wizard. To implement the interface, build the project then right-click your class in ClassView and choose Implement Connection Point. Tick _IMyObjectEvents and click OK. VC6 then generates a CProxy_IMyObjectEvents class which implements a FireXxx method for every method in the event interface.
In the VB6 application, use WithEvents so that VB hooks up the event handlers (named variableName_EventName) for you.
|
|
|
|
|
thanks for the help I managed to get it working. My problem was that I wasnt implementing the connection point at least on the event side. The advise function i just ended up throwing into an already implement interface.
Thanks again for the help.
|
|
|
|
|
I have a solution consisting of two projects, an in-process COM DLL server and a .NET 2.0 C# windows application. (this is a simplification of my issue, but I've manged to repro it with this setup).
(A lot of code follows).
The COM component's IDL is:
[
uuid(703642F5-3FF0-4b47-A856-8B7A0878EFCD),
version(1.0),
helpstring("SimpleCOMLibrary")
]
library SimpleCOMLibrary
{
[object, uuid(B51D2FCA-2258-44c2-961F-C7F52DFA2833)]
interface ISquare : IUnknown
{
HRESULT SquareFloat([in] float value,[out,retval] float *retval);
}
importlib("stdole2.tlb");
[
uuid(50D5FA7D-B195-42a9-963C-B741D69E7F28),
version(1.0),
helpstring("SimpleComLibraryClassObject")
]
coclass SquareClass
{
[default] interface ISquare;
}
}
The basics of the coclass/class factory implementation in C++ is:
class SquareImpl : public ISquare
{
public:
STDMETHODIMP_(ULONG) AddRef(){return 1;}
STDMETHODIMP_(ULONG) Release(){return 1;}
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
{
*ppvObject = NULL;
if(riid == __uuidof(ISquare) || riid == __uuidof(IUnknown))
{
*ppvObject = this;
}
if(*ppvObject)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP SquareFloat(float in, float *out)
{
*out = in * in;
return S_OK;
}
};
SquareImpl s_Square;
class CSquareClassFactory : public IClassFactory
{
public:
STDMETHODIMP IClassFactory::CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppvObject )
{
if( pUnkOuter ) return CLASS_E_NOAGGREGATION;
return s_Square.QueryInterface(riid, ppvObject);
}
STDMETHODIMP IClassFactory::LockServer( BOOL bLock )
{
if( bLock ){InterlockedIncrement( &m_LockCount );}
else{InterlockedDecrement( &m_LockCount );}
return S_OK;
}
public: // IUnknown
STDMETHODIMP_(ULONG) AddRef( void ){return 2;}
STDMETHODIMP_(ULONG) Release( void ){return 1;}
STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject )
{
// find interface
//
if( riid == IID_IClassFactory || riid == IID_IUnknown )
{
*ppvObject = static_cast<iclassfactory*>(this);
}
else
{
// interface not found...
//
*ppvObject = 0;
return E_NOINTERFACE;
}
static_cast<iunknown*>(*ppvObject)->AddRef();
return S_OK;
}
private:
LONG m_LockCount;
};
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv)
{
static CSquareClassFactory s_squarefactory;
*ppv = NULL;
return s_squarefactory.QueryInterface( riid, ppv );
}
Registration code is hidden. However, here are the registry keys, dumped from regedit's export function.
Typelib:
[HKEY_CLASSES_ROOT\TypeLib\{703642F5-3FF0-4B47-A856-8B7A0878EFCD}]
[HKEY_CLASSES_ROOT\TypeLib\{703642F5-3FF0-4B47-A856-8B7A0878EFCD}\1.0]
@="SimpleCOMTest"
[HKEY_CLASSES_ROOT\TypeLib\{703642F5-3FF0-4B47-A856-8B7A0878EFCD}\1.0\0]
[HKEY_CLASSES_ROOT\TypeLib\{703642F5-3FF0-4B47-A856-8B7A0878EFCD}\1.0\0\win32]
@="C:\\Documents and Settings\\ddeptford\\My Documents\\Visual Studio 2005\\Projects\\CSharp_Apartment_Test\\debug\\SimpleCOMServer.dll"
coclass:
[HKEY_CLASSES_ROOT\CLSID\{50D5FA7D-B195-42A9-963C-B741D69E7F28}]
@="SimpleCOMServer SquareClass"
[HKEY_CLASSES_ROOT\CLSID\{50D5FA7D-B195-42A9-963C-B741D69E7F28}\InprocServer32]
@="C:\\Documents and Settings\\ddeptford\\My Documents\\Visual Studio 2005\\Projects\\CSharp_Apartment_Test\\debug\\SimpleCOMServer.dll"
"ThreadingModel"="Both"
[HKEY_CLASSES_ROOT\CLSID\{50D5FA7D-B195-42A9-963C-B741D69E7F28}\ProgID]
@="SimpleCOMServer.SquareClass.1"
[HKEY_CLASSES_ROOT\CLSID\{50D5FA7D-B195-42A9-963C-B741D69E7F28}\TypeLib]
@="{703642F5-3FF0-4B47-A856-8B7A0878EFCD}"
interface:
[HKEY_CLASSES_ROOT\Interface\{B51D2FCA-2258-44C2-961F-C7F52DFA2833}]
@="ISquare"
[HKEY_CLASSES_ROOT\Interface\{B51D2FCA-2258-44C2-961F-C7F52DFA2833}\ProxyStubClsid]
@="{00020424-0000-0000-C000-000000000046}"
[HKEY_CLASSES_ROOT\Interface\{B51D2FCA-2258-44C2-961F-C7F52DFA2833}\ProxyStubClsid32]
@="{00020424-0000-0000-C000-000000000046}"
[HKEY_CLASSES_ROOT\Interface\{B51D2FCA-2258-44C2-961F-C7F52DFA2833}\TypeLib]
@="{703642F5-3FF0-4B47-A856-8B7A0878EFCD}"
"Version"="1.0"
The GUID that the ProxyStubClsid points to is that of the standard marshaller. I used Larry Osterman's post at http://blogs.msdn.com/larryosterman/archive/2006/01/09/510856.aspx as the basis for using these keys.
Now I have a simple .NET 2.0 application, really just the default C# Windows app. It has a reference to the registered SimpleCOMLibrary COM object, and has generated an interop assembly. I've added a button, and have written the following code:
SimpleCOMLibrary.SquareClass m_Square = null;
public Form1()
{
InitializeComponent();
m_Square = new SimpleCOMLibrary.SquareClassClass();
}
private void button1_Click(object sender, EventArgs e)
{
System.Console.WriteLine("{0}\n", m_Square.SquareFloat(123));
(new Thread(new ThreadStart(DoSomething))).Start();
}
void DoSomething()
{
System.Console.WriteLine("{0}\n", m_Square.SquareFloat(123));
}
The main thread HAS to be set as [STAThread]. In the larger application I'm working on, OLE Drag & Drop is used, and we get an error if the main thread's apartment is [MTAThread].
Running this code, the first SquareFloat method call succeeds and prints the output to the console. The second one fails, with the exception:
System.InvalidCastException was unhandled
Message="Unable to cast COM object of type 'SimpleCOMLibrary.SquareClassClass' to interface type 'SimpleCOMLibrary.ISquare'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{B51D2FCA-2258-44C2-961F-C7F52DFA2833}' failed due to the following error: Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))."
Source="Interop.SimpleCOMLibrary"
StackTrace:
at SimpleCOMLibrary.SquareClassClass.SquareFloat(Single value)
at CSharp_Apartment_Test.Form1.DoSomething() in C:\Documents and Settings\ddeptford\My Documents\Visual Studio 2005\Projects\CSharp_Apartment_Test\CSharp_Apartment_Test\Form1.cs:line 29
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
I'm at a complete loss as to why it's not working properly. I thought that by using the default marshaller, the COM runtime used information available in the type library to marshal the call across apartment boundaries. I can't see anything wrong with the QueryInterface methods in the COM object I've written. It works with the main application thread set to [MTAThread], but for the application I'm putting this in this cannot be done.
Any help would be greatly appreciated!
Thanks
Daniel
|
|
|
|
|
Hello everybody.
I'm actually working on a service for phone call notification... However, to achieve that I downloaded a library called CapiThread (this is a sort of wrapper for the capi2032.dll). This is an "old" Win32 dll that exports 5 methods. (InitCapiThread, CloseCapiThread, RegisterNotifyMessage, SetRequest, GetIndication).
To use that dll within a C# Windows-Service project i've written a COM wrapper (COM Object ISDNCapi). The ISDNCapi object retrieves the notifications thrown by the CapiThread dll if an indication is pending and fires an event (OnCapiIndication). There are some other classes to hold the data of the indications and requests.
i know that i can youse P/invoke. but i've choosen to build a com wrapper, because i want to have a more general solution. so i can use it with other languages... and i found the event handlers better than hooking on notify messages (in C#) the CapiThread.dll sends.
Okay...
Now i've build a metadata-dll with TLBIMP that i use in my program. (As descripted in "COM Interoperability in .NET Framework: Part I"). The code compiles without any problems, but during the instantiation of my class ISDNCapi the following error raises:
Retrieving the COM class factory for component with CLSID {3A5119AE-E5CC-406F-8F62-FFC340C424CE} failed due to the following error: 80040154.
The component is definetly registered and can access it's dependecies, because instantiation it in VB6 causes no error and the regsvr32 succeeds also.
Somebody suggested me to check if the class factory registers correctly... but i've never done this seperately (in vc 6) so i don't know howto register it nor what to look for...
i've created the project with the option "component registrar". do i have to call the RegisterAll function of the Registrar class?
can anybody please check it in my code?
I've uploaded the sources of my projects to my server:
CapiWrapperSln
ISDNMonServer
And here are the complete exception details:
System.Runtime.InteropServices.COMException was unhandled
Message="Retrieving the COM class factory for component with CLSID {3A5119AE-E5CC-406F-8F62-FFC340C424CE} failed due to the following error: 80040154."
Source="ISDNMonServer"
ErrorCode=-2147221164
StackTrace:
at ISDNMonServer.ISDNMonServer..ctor() in E:\Entwicklungsumgebung\Projekte\Office\ISDNMon\ISDNMonServer\ISDNMonServer.cs:line 20
at ISDNMonServer.Program.Main() in E:\Entwicklungsumgebung\Projekte\Office\ISDNMon\ISDNMonServer\Program.cs:line 22
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
thanks.
Martin.
|
|
|
|
|
hi ,
plz give suggestion to start learning COM
i now VC++ and C#
Thanks
|
|
|
|
|
forst u have a knowledge of IUnknown interface and Standard interface that is used in vc++.MSDN library is the best solution where u understand everything what is com ,y use com ,how to make com companent
|
|
|
|
|
Did you see Com On codeproject?
|
|
|
|
|
Hai ,
I am developing a build using Install shield 10.5 , after installing the msi , I could open the application but displaying the below error message
First One is Access Vilation Error of the Dll msvcr80.dll
Next Error is
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.
at SipperRobotControllerLib.ActionDeviceClass.set_XYPosIndex(Int32 pPosIndex)
at CaliperLifeSciences.DKP.SipperControl.SipperCtrlPanel.mPlateControl_OnWellClicked(Int32 nRow, Int32 nColumn) in Y:\Core\Devices\PlateHandler\SipperControl.NET\CaliperSipper.vb:line 134
at CaliperLifeSciences.UserInterfaceControl.PlateControl.PlateControl_Click(Object sender, EventArgs e) in y:\Core\support\UserInterfaceControl\PlateControl.cs:line 875
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.UserControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
How can i Solve these Errors.Actuallly i did this using Installshield 11.5.
Please help to solve this problem............................
|
|
|
|
|
The COM method called returned a failure code and the interop layer mapped it into an exception. What COM object and method is being called?
Steve
|
|
|
|
|
Steve ,
I was developing a build using the com and dll's and .net components which is not developed by me , By using these components i could made a build using install shield 10.5. I could open the application , but while select some of the contols i am geting errors as i posted earlier
Can you give a solution for this, I am hanged on this error for a quite long time
Please Help
|
|
|
|
|
Why a particular COM components returns E_FAIL depends on the components and method in question. I can't tell you anything without knowing these details.
Steve
|
|
|
|
|
Steve,
This is when using Dotnet dll's
Thanks
|
|
|
|
|
The error says, "HRESULT E_FAIL has been returned from a call to a COM component." Somewhere a COM component is being called and one of its methods is failing with the E_FAIL failure code. The reason for this depends on the component and method in question regardless of the language used to implement it.
Steve
|
|
|
|
|
Steve,
Is this problem is arising due to non registering of any com or dll component or due to the error in coding ?
I am just deploying the files given to me to make a build
Thanks for your Quick response steve!!!
|
|
|
|
|
It's possible it's a registration problem but note that if a method can return E_FAIL the COM object exists and thus was created correctly which implies it was registered. It's possible some other object which the object uses wasn't registered however.
Steve
|
|
|
|
|
We have been bitten by severe memory leaks in our project.
While having a dry run of one of the components code. I came across the following. This looks like a sure shot memory leak to me. Because of the fact that we are not doing a VariantClear().
Please confirm.
<<
try
{
IXMLDOMSchemaCollection2Ptr m_pSchemaCache;
hr=m_pSchemaCache.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60));
if (SUCCEEDED(hr))
{
hr=m_pSchemaCache->add(szNameSpace_in, szSchemaFilePath_in);
if (SUCCEEDED(hr))
{
VARIANT varValue;
varValue.vt = VT_DISPATCH;
varValue.pdispVal = m_pSchemaCache.GetInterfacePtr();
m_pSchemaCache.AddRef();
m_pDOMDoc->PutRefschemas(varValue);
}
else
{
this->m_errorCode=ERR_XML_DOC_SCHEMA_ADDITION_FAILED;
return FALSE;
}
}
else
{
this->m_errorCode=ERR_XML_DOC_SCHEMA_INSTANCE_CREATION_FAILED;
}
}
>>
Rajdeep
|
|
|
|
|
Off course, its a memory leak. you have to free a variant manually. The other way round is to use CComVariant. This frees a variant automatically and u get spared of calling VariantClear etc.
"Some people believe football is a matter of life and death.
I'm very disappointed with that attitude.
I can assure you it is much, much more important than that. -- Bill Shankly"
|
|
|
|
|
Have you ever tried Google Notebook? After installing the software, it will add a button to the bottom-right corner of IE. Dose anybody know how to implement that ? Any reply is appreciated.
Thanks
R.Y.J
|
|
|
|
|
Please don't cross post.
---
b { font-weight: normal; }
|
|
|
|