I am learning how to implement an out-of-process COM server and came across this Code Project article, Building a LOCAL COM Server and Client: A Step by Step Example.
I can build it, and it runs fine, but where is the proxy/stub DLL? All I can see is the IDL file from which the proxy/stub code is generated during the build. But how is the DLL built, and where is it?
The short answer is that all the interfaces are marked "oleautomation", so oleaut32.dll performs the marshaling, since COM knows how to marshal all the types used in the interfaces.
If "oleautomation" were missing, or a type was specified that COM doesn't know how to marshal by default (see the list here), your nondefault marshaler and its stub would be required.
You need Proxy/Stub project to help COM marshal your interfaces. When you create ATL C++ project with Visual Studio you typically have a secondary project with PS suffix created automatically, and this is your Proxy/Stub DLL. However, you might be doing fine without it at all (I personally never ever had to build and use it, even though I did have to deal with things like custom marshaling). If you provide type library with your project, it is registered and certain conditions are met - COM will supply automatic proxy/stub pair for you.
Bonus reading:
COM Proxy/Stub DLL and why do you need it
When Proxy/Stub Pair is Necessary
Related
I'm currently trying to get a rather tangled scheme running with registration free COM.
It's not that it is not working, it's that I have hit a kind of confusing situation, where it seems I should active the manifest of the assembly dependency directly in the application context, rather than have the application context point at the dependent assembly.
It is rather easy to explain by the example project MS themselves publish:
Normally, you have an application, an app manifest, a (server-)dll and it's assembly manifest. These correspond to what the example gives:
client.exe
client.exe.manifest (This one points to SideBySide.X as dependentAssembly)
SideBySide.dll
SideBySide.X.manifest
Now, one standard case is to embed the client application manifest inside the client executable, and then use the DLL and its external manifest file.
Now, if for whatever reason the correct application manifest isn't known at compile time, you can load a manifest file at runtime via the Activation Context API.
And this is where it gets confusing:
According to the article, the client application now directly switches its Activation Context to the assembly manifest:
If you look at the _tmain function in client.cpp ... a new section of code that initializes the activation context as follows:
actCtx.lpSource = "SideBySide.X.manifest";
I have cross checked this, and it would also work to dynamically load a file that contains the info from client.exe.manifest, i.e. just the reference to SideBySide.X, and continue with this Activation Context - which would also correspond to the ActCtx in use when we embed a correct application manifest into the executable.
That is, actCtx.lpSource = "client.exe.manifest"; would also work.
TL;DR What is the implication, if any, of directly activating an Activation Context "containing" an assembly manifest inside application code.
Is this how it's supposed to be done when loading manifests from files? (And if so, why can't we directly embed the assembly manifest into the executable, when it is known at compile time.)
Note: (This should really be a comment to #Eric Brown's answer, but it's getting rather lengthy)
The linked article does a decent job of explaining the two RT_MANIFESTresource types, but with regard to regFreeCOm, it leaves a few loose ends. I'll throw in some quotes that jumped at me:
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. ...
the NT library loader checks to see if the
dll has a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID. If it does, the loader calls
CreateActCtx with the resource, and use the generated activation
context to probe the dll's static dependencies.
What I understand this to mean is that the only point of RT_MANIFEST/2 is for the static DLL dependency loader to find the correct resource to use for resolving DLL dependencies. (Not COM dependencies, see below.)
Sometimes, you want to use the activation context outside of probing
the dll's static dependencies. You can define macro
ISOLATION_AWARE_ENABLED when you compile the module.
When ISOLATION_AWARE_ENABLED is defined, Windows re-defines certain
APIs. For example LoadLibraryExW is redefined to
IsolationAwareLoadLibraryExW.
... Not all APIs affected by activation context are wrapped. For example,
..., and neither is any of the COM APIs.
So, to sum up: I think the RT_MANIFEST mechanism is mostly orthogonal to regFreeCOM as COM doesn't care at all where it's activation context comes from and there is no built-in help for regFreeCOM wrt. Isolation Awareness.
Yes, this is how it's supposed to be done, and you can embed the assembly manifest into the executable (well, the resource section). That's what the RT_MANIFEST resource type is for. There are two default types of manifest resources
Process manifests, with ID CREATEPROCESS_MANIFEST_RESOURCE_ID (1), used during process creation,
Isolation-Aware manifests, with ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID (2), used during DLL loading.
There are a couple of uses (primarily around Click-once deployment) that illustrate the ability to embed registration-free COM manifests in subsidiary DLLs, using RT_MANIFEST. In particular, if a DLL has a CREATEPROCESS_MANIFEST_RESOURCE_ID, that manifest will be used as well.
An example seems like a good thing here.
Given
client.exe
sidebyside.dll
If sidebyside.dll has an RT_MANIFEST resource with ID 1 (CREATEPROCESS_MANIFEST_RESOURCE_ID) which has the appropriate registration-free COM entries in it, and client.exe has an RT_MANIFEST resource with ID 1 that has a <file> entry for sidebyside.dll, then Win32 will automatically handle the registration-free COM management.
Part 8 of the example article strongly implies this, and I've seen it done in a number of in-house projects.
I have a VB6 program which tries to run a DLL written in C#.
This DLL has a COM interface so I can create an object of a class in it with "CreateObject".
The problem is that it runs and works well when I run it from the VB6 IDE, but when I make an EXE and try to run it, it throws the exception:
"Automation error. The system cannot find the file specified (-2147024894)."
Why is it happening and how can i solve it?
Look at Project, References in the IDE and look which dll or ocx file belongs to the object you are referencing with CreateObject (the Object Manager might also help to find out).
This dll file must be available when the exe is compiled, too. Usually, you need to have it registered with regsvr32.exe.
A technique I use to figure issues of this type is to open the add reference dialog in Visual Basic 6. I scroll the list of available COM Libraries and see if the problem DLL is listed. If it is then CreateObject should work, you should be able to assign it do a variant variant and use late binding to access it's members.
In addition try temporally set a reference to the variable and instead of using CreateObject use the = New and see what error messages, if any, it gives you. Generally I found them to be more informative then the ones thrown by CreateObject.
Finally it would help if you post the reason why you are choosing to use CreateObject instead of setting of a reference. If the DLL is a known object that will be continually used by the program then a reference should be set and early binding generally used.
Finally it may be that the error is resulting from a dependency of the C# COM DLL not the DLL itself. If for example I was to take a Com Library and properly register it but it relies on the COM Library Widget2000 and it NOT registered then it will throw the automation error. Especially if you are testing the EXE in it's installed environment and not the environment in which you complied it.
For example suppose I have a CAD program written in VB6 and I have source tree that begins with MyCAD. THe exe is in MyCAD/MainEXE and the shape library is in MyCAD/ShapeLibrary. I run the IDE everything is fine. Then I make my setup and goto my test machine and install it and it error on the creation of shapelibrary.
The first thing I would do it check if MainEXE will run straight out of the MainEXE directory of my source tree. That test will eliminate whether it is a install issue or a quirk of the IDE vs complied version. Then I would look at the setup and see what not being registered. Also look at either the source for the C# library or the setup for the library and see what dependencies it needs. Since it a complied COM DLL you should be able to use a dependency walker tool to see what COM references it needs. Finally make sure the correct version of the .NET framework is installed.
If you are compiling the C# DLL on your test machine - make sure you have ticked the register for COM Interop setting. If you are not compiling on the same machine you need to run RegAsm with the /codebase option.
try compiling it as an installer and include the dll/com that you use in the compilation of the installer package so that the dll/com that you use will be include in the compilation of your exe.., and install it in the windows not just copy past it.
While implementing my own IFilter I found that most likely some consumers will require marshalling from it. That is they QueryInterface() the IMarshal interface from my object.
Proxy/stubs from MIDL can't be used - MIDL will not compile the filter.idl file - the latter uses custom structures and MIDL doesn't know what to do with them. So it looks like I need to implement marshalling on my own.
Where can I find a guide and samples of how to implement marshaling?
Check out this CodeProject article:
http://www.codeproject.com/KB/COM/CustomMarshaling01.aspx
For example, if writing a shell extension, is it necessary to register the typelib with CComModule::RegisterServer (i.e., I'm wondering if calling it with FALSE will cause some issues).
Hardly ever.
In theory typelibs would be used by IDEs that wan't to display lists of properties and methods on an object. OleSpy++ or whatever the tool is called can use typelibs to generate quite a lot of important information about the ActiveX
In MSVC you can use #import on a ActiveX with embedded typelib and header files describing the interfaces and types will be automatically generated.
When dealing with well-known interfaces - published in the platform sdk - or if the header files are already supplied for C & C++ bindings, then typelibs are a tad useless.
Even when used from script languages, IDispatchEx now seems to be preferred as a discovery mechanism for the IDE or code to query an IDispatch supporting object at runtime for its methods.
In general, it's fine to say FALSE unless you need a typelib because someone is going to be calling your IDispatch implementation. For most shell extensions I don't think you need a typelib.
What are the entrypoints of an ocx ? are they same as that of com dlls ?
Yes, the entrypoints are the same.
There may be other constraints on an OCX that differ from a COM DLL though. For example, it's common (but not required) for a COM DLL to include a type library as a built-in resource. Every OCX I've ever seen has had its type library built-in in this way, so maybe that's a requirement for an OCX?
In general the coclasses defined in an OCX (or at least some of them) are expected to be ActiveX controls, which means they should implement certain specific COM interfaces. A plain old COM DLL has no such expectations placed upon it.