Click here to Skip to main content
15,893,622 members
Home / Discussions / COM
   

COM

 
AnswerRe: How do i make COM inprocess server program using C++? Pin
prasad_som20-Sep-06 23:19
prasad_som20-Sep-06 23:19 
GeneralRe: How do i make COM inprocess server program using C++? Pin
Sakthiu20-Sep-06 23:23
Sakthiu20-Sep-06 23:23 
QuestionIssues Implementing ATL COM Callback Functionality Pin
Setesh8220-Sep-06 13:14
Setesh8220-Sep-06 13:14 
QuestionRe: Issues Implementing ATL COM Callback Functionality Pin
prasad_som20-Sep-06 23:22
prasad_som20-Sep-06 23:22 
AnswerRe: Issues Implementing ATL COM Callback Functionality Pin
Setesh8221-Sep-06 3:14
Setesh8221-Sep-06 3:14 
AnswerRe: Issues Implementing ATL COM Callback Functionality Pin
Mike Dimmick21-Sep-06 3:00
Mike Dimmick21-Sep-06 3:00 
GeneralRe: Issues Implementing ATL COM Callback Functionality Pin
Setesh8221-Sep-06 5:42
Setesh8221-Sep-06 5:42 
QuestionCOM Interop apartment issue - QueryInterface failing?!? Pin
Daniel Deptford20-Sep-06 4:05
Daniel Deptford20-Sep-06 4:05 
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
Questionerror 80040154 at instantiation of COM object Pin
mkrelli19-Sep-06 22:55
mkrelli19-Sep-06 22:55 
Questiongive suggestion to start learning COM Pin
premkamalg19-Sep-06 20:10
premkamalg19-Sep-06 20:10 
AnswerRe: give suggestion to start learning COM Pin
ShilpiP28-Sep-06 0:11
ShilpiP28-Sep-06 0:11 
AnswerRe: give suggestion to start learning COM Pin
Hamid_RT28-Sep-06 9:10
Hamid_RT28-Sep-06 9:10 
QuestionError in Deployment Pin
Jeeva Mary Varghese19-Sep-06 18:21
Jeeva Mary Varghese19-Sep-06 18:21 
AnswerRe: Error in Deployment Pin
Stephen Hewitt19-Sep-06 18:54
Stephen Hewitt19-Sep-06 18:54 
QuestionRe: Error in Deployment Pin
Jeeva Mary Varghese19-Sep-06 19:13
Jeeva Mary Varghese19-Sep-06 19:13 
AnswerRe: Error in Deployment Pin
Stephen Hewitt19-Sep-06 19:37
Stephen Hewitt19-Sep-06 19:37 
GeneralRe: Error in Deployment Pin
Jeeva Mary Varghese19-Sep-06 19:44
Jeeva Mary Varghese19-Sep-06 19:44 
GeneralRe: Error in Deployment Pin
Stephen Hewitt19-Sep-06 19:49
Stephen Hewitt19-Sep-06 19:49 
GeneralRe: Error in Deployment Pin
Jeeva Mary Varghese19-Sep-06 19:59
Jeeva Mary Varghese19-Sep-06 19:59 
GeneralRe: Error in Deployment Pin
Stephen Hewitt19-Sep-06 20:28
Stephen Hewitt19-Sep-06 20:28 
QuestionLeak for not calling VariantClear on a Variant holding a IXMLDOMSchemaCollection2Ptr Pin
rajandpayal17-Sep-06 4:29
rajandpayal17-Sep-06 4:29 
AnswerRe: Leak for not calling VariantClear on a Variant holding a IXMLDOMSchemaCollection2Ptr Pin
Aamir Butt19-Sep-06 20:57
Aamir Butt19-Sep-06 20:57 
QuestionIE Extension: How to add a button to the status bar? Pin
rryyjw15-Sep-06 6:08
rryyjw15-Sep-06 6:08 
GeneralRe: IE Extension: How to add a button to the status bar? Pin
Guffa15-Sep-06 15:57
Guffa15-Sep-06 15:57 
QuestionSystem.Runtime.InteropServices.COMException (0x80040154): ERROR Pin
Jeeva Mary Varghese14-Sep-06 19:23
Jeeva Mary Varghese14-Sep-06 19:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.