Regasm writes mscoree.dll into Registry key InprocServer32 - com

When I register my .NET Assembly with regasm.exe the registry key
HKEY_CLASSES_ROOT\CLSID{111E32AD-4BF8-495F-AB4D-6C61BD463EA4}\InprocServer32
is set to "mscoree.dll".
However, I am trying to mimic an existing COM-Server that was written in C. When registering this old COM-server the InprocServer32 is set to the full path to this component.
Unfortunately the existing system (a plugin host that I can not change) reads and use this value - an is confused by the "mscoree.dll" value.
My solution might be to patch this registry entry manually - but I would like to understand why regasm writes "mscoree.dll" into InprocServer32 .

The explanation is quite easy. When you use a native (unmanaged) COM server in-proc, it is loaded into the consumer process and the consumer process directly calls its functions.
This can't work that easily with a managed code COM-exposed assembly. In case of managed code an intermediate layer is needed that performs the managed/unmanaged interaction. mscoree.dll acts as this intermediate layer. So when the consumer calls CoCreateInstance() mscoree.dll is loaded and emulates the COM server by loading the COM-exposed assembly managed code and forwardind all calls to the latter.

Related

Use of DllRegisterServer

DllRegisterServer is called, when Windows or OLE wants me to register my classes under HKEY_CLASSES_ROOT\CLSID. But I don't understand why this function has to be implemented, because when Windows/OLE can make calls to my DLL, then my classes are already registered with their CLSIDs and their path to the correct DLL. Can somebody tell me, what I am misunderstanding?
You are confounding the chicken and the egg. In order for COM to help a client app to create objects and marshal calls, it needs to know where your COM server is located. The client app just uses a number, a GUID, to tell COM what object it needs. The mapping from a GUID to code in an executable file requires COM to know where that file is located first. And, if necessary, how to marshal a call on an interface from one apartment to another.
It is registering the server that provides COM with that knowledge. It writes keys in the registry that COM uses to find the file back. Like the CLSID key, its InProcServer32 sub-key provides the path to the file. Etcetera. Or the manifest embedded in the client app if it chooses to use reg-free COM.
Observing this with SysInternals' Process Monitor can provide a lot of insight. You'll see what DllRegisterServer() does and how a client app uses those keys.
For the peoples wondering about Title of Question
Example of COM object is Dynamic Context Menu ( which would be a DLL)
to register it-
First Make a Random GUID under HKEY_CLASSES_ROOT
Under That GUID make key named "InProcServer32"
set value of this key as full path of your DLL
This is called Manual Registration
people's with no knowledge of registry editing should also be able to register your dll too.
for that, you should write codes to make these GUIDS and InprocServer32 keys etc programatically Under the DLLRegisterServer() Function in your DLL
so that , people with no knoledge of registry editing will be able to type -
regsvr32.exe "full path of your DLL"
in command prompt for registring your DLL
when they type that command, regsvr32.exe will do nothing but call that DLLRegisterServer() in your DLL
and by calling this function, codes of writing registry keys such as making random GUID and InprocServer32 keys will be Executed ( which you have written )
so registry entries will be made and that is called Registration.
so , according to me regsvr32.exe was just created for the people who have less knowledge of how to edit registry.

COM in a Windows form EXE using Visual Basic/Visual Studio 12

I don't usually program in the .NET framework however I've needed to use it to create a simple exe application that logs data from some measurement equipment. I want this application to have an automation interface with a couple of methods. I've done this before using Delphi/Pascal and it was very straightforward, and I can create a Class Library in Visual Studio that registers itself and the methods and can easily be interfaced with but adding a ComClass to the windows form application doesn't work, can anyone point me in the right direction?
This started as a comment but just kept growing, hopefully i am not off track ...
You can only register a dll. So the short answer would be to add a class library to your project and put the com class in there. This would allow you to share the functionality of the class, but not the same instance of that class.
I think your problem is that you are trying to establish Interprocess Communications. My immediate suggestion is not to do that, at least at first.
For a start you could have your com app interface with a .net class library which would log data. You could then have another project with a .net executable that displays the log, and updates periodically. Now you have .net code on both sides of the fence and can start investigating ways to get them to talk to each other.
The hard part is invoking methods and returning values. If you really need a responsive system you can investigate named pipes inter-process communication, or using a WCF service with callbacks between the two systems. The problem is that in either case you are hamstrung by the class library not being hosted by .net so you have limited functionality (no config file etc). If you can put up with a time lag I would suggest simply starting with writing messages to a local datastore and then polling from each client, every 30 seconds or so. For example the app would create a message saying "give me measurement A" and then start polling every second. The DLL would have a timer and within 30 seconds would read that message and write its own message with the measurement, which the EXE would read and then display. Once you get that system up and running you can decide whether you need to tackle inter-process communication, which is really just a different interface.

Rewriting a dll file when using MEF and WCF

On my current project, I'm sending dll files to clients using a WCF service.
The dll files contain UserControls which the clients use to visualize data.
However, sometimes new UserControls are introduced by the service, without the clients knowing about this. When this happend, I send the new dll file to the clients so they have the latest version of the UserControls.
However, when I want to write this new dll file on the clients HD (using a FileStream), I get an exception saying that the file is used by another process (of course, the clients always have an assembly version of the UserControls on their HD, so this has to be overwriten).
Is there any way to overwrite this file without getting an error? I'm using MEF to read the assembly files in the client project. To send the assembly file to the clients, I just send the filename as a string and the file's content in a byte array.
This is usually done with Shadow Copying, but I can't find anything definitive as to whether it works with MEF.
If its acceptable for your new control to be loaded on closing and re-opening the application, then you can copy all your plugins prior to composing with MEF.
Here is a blog post with somebody essentially trying MEF + Shodow Copy, and a particularly relevant comment.
The fundamental problem here is that
.NET doesn't support dynamic assembly
unloading. You could reload the
assembly, but you would never be able
to recover the memory used by the old
one

Who is responsible for calling CoInitialize and CoUninitialize if surrogate process or COM+

Who is responsible for calling CoInitialize and CoUninitialize if
1- I host a COM dll within a surrogate process (either by using dcomcnfg utility or COM+ wizard)?
2- I build a ISAPI DLL that contains COM objects?
No idea on case 2, but in case 1 the surrogate process certainly calls CoInitialize()/CoUninitialize(). Here's how I know this.
We have a COM object that we host in COM+ and that itself uses MS XML 4. When you need to create an XML document object in MS XML 4 you call CoCreateInstance(). We never call CoInitialize() in our COM object, yet document creation is always successful - certainly the surrogate calls CoInitialize(). If we do the same in a stand-alone app document creation fails unless we ourself call CoInitialize().
So the bottom line is: COM+ surrogate (and I'm sure that applies to DCOM surrogate as well) calls CoInitialize() itself.
Btw you can use this to investigate the case 2 - call CoCreateInstance() inside the ISAPI dll - if it is successful CoInitialize() has already been called.

Simulating SideBySide for Out of Process ActiveX

We are adapting our client side relatively complicated application (ActiveX / .net / Delphi / C++ / COM ) to use SxS to achieve non admin deployment and isolation from older versions of our product.
We were able to achieve this goal for almost all our in proc components such as our .net ui, Delphi ui, and the COM servers we use in proc by composing a manifest file which described all the libraries used by our process, with no registration on the client of any of the components (almost).
And here comes the almost part:
At the moment, our application invokes (from it's c++ portion) an out of proc ActiveX server (Delphi ActiveX EXE), which in turn itself invokes another set of out of proc ActiveX servers (third party plugins, any thing goes here, Delphi, C++, any thing as long as it's out of proc ActiveX EXE and implements our interfaces).
As we know SxS does not support out of proc ActiveX servers. And we can't use these objects as in proc com servers in our main process because that would require a major rewrite of our application and even worst, a break of our public facing API which is used by third party tools and vendors, an api break which we can't allow.
We have stumbled on this article which describes how IHTMLDocument2 can be extracted from an Internet Explorer window running in a separate process. Which made us think of this approach:
We would create a secondary satellite application / process which will run the ActiveX as in process server.
Then we will use LresultFromObject and ObjectFromLresult to transfer a reference of the ActiveX object from the satellite application to the main application process. The satellite application will have it's own manifest file which will allow it to run in SxS mode.
Same approach will be taken to communicate between this Delphi ActiveX EXE and the third party AciveX EXE Plugins
There is an alternative solution, which for the moment we do not prefer over the proposed solution above which is to use .net remoting and .net com proxy classes to open the communication channel between the two processes, by translating the com request to .net remoting, and back to com on the second process.
So here comes the question:
What do you think about this approach ?
Do you see a better solution to the problem ?
It is possible to do. What is needed:
An application needs to start a server itself rather than relying on COM to do it. You don't need the extra indirection provided by the registry, just use CreateProcess().
A server should register its class factories in its main() method with CoRegisterClassObject().
Important: the CLSID it uses for each factory should be altered to be unique for each service instance. This ensures that the client connects to the correct server. I simply XOR the process ID with a class factory CLSID. The client knows the process ID as well so can make the same alteration.
The application should call CoCreateInstance() in a loop with a Sleep() call to wait for the object factory to appear. Don't declare failure until at least 60 seconds have passed (that bit me).
Both the application and the server need a manifest that contains a <file> element for each proxy/stub DLL and <comInterfaceExternProxyStub> elements for each interface that is remoted.
Alex,
nobugz is right, you can access the Running Object Table to create an instance of a COM Object from a currently running process of your Delphi automation exe.
However I have found a big issue that I cant explain. I can only access the object via the variant dispatch method when working this way.
Basically if my Active X exe is not registered, I get an "Interface Not Supported" error if I try to instance the object through interfaces for example:
WebUpdate : IAutomation;
WebUpdate := CoAutomation.Create; <-- Wont Work Error
WebUpdate : Variant;
WebUpdate := CreateOleObject('WebUpdate.Automation'); <-- Works Fine
If I register the active x exe using regserver the problem goes away!!
Go Figure!