locked
COM object registration RRS feed

  • Question

  • Hi all
    I'm on VS2008, WXP SP3. I'm trying to develop some basic client - server application (COM server object in .exe file). I compile server program without warning, it starts and waits for requests. Then I compile my client program and comes out an exception: A first chance exception of type 'System.NullReferenceException' occurred.
    The code for registration of component in server program:
    CoInitializeEx(NULL,COINIT_MULTITHREADED);
    IClassFactory* pSClassFactory= new CSimple_If_Impl();
    DWORD dwSRegister;
    CoRegisterClassObject(CLSID_DCOM_server, pSClassFactory,CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwSRegister);
    hEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
    WaitForSingleObject(hEvent, INFINITE);
    CoRevokeClassObject(dwSRegister);
    pSClassFactory->Release();
    CoUninitialize();

    ...client component initialization request:

    hrSI = CoInitializeEx(NULL,COINIT_MULTITHREADED);   
    if (SUCCEEDED(hrSI))                // macro to check for success
    {
      hrSI = CoCreateInstance( CLSID_DCOM_server, //COM class id	   
    NULL, // outer unknown CLSCTX_LOCAL_SERVER, // server INFO IID_ISimple_Interface, // interface id (void**&IS_I ); // pointer to interface }

     ...and method call in client program:

    start=clock();
    for (int i=0;i<1000;i++)
    {
        hrSI = IS_I->get_char(i,&u_c);
        tempCharTable[i] = u_c;
    }
    My question is, obviously "Where I got wrong?" or what is a proper way to proceed in this case?
    Thanks in advance for any help
    Cheers
    M

    Wednesday, May 27, 2009 12:26 PM

Answers

  • AllocConsole() hooks up the standard output handle so you can write to the console any way you want. std::cout is just fine, although it is typically a hair slower than printf(). fwrite() is probably faster but not as convenient to code.

    This really has nothing to do with your original question. I suggest you start a new thread for any new questions that come along.
    Thursday, May 28, 2009 10:00 PM

All replies

  • Did you really mean to make a .NET program as your client?  You are not writing .NET code.  More than likely, IS_I is null.  I don't see you checking the return value of CoCreateInstance().  Probably because you didn't build and/or register the required proxy/stub DLLs.

    If .NET code is your preference, steer clear from COM and use .NET remoting.

    Hans Passant.
    Wednesday, May 27, 2009 12:47 PM
  • I have to use COM. My client program is W32 application, for some reason I do not use ATL. I compiled my .idl file, and obtained files in my server project directory (interface_h.h, interface_p.c, interface_i.c and dlldata.c). interface files with proxy/stub code I copied to my client directory and included interface_i.c and interface_h.h. My COM server object is in .exe  file, does the component registration is correct in this case? Do I have to include dlldata.c also?
    Wednesday, May 27, 2009 1:09 PM
  • Your client is not a Win32 app if it generates a System.NullReference exception.  Only managed .NET code can generate that exception.  You need to build the proxy/stub DLL in a separate project.  If you don't use ATL, it is pretty unlikely that your component registration is done correctly.  You would know you did it right from writing the required code yourself.

    Hans Passant.
    Wednesday, May 27, 2009 1:22 PM
  • You're right; My server project is a Win32 application. The client is Windows Forms. I do not find any precise desription about building the Win32 exe project that will hold the COM  server object. Anyway, I started with Win32 application, then I compiled with MIDL my .idl file. It generated files that I mentioned earlier, and two of them were added to newly-created folder "Generated Files" inside of my project (being excluded from compilation). Then I have my interface functions definitions in other file and registration I perform as I wrote in may first post. At this point, what is incorrect on server side?(compilation , linking, go with no problems)?
    M
    Wednesday, May 27, 2009 4:57 PM
  • What testing did you do on the server side? Did you register the COM server? Did you run the OLEVIEW utility and try to instantiate the COM object?
    Wednesday, May 27, 2009 5:47 PM
  • Registration I did as I posted in may first post (if this is it). Did not know about OLEVIEW utility how to try to instantiate COM object? I did not performed any tests seeing server  working. Do you think registration above is performed properly?
    Wednesday, May 27, 2009 6:11 PM
  • I did not performed any tests seeing server  working. Do you think registration above is performed properly?

    If you didn't do any testing, how would I know?

    My questions were rhetorical. Let me restate my post:

    You need to test the server side. Make sure you register the COM server. Use OLEVIEW to confirm the COM server is registered correctly by explicitly instantiating the COM object:  Find the COM class name. It should be listed under "Automation Objects". Right-click, and you will see a "Create Instance" menu item in the context menu. Use it.



    Wednesday, May 27, 2009 7:22 PM
  • Ok. I used Oleview, but I did not find my COM server class registration. My MIDL "class", created from interface definition is called ISimple_Interface,  and it inherits from IClassFactory. COM class that defines functions declared in interface is called CSimple_If_Impl and inherits from ISimple_Interface (is CSimple_Interface the name I have to look for in OleView?). Registration procedure that I described above I have found on Web. Am I wrong on entire registration concept or I just used the wrong methods? All precise description I find are concerning COM objects in .dll files, my should be placed in .exe.

    Thursday, May 28, 2009 6:16 AM
  • Oleview will list the COM object using the helpstring attribute of your type library. Look in your IDL file for the helpstring, and if it isn't there, add one. It should be just above the library statement.

    If you still can't find it, then in all liklihood your COM server is not registered properly.
    • Edited by Brian Muth Thursday, May 28, 2009 4:26 PM clarification
    Thursday, May 28, 2009 4:24 PM
  • I do not find my COM server with helpstring. I understand, that my server is not registered properly and my question is:
    Am I wrong on entire registration concept or I just used the wrong methods? At the begining I wrote the code for registration of COM server, may I have an answer if it is correct? And if is not could you post some example of registration in .exe server program?
    Thursday, May 28, 2009 5:27 PM
  • What framework was used when constructing your COM server? With both MFC and ATL, the registration code gets burned right into the server itself.

    For DLL servers, simply run:

    regsvr32 MyComServer.dll

    For EXE servers, simply run

    MyComServer.exe /regserver

    Thursday, May 28, 2009 5:43 PM
  • I did not use any framework. I created Win32 console application, added and compiled idl file and it generated stub/proxy files in my project. Then I added declarations/definitions files for functions of interface and registration code. ___.exe /regserver does not changed anything in oleView. Is it possible to create COM server program in a way that I did?

    Thursday, May 28, 2009 7:22 PM
  • Oh dear, oh dear. I've reread your initial post and I see you have chosen the most difficult path possible to construct your COM server. Yes, of course you can do it the way you have done, but no one in their right mind does things that way, including me. A more sensible approach would be to use one of the readily available frameworks. I tend to prefer ATL, but MFC works fine too.

    Having said that, I don't see anything obviously wrong with your code, but then your posting is incomplete. Is CSimple_If_Impl() truly a class factory?

    I'm afraid I won't be able to help you very much. This is a area I've never dared to traverse. Wouldn't it make more sense to go back and use ATL or MFC? This kind of boilerplate code comes for free, and you don't have to debug your own version.
    Thursday, May 28, 2009 7:50 PM
  • Excellent. For CSimple_If_Impl : In my .idl file I defined interface ISimple_interface that inherits from IClassFactory:

    [
    	object,
    	uuid(90F42FCB-1FDA-48A3-82E2-A02DA3260BAD),
    
    	helpstring("ISimple Interface"),
    	pointer_default(unique)
    ]
    interface ISimple_Interface : IClassFactory
    {
    	HRESULT get_char([in] unsigned short _index,[out,retval] char* c);
    	HRESULT get_double([in] unsigned short _index,[out,retval] double* d);
    	HRESULT set_char([in] char c,[in] unsigned short _index);
    	HRESULT set_double([in] double d,[in] unsigned short _index);
    };

    then I compiled this file (now I see a warning MIDL:

    1>midl\oleaut32.dll : warning MIDL2368 : error generating type library, ignored : Could not set UUID : __MIDL___MIDL_itf_interface_0000_0000_0001 (0x800288C6)

     


    Anyway, it creates me stub/proxy files (I described it before) etc. Interface functions declarations/definitions I have in other files (.h .c respectively) together with definitions of functions inherited from ClassFactory. Below code of QueryInterface:

    HRESULT __stdcall CSimple_If_Impl::QueryInterface ( REFIID riid, void** ppvObject )
    {
        HRESULT hr= S_OK;
        if( riid == IID_IUnknown ) 
        {
            *ppvObject= static_cast<IUnknown*>(static_cast<CSimple_If_Impl*>(this));
        } 
        else if( riid == IID_ISimple_Interface)
        {
            *ppvObject= static_cast<ISimple_Interface*>(this);
        } 
        else
        {
            ppvObject= NULL;
            hr= E_NOINTERFACE;
        }
        if(SUCCEEDED(hr))
            (static_cast<IUnknown*>(*ppvObject))->AddRef();
        return hr;
    };

    That is all.
    For use of ATL: Is it possible to create ATL console win32 project ?

    Thursday, May 28, 2009 8:23 PM
  • This looks completely messed up to me. Your class factory must be a completely separate object from your class object. The class factory object behaves as a singleton, whereas the class object typically does not. Why on earth you are deriving your interface from IClassFactory?

    I strongly suggest you toss this code in the bin.

    COM servers typically don't have a window or a console. There is no need for them to interact with the desktop, and indeed typically they should not. Having said that, it is not difficult to modify an ATL executable to display a console. Why do you want one?

    Thursday, May 28, 2009 8:39 PM
  • I have other project that I have to compare to, and it is a console project, so my idea is to make both of them look the same. I created an ATL project and I have _winmain as an entry point :
    extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                    LPTSTR /*lpCmdLine*/, int nShowCmd)
    {
        return _AtlModule.WinMain(nShowCmd);
    }
    You said it is not dificult to modify this in a way that shows me a console window, do I have to change this code to

    int

     

    _tmain(int argc, _TCHAR* argv[]){} ?

    And then how to proceed?

    Thursday, May 28, 2009 8:55 PM
  • No, I wouldn't. If you want a console, call AllocConsole(). You still haven't told us why you want one though.
    Thursday, May 28, 2009 9:20 PM
  • I have other project that I have to compare to this one, and it is a console project, so my idea is to make both of them look the same. I created ATL project and I inserted my .idl file contain. I put AllocConsole() and to write sth to the output I have to use std::cout?? What is the fastest way to write something to the output in this case?
    Thursday, May 28, 2009 9:47 PM
  • AllocConsole() hooks up the standard output handle so you can write to the console any way you want. std::cout is just fine, although it is typically a hair slower than printf(). fwrite() is probably faster but not as convenient to code.

    This really has nothing to do with your original question. I suggest you start a new thread for any new questions that come along.
    Thursday, May 28, 2009 10:00 PM
  • Thank you very much for help.
    Thursday, May 28, 2009 10:09 PM