I need to add a dependency on a specific version of GDIPlus. This is the version of GDI+ that i want:
I want to be sure that I'm using this version for a specific compatibility reason.
I've added an assembly manifest to my executable, defining my dependancy on the version of GdiPlus:
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32" name="Microsoft.Windows.GdiPlus"
pubicKeyToken="6595b64144ccf1df"
version="5.1.3102.2180" processorArchitecture="x86"
language="*" />
</dependentAssembly>
</dependency>
Except when I run my application, Windows' fusion loader gives me some other version of gdiplus.dll from the Side-by-Side folder, which I can see in Process Explorer:
It's giving me version 5.02.6002.18005, rather than 5.1.3102.2180.
So the question is: How do I take a dependency on a specific version of a Windows dll?
Your "problem", such that it is, is that there is a policy file installed that specifies that requests for 5.1.3102.2180 can be redirected to 5.02.6002.18005
This is, usually, a good thing. it lets applications specify the version they were built against in their manifest, but when critical security fixes are introduced, the OS can redirect apps to compatible versions.
So, whats going to happen here is, your app is going to link against GDI+ 5.1 on any PC that has only 5.1 installed. but any PCs with the 5.2 GDI+, you will be redirected to that.
If you do have an honest to goodness reason why you want to use 5.1, even when 5.2 is available... I think you can use an application config file to manage that.
Create a file called, yourapp.exe.config - if the module in your app thats importing GDI+ is a dll, then it would be thedll.dll.2.config
I am unsure how to structure the bindingRedirect however. i.e. given the policy files redirection, im not sure if you need to redirect the old version back to itself, or the new version back to the old version. or what. some trial and error might be required.
The data in the .config file looks almost exactly like the data in the manifest file. Something like this (which mimics almost exactly the contents of the policy file installed in winsxs thats doing the redirection you dont want).
<configuration>
<windows>
<assemblyBinding xmlns=...>
<dependentAssembly name="GdiPlus...>
<bindingRedirect oldVersion="5.1.x.x" newVersion="5.1.x.x"/>
To make the choice of "oldVersion" easier, it supports a range syntax. so
oldVersion="5.0.0.0-5.3.0.0"
would be a simple way to ensure that a whole range of GdiPlus versions get redirected to a specific version.
Related
I had to download a different version from a DLL, but now this new version requires 4 other DLLs, which I don't want to add into my package. Since I'm not even using them, it would be a waste of space.
Is it somehow possible to edit the DLL and make it ignore the missing dependencies which aren't even used?
I'm talking about libgd2.dll, and since the website is down, I was unable to find the old version of this library, so I had to download this newer version. Earlier I had bgd.dll, but now I can't find the old bgd.lib file anywhere on the web.
I am building an application using Microsoft Visual C++ 2005. After a major update of libraries, I am getting the following entry in my manifest file:
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.4053" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
However, when I look use the Dependency Walker on the resulting executable, I don't see MSVC80D.DLL in the list at all, which is a bit surprising to me.
I've also tried setting the linker to "verbose" mode, to see if it would tell me where the dependency indicated in the manifest is coming from. Alas, the information there doesn't shed any light on the problem.
I've also gone through all the libraries I'm linking to see if any of them use the debug CRT. As near as I can tell, none of them do.
How can I determine what library is causing this issue? When I distribute the executable as it is, I get a side-by-side error, presumably because of this entry in the auto-generated manifest.
Thanks so much for any help you can offer... After a few days of trying to figure out what's going on, I'm starting to get really frustrated with the problem.
I think I've found the solution to my problem. I decided to build a small test app, then add the libraries I'm using one at a time. Using this method, I isolated one library in particular that seemed to be causing the problem. I'm certain the library didn't show debug dependencies using dumpbin, but, on the other hand, I have been able to eliminate the unwanted manifest line by rebuilding that library.
Let's say I have an application that uses MSHTML. Installing IE9 beta would update MSHTML which breaks my application. I found that copies of IE8 dll is still present in the WinSxS folder, so maybe I can somehow use them without recompiling my program? Can WinSxS do it?
I've searched for a long time but couldn't figure out how to redirect the loader to use the IE8 MSHTML (which is in WinSXS) instead of the IE9 (which is in %SYSTEMROOT%\system32). Any ideas/examples would be appreciated.
I've since gone with a different approach to this problem. I'll share what I eventually did -- I hijack LoadLibrary and load whatever DLL I want: DLL file loaded twice with DLL redirection through manifest.
To answer the specific title of the question ("use WinSxS manifests to redirect"), I'll answer with "No, you can't" based on my long time battle with WinSxS (downvote if you disagree, I'll be happy to see how that can be done.)
You definitely can't use WinSxS manifests or policy redirection to force loading different versions of OS components. While os components are also stored in the WinSxS store, they are not bindable as sxs assemblies and so this kind of redirection is not possible.
Grovelling around to redirect LoadLibrary and force loading of an older version of mshtml (or any other OS DLL) is a very bad idea and I strongly recommend against it. Reasons include the fact that the older DLL may not be present on all installs, that you are unlikely to correctly hook all the loading paths (and hence create a strange hybrid), and of course that things like MSHTML are designed for use in a specific way and any other use could lead to problems later - especially in security sensitive stuff like HTML.
Martyn
We have recently decided to start shipping the versions of some of the DLL files that a product requires with the product itself.
This is to guard against the situation where (for example) the MVC DLL file is updated on the server to which the software is deployed and the product fails to work as it was written against the now previous version of the DLL.
If the MVC DLL file of the specific version is included in the product and "locally" referenced this prevents this problem from happening. (In an ideal world every product which will be installed onto the destination server would be updated to the most recent version but this is not always practical)
My concern and question is whether this is going to give a false sense of security or not actually cope with the problem in the following situation: if Version 1.0 of the MVC DLL file is relying on method X of standard Microsoft DLL library Y and this DLL file Y is updated we will be in the same situation of having a broken product?
Assuming you meant the MSVC (Microsoft Visual C++) DLLs, the correct solution is to use an application manifest. The MSVC DLLs support Side by Side installation (SxS). This means that a new version of those DLLs does not replace an old version. Your application manifest tells Windows which DLL version(s) you want.
I don't know about MVC specifically, but you have a bigger problem if the conflicting version of a dependency dll is installed to the GAC on your target machine, as it will be used in preference to the local file.
Depending on how big it would make your final product, consider statically linking your program. This will prevent the much dreaded DLL hell since you wont have to give DLLs out.
Alright, after doing a ton of research and trying almost every managed CPP Redist I can find as well as trying to copy my DLLs locally to the executing directory of the app I cannot figure out what dependencies i'm missing for this mixed mode library.
Basically I have a large C# application and I'm trying to use a mixed mode library I made. On the development machine it works perfect (of course) but deployed when the library needs to be loaded for use it exceptions out because of missing CRT dependencies (I assume).
I have used dependency walker to check all the DLLs referenced and ensured they exist on the deployment machine with no luck, I'm wondering if maybe it's some dependencies that need to be registered that I am missing, but i can't figure out what.
I get the following exception when code tries to instantiate a class from the mixed mode library.
Exception Detail:
System.IO.FileLoadException: Could not
load file or assembly 'USADSI.MAPI,
Version=1.0.3174.25238,
Culture=neutral, PublicKeyToken=null'
or one of its dependencies. This
application has failed to start
because the application configuration
is incorrect. Reinstalling the
application may fix this problem.
(Exception from HRESULT: 0x800736B1)
I am compiling the library using VS2008 SP1 with /clr:oldSyntax specified.
The intermediate manifest looks like this:
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
</assembly>
I can provide any more information as needed, unfortunately i'm not well versed in making mixed mode libraries so this has thrown me off.
If anyone can offer any advice I would greatly appreciate it!
Did you deploy the CRT libraries on the target machine? Long shot: since you have a dependency on 32-bit code, you should set Target Platform in the Build property tab to x86.
EDIT: trouble-shoot side-by-side resolving problems with the Sxstrace.exe utility, available on Vista.
Typically I've found that the pragma comment style manifest decleration's to be much more error free, from a developer maintenence and an over all build action perspective. The XML manifest's are natoriously snafu.
The fimiluarity with how the linker operates and the usual compilation of C code and the fact that you simply tak this in, onto one of your source files, keeps everything a bit feeling more "together";
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")
I had a similar problem the first time I deployed a VS 2005 app on a target machine -- had to bring over the MSVCRT80 DLL. Are you saying you already have the 2008 VS runtime library there?
ETA: Also, dumb question, but are you sure you have both the CRT Runtime (linked to above) and the .NET Runtime, with the same version you compiled against (probably 3.5)? You probably already know this (especially considering your score) but they're 2 different things.
I found a solution that seems to work although I don't like it very much.
I had to copy the folders:
Microsoft.VC90.CRT & Microsoft.VC90.MFC
From: Program Files\Microsoft Visual Studio 9.0\VC\redist\x86
Into the deployed application directory, I just can't figure out why this seems to work and the redistributables did nothing.
EDIT: Looking at the manifest I probably don't need to copy the MFC directory
Best way to solve this problem is to download process monitor which is free from:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
Add a filter to watch only your process and it will show you all file access the process tries. This will show you exactly which dll it can't find.
I always use this when faced with the same problem - if only microsoft filled in the filename in the thrown exception it would all be easier.