I've been told to create a 'manifest' to achieve Reg-Free-Com between a VB6 .EXE and a .NET DLL.
What is a 'manifest' in this context?
What does it mean to 'embed' a manifest?
From: http://msdn.microsoft.com/en-us/library/ms973913.aspx#rfacomwalk_topic2
Registration-free COM uses manifest to refer to text files with the .manifest extension containing XML, which either defines the identity of an assembly (assembly manifest), together with the binding and activation details of its classes, or defines the identity of an application (application manifest), together with one or more assembly identity references.
To 'embed' a manifest means the text information is embedded in the dll as a Win32 resource rather than sitting on disk as a standalone text file.
Related
I'm creating a new custom action in a basic MSI (installshield 2014) project. I've to call a public method in a managed .Net assembly abc.dll which gets deployed as part of the product deployment. abc.dll is part of a component named component1 which is part of the the feature feature1 in the setup design.
When I try to refer that assembly in the custom action creation wizard I mention its Location as Installed with the product. But on the Action Parameters step in custom action creation wizard when I try to browse abc.dll at the deployment path then I don't see it:
Although I'm able to see abc.dll while browsing it in the components as shown in the snapshot below. The abc.dll is present as part of component1 which gets deployed in %programfiles% path of the product.
On the other hand, I can see a pqr.exe file (which gets deployed as part of another component component2) in the custom action creation wizard as shown in the below snapshot:
Can anyone guide me why this might be happening?
I assume that InstallShield is validating that those binaries can be called as custom actions. An executable can be run as a custom action, so it shows up. A Dll cannot be arbitrarily called unless it exports an entry point with the required signature. There is no native support for Windows Installer to call managed code custom actions, so perhaps InstallShield provides a C++ shim to call (as do Visual Studio installer projects). Otherwise C++ Dlls need to have this signature:
UINT__stdcall CustomActionEntryPoint(MSIHANDLE hInstall)
Examples here:
https://www.simple-talk.com/dotnet/visual-studio/visual-studio-setup-projects-and-custom-actions/
https://www.codeproject.com/Articles/570751/DevMSI-An-Example-Cplusplus-MSI-Wix-Deferred-Custo
And as I said, your version of IS may have support for calling managed code Dlls under some other description of calling Dlls (as opposed to something like "calling a standard Windows Installer custom action").
I finally got the problem to my solution. It all boils down to how Installshield treats the packaging of .Net assembly and its dependencies.
Difference between how a .Net exe and its dependencies are referred by Installshield:
Whenever you add main project output e.g. pqr.exe in my case then it gets added into a component. When you browse your component you will see the source path of the exe under Link To column in terms of standard known variables of installshield environment e.g. [InstallDir]\ComponentName\ etc.
Now when installshield has to create the MSI package for deploying a .Net assembly e.g. pqr.exe in my case it also tries to package its dependencies as well for deployment. In my case prq.exe was depending upon abc.dll. But the caveat is that installshield doesn't maintain the list of dependencies of a .Net assembly statically inside its own *.ISM installer project file.
So abc.dll was also shown in the component but its path was coming as a fully qualified path on the disk where ISM file was getting built e.g. D:\mywork\MSIProject\. This is because abc.dll is actually not part of the ISM insataller project file. In fact, I opened the xml format of the ISM file in a text editor and tried to search for abc.dll and it was not there at all. So abc.dll is not present as an assembly to be deployed inside ISM installer definition file. But only while building the ISM file it tries to package all the dependencies along with the *.exe file.
All the dependencies should be present in the same root directory where *.exe file is present or installshield will not be able to package them.
Difference between how a .Net exe and its dependencies are packaged by installshield:
Another point of difference to note is that if you remove the pqr.exe from disk path where ISM file is getting built then ISM file will fail to build but if you remove abc.dll (which is not a physical part of the ISM definition file as it only a reference/dependency) then ISM file will still build successfully.
Difference between how a .Net exe and its dependencies are referred by a custom action in installshield:
As far as my actual problem goes, you can refer only those assemblies in your custom action which are part of a component in a direct manner. You cannot refer the assemblies which logically look like a part of the components only (as they are dependencies) but in reality they are being shown there just because they are dependencies of a managed .Net exe file.
Whatever I download, source code, e.g. NHibernate, or .dll file, e.g. NHibernate.Caches.SysCache, there are the .snk file.
What does this mean?
For source code, I just delete the snk file and compile them directly, it works. But is there anything I do wrong? I don't use the snk file.
For dll file, I found problem on version.
Assemblies can be assigned a cryptographic signature called a strong name, which provides name uniqueness for the assembly and prevents someone from taking over the name of your assembly (name spoofing). If you are deploying an assembly that will be shared among many applications on the same computer, it must have a strong name.(msdn)
With snk file included in a project, you can able to generate PublicToken for your dll.
What is the difference between application manifest and assembly manifest? Where is each one used? Which one of the two is found in .dll or .exe resources? (or both can be there? ).
Sorry if its too many questions at once, but if anyone can explain this to me it would be really helpful. The reason i'm asking this is that i want to be able to extract information from manifests embedded in PE files. I found these descriptions of manifests, but there are two and i'm not sure which one to follow:
Application manifest description
Assembly manifest description
EDIT: and no, i do not want to use any API calls. I'm writting it all myself.
In brief, the two are completely separate concepts with unfortunately similar names.
An application manifest is an XML file embedded in, or distributed along with, a PE binary (managed or native), giving instructions to the OS loader about things such as SxS assembly dependencies, required elevation, OS version compatibility, etc.
An assembly manifest is a section in a CLI assembly, stating the managed assembly's dependencies, the files making up the assembly, the assembly's public key, type exports, CLR flags, and so on. You can inspect an assembly's manifest using ILDASM.exe or most .NET decompilers.
A relevant excerpt from ECMA 335 (the CLI specification), section I.9.6:
Manifests: Every assembly has a manifest that declares which files
make up the assembly, what types are exported, and what other
assemblies are required to resolve type references within the
assembly. Just as CLI components are self-describing via metadata in
the CLI component, so are assemblies self-describing via their
manifests. When a single file makes up an assembly it contains both
the metadata describing the types defined in the assembly and the
metadata describing the assembly itself. When an assembly contains
more than one file with metadata, each of the files describes the
types defined in the file, if any, and one of these files also
contains the metadata describing the assembly (including the names of
the other files, their cryptographic hashes, and the types they export
outside of the assembly).
Note that:
all managed assemblies must have assembly manifests, executables and libraries alike;
all native binaries, executables and libraries, may have application manifests.
It seems that i will have to follow both:
As a resource in a DLL, the assembly
is available for the private use of
the DLL. An assembly manifest cannot
be included as a resource in an EXE.
An EXE file may include an application
manifest as a resource.
(Information found here). So it seems that executables have application manifests embedded in resources and libraries (DLL) have assembly manifests. Since both of them are PE (portable executable), i will need to parse both types.
Application manifests are typically embedded in EXEs and, ironically, Dlls, and specify which assemblies the EXE or DLL is dependent upon.
Assembly manifests can be embedded in DLLs, or be on disk as a separate file, and give an assembly an identity, and a list of resources: being dll's, activation free com objects, and window classes.
If the name of the assembly is the name of a dll, then the same manifest ends up being used as both an application manifest to determine the dependencies of the dll, and an assembly manifest to see what the assembly exports. This option really just seems crazy for native assemblies, its usually better to create an assembly with a complicated name along the lines of company.product.module, and then just have a simple module.dll as its one entry.
Background
I'm maintaining a plugin for an application. I'm Using Visual C++ 2003.
The plugin is composed of several DLLs - there's the main DLL, that's the one that the application loads using LoadLibrary, and there are several utility DLLs that are used by the main DLL and by each other.
Dependencies generally look like this:
plugin.dll -> utilA.dll, utilB.dll
utilA.dll -> utilB.dll
utilB.dll -> utilA.dll, utilC.dll
You get the picture.
Some of the dependencies between the DLLs are load-time and some run-time.
All the DLL files are stored in the executable's directory (not a requirement, just how it works now).
The problem
There's a new requirement - running multiple instances of the plugin within the application.
The application runs each instance of a plugin in its own thread, i.e. each thread calls functions exported by plugin.dll. The plugin's code, however, is anything but thread-safe - lots of global variables etc..
Unfortunately, fixing the whole thing isn't currently an option, so I need a way to load multiple (at most 3) copies of the plugin's DLLs in the same process.
Option 1: The distinct names approach
Creating 3 copies of each DLL file, so that each file has a distinct name. e.g. plugin1.dll, plugin2.dll, plugin3.dll, utilA1.dll, utilA2.dll, utilA3.dll, utilB1.dll, etc.. The application will load plugin1.dll, plugin2.dll and plugin3.dll. The files will be in the executable's directory.
For each group of DLLs to know each other by name (so the inter-dependencies work), the names need to be known at compilation time - meaning the DLLs need to be compiled multiple times, only each time with different output file names.
Not very complicated, but I'd hate having 3 copies of the VS project files, and don't like having to compile the same files over and over.
Option 2: The side-by-side assemblies approach
Creating 3 copies of the DLL files, each group in its own directory, and defining each group as an assembly by putting an assembly manifest file in the directory, listing the plugin's DLLs.
Each DLL will have an application manifest pointing to the assembly, so that the loader finds the copies of the utility DLLs that reside in the same directory. The manifest needs to be embedded for it to be found when a DLL is loaded using LoadLibrary. I'll use mt.exe from a later VS version for the job, since VS2003 has no built-in manifest embedding support.
I've tried this approach with partial success - dependencies are found during load-time of the DLLs, but not when a DLL function is called that loads another DLL.
This seems to be the expected behavior according to this article - A DLL's activation context is only used at the DLL's load-time, and afterwards it's deactivated and the process's activation context is used.
Edit: Works with ISOLATION_AWARE_ENABLED as expected - runtime loading of DLLs uses the original activation context of the loading DLL.
Questions
Got any other options? Any quick & dirty solution will do. :-)
Will ISOLATION_AWARE_ENABLED even work with VS2003? Edit: It does.
Comments will be greatly appreciated.
Thanks!
ISOLATION_AWARE_ENABLED is implemented by the Windows SDK header files and thus probably wont worth with VS2003 at all. However, it is possible to download the latest Windows 7 SDK and use that with VS2003.
You don't need to use MT to link in manifests. Manifests can be embedded as resources in environments that dont have explicit knowledge.
Add the following to a dll's .rc file to embed a manifest. (With a recent enough platform sdk RT_MANIFEST should already be defined):
#define RT_MANIFEST 24
#define APP_MANIFEST 1
#define DLL_MANIFEST 2
DLL_MANIFEST RT_MANIFEST dllName.dll.embed.manifest
EDIT: Since the original wording of my question caused much frowning I re-phrased it. Sorry about the confusion.
Until now all my COM DLLs had the extension .dll, but I assume there are some rules about that. I know there are .ocx, .oca, .tlb and .olb files. I'm aware that these files all contain "COM stuff" but what exactly?
What are these files in general: .ocx, .oca, .tlb, .olb?
What is the difference between an OLB and a TLB?
What is the difference between TLB and OCX?
What is the difference between .ocx and .oca?
When should I name my library .ocx and when .tlb? If they contain a certain kind of feature?
Which properties do my libraries have to have to use a certain extension?
.ocx
ActiveX Control
.oca
Extended type library/custom control cache file that goes along with a .ocx
.tlb
Contains the definitions of the COM interfaces and types contained in its associated COM library. It is a cross language "header file".
.olb
A Microsoft Object Library file that contains information referenced by Microsoft Office components.