Looking at registration-free COM it is still unclear to me whether you can just take any existing, completely unaware COM component(*) and use it in a registration-free way by adding the correct manifest files.
Is this supposed to work in all cases.
What's with the apartment stuff (comInterfaceProxyStub) they are talking about?
(*) : (e.g. an ocx file or another in-process COM server DLL that is supposed to be used with regsvr32
Yes, no problem. The manifest simply provides the configuration that COM normally reads from the registry. Thus the term "registry-free". The typical problem with writing one for a 3rd party server is that you don't know the guids. Observe the changes that Regsvr32.exe makes to the registry with SysInternals' ProcMon or ask the vendor for help.
The "apartment stuff" is just additional config, the keys written to HKLM\Software\Classes\Interface. Required by COM when an interface call needs to be marshaled from one thread or process or machine to another. COM needs help to figure out how to serialize the method arguments into an interop communication packet. It doesn't know what the function looks like so needs the help of a proxy and a stub. A helper DLL registered with the ProxyStubClsId32 key provides the proxy and stub implementation. Auto-generated from the IDL or provided by the standard Automation marshaller that uses the type library to discover the function declaration. The comInterfaceProxyStub element provides the manifest version of that registration.
Related
I have a 3rd party legacy app that requires a VB6 Active X EXE library interface. I am looking to update the VB6 Active X EXE library to a currently supported language. As the legacy host application is from a 3rd party I do not have the ability to change the host API to use an interface other than ActiveX EXE. Is there any currently supported Microsoft language i.e., x86 C++, C++/CLI, C# or VB.NET that can create the equivalent of an ActiveX EXE interface?
I suspect the answer is no but am looking for a definitive response saying so. That any legacy host application using ActiveX EXE library must be itself be modified to allow the use of supported languages and tools. Basically confirming that effectively ActiveX EXE is now an unsupported API interface.
I've already looked at this similar question and from it one could deduce that the answer is no but there is no definitive response. I've also looked at this Microsoft Tutorial and from what I can tell it talks about updating the host application which isn't an option in this case. The tutorial talks about switching to an ActiveX DLL but my understanding is that this would require a change to the 3rd party host application. Again that is not an option in my case. I need something that looks like an ActiveX EXE library to the host.
If you are sure that an ActiveX Exe is required, have you considered just using VB6 to create the that as a thin shim and then have it delegate all implementation to a .NET assembly? You probably would never need to recompile the Exe again, unless the 3rd party vendor is still expanding their interface.
If you post some more information about the VB6 Active X EXE library interface, I might be able to refine this solution with specific code samples. Presumably your Active X Exe must implement a provided interface?
My website application uses C# COM+ components running under a particular identity to access SQL Server, invoked from classic ASP.
There's also a web service that utilises a \bin DLL in the website application that contains a method to insert some data into the SQL Server database (let's call it MyApp.Database.dll).
From the website front end, I want to be able to provide authenticated users with this same functionality.
I don't want to duplicate code in MyApp.Database.dll within the COM+ component for obvious reasons.
My idea was to utilise the COM+ component from ASP to invoke the MyApp.Database.dll method to access the SQL database using the application credential since the ASP is running as the user and has no access to SQL Server.
Problem I've seem to run into is that although I can reference MyApp.Database.dll in my COM+ component project (under 'References' and 'using MyApp.Database.dll'), when it comes to actually running or debugging the COM+ component, when it tries to invoke the method from MyApp.Database.dll, it tells me 'Could not load files or assembly 'MyApp.Database, Version=3.3.3.11658, Culture=neutral, PublicKeyToken=.....' or one of its dependencies.'
The MyApp.Database.dll is not registered in GAC (trying to avoid this, it's also used by other applications as well), and hasn't had its codebase registered in the registry using regasm (I tried this and still didn't work). The version is correct, and I've placed MyApp.Database.dll in the application folder of the COM+ component.
Am I missing something or is it not possible to do this?
Thanks in advance for your help.
This is a common mistaken expectation: just because your .NET COM DLL was found in some given folder (the folder set by the /codebase argument or RegAsm) -- it doesn't mean .NET will look on that folder for anything else.
Generally speaking, it won't. Loading a .NET assemblies via COM interop is a special case. For everything else, assemblies will be loaded in the AppDomain based on the Fusion binding policy for the process - which has nothing to do with where your .NET COM DLL is. The process is actually (depending on your version of IIS) either dllhost.exe, iisexpress.exe or w3wp.exe.
You have a few options.
First, the obvious solution is putting MyApp.Database.dll in the GAC, since .NET always looks there. Sometimes that's the right choice (I've done that and it works). You have declined to do so and you have your reasons; that's Ok.
Second, I believe you can change the binding policy with a web.config file. See here: http://msdn.microsoft.com/en-us/library/823z9h8w(v=vs.110).aspx. Yes, your ASP Classic project can have a web.config. Obviously it has no effect on your ASP Classic scripts, but (depending on the version of IIS), .NET and/or IIS itself use it for configuration. I'm afraid that I can't help you much with this alternative because I've never had to try it before, but you're welcome to explore that option - let me know how it goes.
Third option - my personal choice: You said this DLL is already a web service, right? Just call the functionality with a web service call from your COM DLL. That doesn't require mucking with magic folders, GAC and binding policies. Much cleaner. The only mild complication is tracking in configuration where your web service is located - and I bet you already do that for your database connection anyway, so it shouldn't be hard to add.
If you are curious to know where .NET is looking for the DLL, read up on these guys:
How to enable assembly bind failure logging (Fusion) in .NET
http://www.hanselman.com/blog/BackToBasicsUsingFusionLogViewerToDebugObscureLoaderErrors.aspx
http://www.hanselman.com/blog/MoreOnAssemblyBindingStrongNamingTheGACPublisherPolicyAndDynamicallyLoadedAssemblies.aspx
Good luck, and please let us know what worked for you.
I'm in need of distributing several old COM applications that are to be installed on locked down computers. I'm trying to get these applications to launch without having to be registered in the registry via regsvr32 or in the case of an EXE component via the /regserver switch. I can control and locally copy all the required dependencies in this scenario.
I know this is possible, however, I'm having a real tough time piecing together the different pieces or finding coherent information on how to set this up.
Any help or pointers would be greatly appreciated.
Microsoft has a good tutorial on Registration Free COM.
There are two basic parts to getting registration free COM working.
First, you need to convert the COM dlls to an assebmly: Just the COM dll's, and create a manifest describing them, and give it a name. Bundle this assembly in the same folder as your application.
Next, you need to tell your application to use the assembly you just created. When COM tries to create a new object, it will first look in any assemblies registered in the default activation context, before looking in the registry.
Registrationless COM can be tricky to set up but the overall process is not very complex. I wrote up my process along with some tools that help with debugging problems in a blog post here:
http://www.west-wind.com/weblog/posts/2011/Oct/09/An-easy-way-to-create-Side-by-Side-registrationless-COM-Manifests-with-Visual-Studio
FWIW, registrationless COM doesn't work with DCOM EXE servers unfortunately - only DLL servers are supported.
This question is a follow-up to the answer given by Marc Gravell to my question Create Out-Of-Process COM in C#/.Net ?. I have chosen his proposed solution, but now am running in a different issue.
Here is my situation:
I implemented a "DataProvider" COM component in C#
This component is hosted in a COM+
Server application so that multiple
processes can access the same
instance of the DataProvider
The types of processes that can access the data provider through COM are Matlab, VB Scripts and .Net applications.
When instantiating the COM DataProvider from Matlab or VB Script, the COM+ mechanism kicks in and I can verify that a single instance of the DataProvider can be used.
The problem comes when I try to access the COM+ managed instance from .Net. Basically, when a COM component is based on a .Net DLL, even with lazy loading, .Net always seems to find the DLL and instantiate the object from there, skipping the whole COM mechanism. This is expected for performances, but it does not help in my case.
Now for the question:
Is it possible to instantiate a .Net written COM component in a .Net application using the COM mechanism?
Note that the following code does not use the COM mechanism:
Type type = Type.GetTypeFromProgID(progID);
return Activator.CreateInstance(type);
Look into this answer. The assembly must be added to the GAC first and then the COM+ application must be created using the regsvcs utility. Otherwise, .Net doesn't look into the COM+ catalog at all:
"c:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe" MyObject.dll
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe" /i MyObject.dll
We've got some code that uses LoadLibrary and GetProcAddress to implement a plugin architecture for one of our products. We ensure that the DLL about to be loaded is signed with our code-signing key.
We're changing the plugin architecture to use COM instead. Is there a way to enforce code-signing (preferably with our certificate) when instantiating a COM object?
You need to do this at the DLL level using the Authenticode API. The standard API is called WinVerifyTrust() and there are samples documented there. There's another KB article number 323809 that gives an example of how to peel other details out of the authenticode information attached to your DLL.
Of course, these APIs expect to be handed a path to the DLL itself whereas in a COM plugin scenario you usually don't directly touch that but instead rely on registration to find the right binary. You can either hand-roll your load scenario (i.e. load the DLL using LoadLibrary() and call DllGetClassObject() yourself) or simply require users of your API to adhere to additional rules such as placing the DLL in a certain location regardless of registration.
Or as Rob Walker suggested, look up the CLSID registration in the registry yourself and use that as the way to find the right DLL to verify.
I don't think you can do this directly, but you could look up the DLL that the CLSID uses in the registry and check its signature before issuing the CoCreateInstance call.