Can I make it so that a third-party application can use several of my DLLs with the same name but different versions? - dll

I developed a DLL library (let's call it comp.dll) used by a third-party application (let's call it app.exe) as an additional plugin.
No intervention in app.exe on my part is possible.
At this stage, there is a problem loading by process app.exe of several comp.dll different versions simultaneously.
The file and folder structure is as follows:
App folder
|______ app.exe
|______ comp ver 1.0 folder
|______ comp.dll
|______ comp ver 2.0 folder
|______ comp.dll
It is necessary to make it possible for the app.exe to dynamically, during its lifetime, load comp.dll from 'comp ver 1.0 folder' and comp.dll from 'comp ver 2.0 folder' at the same time.
I'll try to describe some examples. "App.exe" works with some data file "test.dat". Functions for processing of data from "test.dat" are implemented in "comp.dll". In "tast.dat" also provided the path to "comp.dll" where it is stored on the disk storage device. "App.exe" read path to "comp.dll" from "test.dat", load this dll and call functions to process data from "test.dat". For one file all is ok. Now, let's consider two files: "test1.dat" and "test2.dat". If both files use the "comp.dll" of the same version, everything is fine, but if versions are different, conflicts arise, since the dll that was loaded first is used, and the second one is not loaded.
I know that such problems are solved with the help of manifests, but I can't influence the manifest app.exe in any way.
Can you please tell me if there is any way to solve this problem?

Related

MSBuild GenerateResource task produces resource file names with incomplete namespace, causing our app to crash at runtime

We build mobile apps using Xamarin Forms, with macOS building the iOS apps. We ran into an issue today that has left me scratching my head.
A normal build with embedded resource files looks like this:
CoreResGen:
/Library/Frameworks/Mono.framework/Versions/5.16.0/lib/mono/4.5/resgen.exe /useSourcePath
[....all of our references....]
/compile
Resources/HtmlStyleRes.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.Resources.HtmlStyleRes.resources
Resources/TextRes.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.Resources.TextRes.resources
Resources/TextRes.nb.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.Resources.TextRes.nb.resources
So no surprises there; the .resx files are compiled into binary .resources files with the assembly namespace + folder name + resx filename.
However, we made a change to our directory structure on the build server, and this changed the output from CoreResGen:
CoreResGen:
/Library/Frameworks/Mono.framework/Versions/5.16.0/lib/mono/4.5/resgen.exe /useSourcePath
[....all of our references....]
/compile
Resources/HtmlStyleRes.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.HtmlStyleRes.resources
Resources/TextRes.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.TextRes.resources
Resources/TextRes.nb.resx,obj/BuildAgentRelease_iOS/ForumApp.Common.TextRes.nb.resources
Notice how the "Resources" folder was dropped from the .resources filename. When compiled into an app, this causes our app to crash at runtime, since the resource file namespace is now different.
We build our apps using self-hosted Azure agents. All apps are built from the same repository, and as part of an effort to streamline the build servers, we implemented a pipeline task to utilize a common repository folder for all builds. The Azure agent would normally build out of _work/build-id/s, and our pipeline task will symlink this directory to _work/g/repo-id so that multiple builds can share the same repository.
When we build with the repo in _work/build-id/s, everything is fine. When we build with the symlinked repo, the file namespace error occurs.
As far as we can tell, this happens on macOS, but not on Windows.
We have a possibly related issue that happens on macOS, but not on Windows. The following outputs are from macOS using mono:
Path.GetDirectoryName(#"Resources\TextRes.resx") => ""
Path.GetDirectoryName(#"Resources/TextRes.resx") => "Resources"
Path.GetDirectoryName is used in CreateCSharpManifestResourceName to create the output file name from Resources\TextRes.resx, but there appear to be guards replacing \ with / and I can't see why symlinking the source folder would trigger it.
Has anyone experienced this? Am I missing something obvious?

Is the creation of a zip file, out of the structure of folders and files, possible in WIX?

Here is what I am dealing with. I have a WIX project, that outputs a MSI file. This works like a charm.
I got a new requirement, that I need to analyse in order to figure out how to approach it. As the new requirement is, I need to get as output, a ZIP file, that contains the files and folders as described in the WIX project...
I searched for the "ZIP" keyword on the official documentation, but did not have any luck in finding something helpful...Maybe some of you guys have an idea?
Obviously, I could use other tools to perform this, like maven and the maven assembly plugin, but that would cause maintenance issues, as there would be 2 different projects, 2 different technologies, and since the files and directories structure is quite big, this could cause issues like one developer modifying a project, and forgetting about the other..
So yeah...difficult question...any input would be welcomed :)
Thx
Administrative Installation: Windows Installer / MSI features a built-in capability to extract all files and make a "network installation point" (a network location where installation can be kicked off from to install on all workstations on the network - ensures all source files are available for repair operations and patching). This is called an administrative installation - in plain terms a glorified file extraction mechanism.
Given the availability of the administrative installation, is a ZIP file really necessary? I suppose you could zip up the extracted admin image? Note that any files that need to go to system, shared or userprofile folders may cause issues and prevent successful launching of your application from the extraction folder (obvious, just mentioning).
Command Line: Try it, from a cmd.exe command prompt (see above link for more details):
msiexec.exe /a MySetup.msi
You could set the Compressed="no" attribute of the Package element to create an uncompressed layout. The result could be easily zipped (excluding the *.msi file) by running any of the freely available command-line zippers (e. g. 7za.exe of 7-zip).
Note:
File elements can override the Compressed attribute of the package.

Getting out of DLL Hell with Microsoft.VC90.CRT?

I've built a inproc com server dll which I can package as 1 file or many via the build utility py2exe. When I allow all the dependencies to remain external, I have no issues, but bundling as 1 file produces problems.
When the dll is utilized (either registering it or instantiating a com object from it), it immediately loads MSVCR90.DLL from the path c:\windows\winsxs\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6871_none_50944e7cbcb706e5\MSVCR90.DLL no matter what I do, I can't change that. There is no information that I can find (using Dependency Walker) to indicate what is causing that to load. It just happens magically...
Then, later on it loads that dll again via an explicit call to LoadLibraryA("MSVCR90.dll") (part of some py2exe black box?), but this time it does not look into the winsxs manifests / directory. Instead it looks to the system path and/or will respect a dll redirection. That's when the problem occurs. If I set the system path to start with c:\windows\winsxs\x86_microsoft.vc90.crt...\ it will load the exact same dll and be happy - but if ANY other file is utilized - inclusive of a copy of the EXACT same dll - but at a different path - then the whole thing blows up. It can't handle using two different files.
How can I fix this? Ideally, I've love to make the initial magic loading of the dll draw upon a private assembly, but no matter what I do with manifests or .dll.local etc it will not respect that until this second dll loading takes place.
Note that with the non-bundled dll (external dependencies) it always uses the winsxs MSVCR90.DLL.
I can "fix" my failure to use the dll by forcing the system path to load the winsxs copy, but that is pretty useless for a deployable com server!
The reason is that you DLL has a manifest that tells the module loader to search also in the SxS storage.
You have several choices
Build your DLL using static linkage. Not using any of the MFC-DLLs (see project settings)
Don't use a side by side manifest for the DLL and still use the MFC DLLs. But beware you have to ship those DLL with your DLL in the local path (see DLL search sequence docs)
Use a later build of VS. Later versions of VS don't use the SxS storage any more and there are no manifests for those DLLs any more.
For the 2. see this article in code project. There is an update for VS-2008 [here].
2
Build your DLL

I would like to have my AssemblyVersion in my deployment package name

I am using MSbuild to create a deployment package (simply copying various files from the projects in my solution to different folders) I would like the root folder to be of the format
DeploymentPackage2.3.4.5ForRelease
How can I get MSbuild to put the Assembly number in the folder name automatically?
EDIT:
The solution has a great deal of projects in it (too many really) they all get their version number from a SharedAssemblyInfo.cs file that is manually updated but in the fullness of time will pick up the svn build number (but that is a job for later)
I am building using an external .bat file that calls a custom written .targets/.proj setup that simply calls msbuild on the .sln of the solution.
The 'create package' step I am trying to create happens after a succesful build and will eventually be run by our CI framework, however I would like to be able to run it locally too.
I have created a "CreatePackage" target that does the copying that I want, however it is currently into a fixed folder. I need the folder name to reflect the AssemblyVersion of one of the final dll's.
If there is a better way then I want to know about it... but I am going to use this I think
MSBuild Task to read version of dll

MSBuild overwriting dependencies

Ok, so I've got a somewhat complicated problem with my build environment that I'm trying to deal with.
I have a solution file that contains multiple C# projects which is built by a NAnt script calling MSBuild - passing MSBuild the name of the solution file and a path to copy the binaries to. This is because I want my automated build environment (CruiseControl.Net) to create a folder named after the revision of each build - this way I can easily go back to previous binaries for any reason.
So idealy I have a folder layout like this
c:\build\nightly\rev1
c:\build\nightly\rev2
c:\build\nightly\rev3
...
c:\build\nightly\rev10
etc.
The problem that's arisen is I recently added the latest version of the Unity IoC container to my project, checking it directly out of MS's online SVN repository. What's happening is I have a Silverlight 3 project that references the Silverlight version of Unity but I also have other projects (namely my Unit testing project) that reference the standard (non-Silverlight) version of Unity.
So what happens is since MSBuild is dumping everything into one single folder the Silverlight version of the Unity assembly is overwriting the non-Silverlight version because they have the exact same assembly file name.
Then when CruistControl runs my unit tests they fail because they don't have the proper dependencies available anymore (they try to load the Silverlight specific Unity assembly which obviously doesn't work).
So what I want to do is:
keep my desired output directory
structure (folder\revision)
I don't want to have to manually edit
every single proj file I have as this
is error prone when adding new
projects to the solution
Idealy I would like MSBuild to put everything into a folder structure similar to this:
nightly\revision1\project1
nightly\revision1\project2
nightly\revision1\project3
...
nightly\revision2\project1
nightly\revision2\project2
nightly\revision2\project3
etc
I can't modify the Unity project to give it a different file name because it comes from another SVN repository I cannot commit changes to. I found a similar question posted here and the suggested solution was to use a "master" MSBuild file that used a custom task to extract all the project file names out of the solution then loop over each one building them. I tried that but it doesn't build them in the order of their dependencies, so it fails for my project.
Help?
Firstly I would always have the build server delete the old working copy and check out a fresh copy to avoid any problems with stale artifacts from the previous build.
Next I would have nant or msbuild build the solutions as before with the artifacts from each build going to their local working output folders.
After that I'd move the artifacts from their working paths to their output paths, this shouldn't require digging through the project files since you can just tell msbuild/nant to copy working\project1\bin\release\**\*.* to artifacts\project1\.
The script that does this should ideally be stored along with the source with the main file, e.g. build.nant or build.proj in top level of the trunk.
For third party libraries I would simple include the DLLs directory in your repository. Nothing worse than writing some code and having a third party dependency break your build because of changes on their end.
Simply document the versions of the libraries you are using, and if you must update them, you'll have a better sense of what breaks the build before you even check it in.
Also, doesn't CC.Net automatically handle the providing of releases based on revision? I'm using TeamCity and it keeps a copy of the artifacts of every build.
I highly recommend reading JP Boodhoo's Automating Builds with NAnt blog series. That's been my starting point and have made lots of changes for my own taste. I also highly recommend checking out the builds of many open sources projects for examples. I've learned a lot from the builds of the Castle/Nhibernate/Rhino-Tools stack.