I currently have a .NET class library written in C# that exposes its functionaility via COM to a C++ program (pre-.NET).
We now want to move the library out-of-process to free up address space in the main application (it is an image-processing application, and large images eat up address space). I remember from my VB6 days that one could create an "OLE automation server". The OS would automatically start and stop the server .exe as objects were created/destroyed. This looks like the perfect fit for us: as far as I can see nothing would change in the client except it would call CoCreateInstance with CLSCTX_LOCAL_SERVER instead of CLSCTX_INPROC_SERVER.
How would I create such an out-of-process server in C#? Either there is no information online about it, or my terminology is off/out of date!
You can actually do this in .NET (I've done it before as a proof-of-concept), but it's a bit of work to get everything working right (process lifetime, registration, etc).
Create a new Windows application. In the Main method, call RegistrationServices.RegisterTypeForComClients- this is a managed wrapper around CoRegisterClassObject that takes care of the class factory for you. Pass it the Type of the managed ComVisible class (the one you actually want to create- .NET supplies the class factory automatically) along with RegistrationClassContext.LocalServer and RegistrationConnectionType.SingleUse. Now you have a very basic exe that can be registered as a LocalServer32 for COM activation. You'll still have to work out the lifetime of the process (implement refcounts on the managed objects with constructors/finalizers- when you hit zero, call UnregisterTypeForComClients and exit)- you can't let Main exit until all your objects are dead.
The registration isn't too bad: create a ComRegisterFunction attributed method that adds a LocalServer32 key under HKLM\CLSID(yourclsidhere), whose default value is the path to your exe. Run regasm yourexe.exe /codebase /tlb, and you're good to go.
You could always expose your .NET class as COM classes using InteropServices and then configure the library as a COM+ application. The .NET library would run out-of-process and be hosted by a DLLHOST.EXE instance.
Here is an article in MSDN that covers all aspects of how to create COM localserver in c# (.net): link
Your post started a while ago and I had the same problem. The following link is absolute gold and tells you everything
http://www.andymcm.com/blog/2009/10/managed-dcom-server.html
Related
I am creating a web app using ASP.NET. This web app creates an instance of a C# class. This C# class instantiates a COM component written in c++. The C# class calls multiple functions in the COM dll sending a lot of data (read from an ascii file) through the COM interface. The COM dll then does calculations and returns data to the C# application using structures defined in the COM IDL. The COM dll was originally creating us MS C++6.0 but is now built using VS2012.
I see that when I access the web app from 2 different computers, 2 instances of the C# class are created, as I'd expect. Each instance of the C# class creates an instance of the COM component using "new MyCOMInterface". When I look at each instance of the COM interface, they have different addresses, which is what I'd expect. I then start the calculations on both computers. The initial sets of results that get returned from both runs of the web app are correct on both computers. But, if I then press the "Next" button on computer1 (to get the next set of results, which should be sitting in memory in the COM dll), the new results are display on both computers!
I put the C# class within a Session to try to fix this but it did not work. If I then try to get the "Next" set of results from computer2 (by pressing a "Next" button in the web app on comuter2), the results displayed are the next results from computer1.
I am trying to determine if this is a problem in the web app or if my 2 instances of the COM dll are not really independent (are they somehow sharing some memory)? I know that when I run my COM component from two different instances of an .exe, all memory is separate, but I don't know if this is true in a web app.
COM loads and frees libraries using the standard LoadLibrary(Ex) and FreeLibrary routines. These routines load only a single copy of each DLL and maintain a count on the number of times they have been called. When this count reaches 0, the DLL is truly unloaded.
This means that all COM objects served by a DLL (or OCX or other in-process container) will share the global state of their containing library. This is true no matter what isolation is provided by other frameworks like .NET or ASP.NET -- COM doesn't know anything about .NET's AppDomains, for example, and therefore it cannot maintain a separate copy of the DLL per AppDomain.
What you are seeing appears to be bad global state management in your COM DLL. It sounds like it needs to be reimplemented so that the state is managed per object instance.
When I try to Convert HTML to XHTML Tag I'm getting the following error...
Error: Retrieving the COM class factory for component with CLSID
{59939390-0E6A-4F1B-A742-20C5459501F7} failed due to the following
error: 80040154.
After googling I found few solutions:
Registering the DLL into regsvr32 "E:Source
Code\bin\Interop.HTML2XHTMLLib.dll"
I'm just tried to register the dll. But E:Source Code\bin\Interop.HTML2XHTMLLib.dll was loaded. But the DllRegisterServer entry point was not found this error message was displayed. Why..?
Recompiled my project for x86 and x64.. no use..
VB.NET Code:
Dim xhtmlUtil As New XHTMLUtilities // Here itself im getting the above error.
sFormattedOutput = xhtmlUtil.convertToXHTML(sInputline) //Send it for conversion
My Operating system is Windows XP 32-bit Service pack 3. My application was done in VS2008. currently I'm working with VS2010.
Here what I'm missing. Could any one help me to figure out this problem?
Thanks in advance.
i'm just tried to register the dll. But E:Source Code\bin\Interop.HTML2XHTMLLib.dll was loaded. But the DllRegisterServer entry point was not found this error message was displayed. why?
The Interop.HTML2XHTMLLib.dll file isn't the library you want to register using regsvr32. It is only the managed interop assembly, generated make COM objects accessable for your .NET application. You actually need to register the type library for the HTML2XHTMLLib.dll.
To do this, you have two options:
Find the redistributeable package, that contains the library and install it together with your application.
On your development system, open the "Add references" dialog of Visual Studio. Choose the COM tab and search for the library (just like you did when you've added the reference). There you will find the absolute path to the library. Copy the library to the client system and register it using regsvr32.
Since I do not know the source of the HTML2XHTMLLib, I can only suggest those ways. You should prefer the first one.
Since you've started a bounty on this, I want to go a little bit more into detail on COM and the InterOp.
Differences between COM and .NET assemblies
There are two types of servers in COM: InProc-servers and OutProc-servers. InProc (In Process) are servers we usually know als DLL. OutProc (Out of Process) servers are standing alone, running in their own process. We know them as EXEcutables.
You want to consume an InProc-server. Your COM-server (HTML2XHTMLLib) consists out of two parts:
A type library (.tlb), that contains meta-information about the server, it's contained objects and their accessability.
A library, containing the code where all the objects are implemented. The library also exports the following static functions:
DllGetClassObject – Tries to create an instance of an object, defined inside the server
DllCanUnloadNow – Tells the COM environment, whether or not the server can be released, because it isn't used by any other process any more.
DllRegisterServer – Called by regsvr32 to register the previously mentioned type library in the Windows Registry, to make it visible to clients and the COM environment.
DllUnregisterServer – Does the exact opposite, when called through regsvr32 -u.
The type library can also a resource of the DLL or EXE file, so that there's only one file. For C# developers this seems somehow confusing, since meta-information is directly compiled into a.NET assembly and accessable through reflection.
The InterOp: A wrapper between .NET and COM
So basicly type libraries describe everything that is needed by the .NET reflection to access the objects exposed through COM. But the problem is, that COM-components are stored in a different format:
Usually they are directly compiled into machine code: You cannot link a .NET assembly, compiled with AnyCPU against a COM-server. COM-servers are directly compiled to either x86-assembler, or x86-64-assembler. They have fixed pointer sizes and thus are only compatible with one of the compilation-models.
COM defines rules for memory management. Each COM-object must implement the IUnknown-interface. This interface defines three methods. The methods AddRef and Release are for memory management purposes. Whenever a client accesses an COM object it needs to call AddRef. This increases a counter by one. When the client does not need the object anymore, it calls Release instead of deleting the object, resulting in a counter decrement. If the pointer reaches 0, the object delete's itself. This is different from how .NET manages memory. In .NET the garbage collector visits each object on the heap in a non-deterministic manner (you cannot determinate the exact point of time an object get's deleted) and releases the object, when there are no references left to it.
COM defines rules for identity. Whenever you only want to access an base interface of an object, you have to call the QueryInterface method, defined by IUnknown. This method is guaranteed to allways return the same pointer, when a specific interface get's queried. This might be also true for .NET (besides you are overloading some operators), but the way .NET ensures object identity is different.
COM defines rules for object relations. Crazy stuff like Aggregation and Containment, which do also exist in .NET, but are implemented differently.
COM defines different multithreading rules, like Single Threaded Appartments and Multi Threaded Appartments. Those threading models define how objects interact, when they are coexisting in different manners. In .NET you have to perform each synchronisation process manually.
This list may not be complete, neither I want to go into detail any further, because it is only incidental for your question, but you see, that there are some big differences between .NET and COM. And to manage those differences there is a layer between both worlds: the COM InterOp.
If you are calling a COM server from .NET, the InterOp is nothing more than a .NET assembly, that does all the hard work under the hood. It get's created using the tlbimp.exe tool. Visual Studio typically calls it for you whenever you are referencing a library from the COM tab. The result is the library you wanted to register: InterOp.Libary.dll. This library redefines all types of the type library of the COM server, implements the rules required by COM and performs the actual calls for you. However it is a managed .NET library which does not define the methods, described earlier. This is why regsvr32 cannot find the DllRegisterServer entry point.
The way described above is only a one-way with an unmanaged COM server and a managed .NET client. There is also the other way, with the counterparts tlbexp.exe and regasm.
I have a 3rd party COM object(32 bit) that I need to call from my c# application (64 bit).
I know I have to run the COM object in a separate process.
This COM object has many classes implemented in it, so I'm trying to avoid writing my own remoting wrapper that exposes all the methods. COM+ seems to be the most straightforward solution. I opened the Component Services menu, created a new COM+ Application, added my COM object as a component to this application. Everything seemed to import beautifully.
In my C# application, I added the original COM object as a reference (which automatically generates the type library). Using the type library reference, I can create objects from from the COM+ component (I see them begin to spin in the Component Services window), but when I try to access on of the methods of the object, I get an error saying the interface is not registered.
Does anyone have a clue? I went back and ran regsvr32 on the COM object, but I don't think it was necessary, and it didn't help.
Is my usage in C# correct? VS2008 autocomplete had no problem seeing those methods.
The exact exception is:
"Interface not registered (Exception from HRESULT:0x80040155)"
Unclear about exactly what the permissions and roles are about in the Component Services, I tried setting up the COM+ object identity to run under the System Account, both as a local service and as interactive user. I've added Everyone as a user in the Roles.
Everything is running locally, so there shouldn't be an issue with file privileges or anything like that.
I also want to reiterate that this COM object contains many classes. I successfully instantiated one class object in my client and set some property values.
I also successfully instantiated another class object, but received this exception when attempting to call a method of this second object .... so I don't think there is an issue with which registry my COM object is registered in.
We had a similar situation, working with a COM dll from VFP.
It all depends on rights and permissions, like Yahia says.
We got it working by doing this:
Install VFP oledb 9 drivers (dunno what you have so probably not required).
give Network Service IIS_IUSR full control on the COM folder (required so the DLL can do some logging in its own folder, when called from the website).
run regsvr32.exe "c:\xxx\yourfile.dll" -> this should be successful!
Create COM+ application, and add the DLL as a part
Set the application COM+ credentials on a user wigh sufficient rights
and we had to do some more settings on rights in application pool / IIS, but thats not required for you I guess.
Anyways, just make sure you have enough logging, make sure the dll is registered, and after that its all about rights rights rights..
Good luck with it!
Sorry to use the "Answer" to respond to comments, but it seems to be my only avenue.
The whole purpose of moving to a 64bit operating system was to gain the extra addressable memory space, so running the entire application in 32bit mode is not an option.
It might be relevant to the problem that after successfully creating three class objects, I was able to set properties in one, call a method with no arguments in the second, but it was calling a method in the third, which took the other two objects as arguments that threw the exception.
That's what I wanna achieve :
There will be dll which contains only methods which calls my actual methods from my application and I can share that dll with outside world regardless of which methods it includes because actual methods will be in the dll in my application but if some one uses that outside dll he/she can manages to get my application to do something in limits of I desire.
I hope I could describe what I want. I don't know if you have ever used Skype4COM.dll. It actually works like that, it somehow connects to Skype Client and let me call some one I want. For example :
Skype s = new Skype();
s.PlaceCall("phoneNumber");
I import Skype4COM dll in my project and when i write code like above in C#, it connects to Skype and make a call.
I think there is no actual methods which makes calls in Skype4Com.dll. I think it only does have some sort of methods which reach actual methods in Skype API and make the call so whatever the developers change in Skype, it doesn't affect Skype4Com.dll wrapper as long as signature stays the same.
So, that's what I want to achive, I am not quite interested in writing wrappers tho, that was a sample case, I want to write a dll which reachs my API and uses method signatures and let people use the application from outside so as long as the signatures stay same, if I want to change something between block I don't need to change the dll given out to outside..
Thank in advance....
If I understand you correctly, you want to expose a limited subset of the functions of your application to outside users. In effect, you want to offer a service, but nothing else.
Then you should use Windows Communication Foundation to host a service inside of your application (or elsewhere). This service could use industry-standard protocols like SOAP; or could use REST; or it could use faster binary transfers over TCP/IP for your .NET clients.
It's perfect for a service-oriented situation like yours.
What you're describing is a COM wrapper around Skype. If you really want a COM wrapper around your C# DLL, you can do that. Microsoft has provided an example that demonstrates how to create a COM Class from C#.
If you're looking into providing a wrapper around your code from managed DLLs, then it's as simple as providing a public interface that consumers of your DLL can use. You'll probably also want to install your code in the GAC (Global Assembly Cache) so that anyone that wants to call into your API can do so without putting copies of your code all over their system.
You could make everything internal instead of public inside this DLL. Internal keyword restricts access to classes, methods or properties to assembly while public keyword allows access from other assemblies
I have a .NET C# WPF application that I am trying to make into a single-instance application using a Mutex.
This .NET application is called by a C++-based DLL using CreateProcessAsUser() and is given parameters via environment variables.
Subsequent instances will also be created by the C++ DLL in the same way.
Subsequent instances would then need to pass their parameters to the first instance of the application before exiting.
The problem is what methods can be used in the .NET application so that the subsequent instances would be able to pass their data to the first instance of the .NET application? The simpler, the better.
I have researched some but I hope there are simpler ways.
Things I have researched:
Named Pipes
.NET Remoting
Windows Messaging (Sending WM_COPYDATA to the first instance window)
Since I am just trying to pass 4 strings to the first instance, I am trying to avoid the above mentioned methods because they are somewhat overkill for my problem.
The simplest I can think of is to export a function from the .NET application so that the subsequent instances of the .NET application can just call this function on the first instance of the .NET application and pass the data as the parameters of the function. However, is this possible in .NET? I've read that .NET EXE or DLLs could not export functions.
Thanks!
The simplest I can think of is to export a function from the .NET application and then the subsequent instances can just call this function and pass the parameters to it.
This is not how this works. You'll load the .NET assembly in the calling process, not magically cross the process boundary and talk to the child.
Just have the parent open the child with redirected pipes using the Process class, and have the child read from stdin using Console.Read*
thanks for the reply, Paul!
I've added more detail to my question above, though, coz I'm not sure if my scenario was understood correctly.
But regarding your answer, the parent of the .NET app will be a C++-based DLL and all it will do is call the .NET app and give it parameters. The C++-based DLL will also exit after this so I wouldn't want to add anymore behavior to it.
So, passing of data would then be done between the instances of the .NET applications only.
Since you are going from .NET to .NET, I'd recommend just doing a WCF call. You can use a named pipes transport between the two .NET instances to expose the "service" (which is what your first instance would expose).
Subsequent instances would do the single instance check, and if they detect an already running instance, they could make a WCF call to the service running in the first instance and pass the data that way.