{"id":97195,"date":"2017-10-11T07:00:00","date_gmt":"2017-10-11T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=97195"},"modified":"2019-03-13T01:32:58","modified_gmt":"2019-03-13T08:32:58","slug":"20171011-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20171011-00\/?p=97195","title":{"rendered":"How can I specify that my DLL should resolve a DLL dependency from the same directory that the DLL is in?"},"content":{"rendered":"<p>A customer had a program that loaded two DLLs, let&#8217;s call them <code>A.DLL<\/code> and <code>B.DLL<\/code>. Both of those DLLs use a common helper DLL called <code>C.DLL<\/code>. The catch is that the two DLLs want to use <i>different incompatible versions<\/i> of <code>C.DLL<\/code>. The two DLLs <code>A.DLL<\/code> and <code>B.DLL<\/code> reside in separate folders, and each folder has a corresponding copy of <code>C.DLL<\/code>. <\/p>\n<p>An additional complicating factor is that <code>A.DLL<\/code> was written by a third party and cannot be modified. <\/p>\n<p>The customer was hoping there would be some way to get the two DLLs <code>A.DLL<\/code> and <code>B.DLL<\/code> to use their respective versions of <code>C.DLL<\/code>. They suspect that some magic with activation contexts and manifests might do the trick, but they didn&#8217;t have the expertise to figure out exactly what. (And remember that <code>A.DLL<\/code> came from a third party and cannot be modified.) <\/p>\n<p><a HREF=\"https:\/\/blogs.msdn.microsoft.com\/talagrand\/\">Eugene Talagrand<\/a> explained that you can solve the problem with manifests. Embed a manifest into <code>B.DLL<\/code> with resource ID 2 that looks like this: <\/p>\n<pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"&gt;\n    &lt;file name=\"C.dll\" \/&gt;\n&lt;\/assembly&gt;\n<\/pre>\n<p>You don&#8217;t have to make any changes to the code that loads <code>B.DLL<\/code>. When you try to load <code>B.DLL<\/code>, the system will recognize the manifest, and that manifest tells the system to ignore any rogue copies of <code>C.DLL<\/code> and link <code>B.DLL<\/code> to the copy of <code>C.DLL<\/code> in the same directory. Furthermore, this special &#8220;<code>B.DLL<\/code>-specific&#8221; version of <code>C.DLL<\/code> is not made visible to other DLLs (unless they specifically ask for it with their own manifest), so when the program loads <code>A.DLL<\/code>, it will ignore the &#8220;<code>B.DLL<\/code>-specific&#8221; copy and look for <code>C.DLL<\/code> using the traditional search path. <\/p>\n<p>The customer confirmed that adding the manifest to <code>B.DLL<\/code> worked! <\/p>\n<p>Note that the manifest declaration applies to DLL dependencies resolved when <code>B.DLL<\/code> is loaded. If <code>B.DLL<\/code> performs a <code>LoadLibrary(\"C.DLL\")<\/code> at run time, then it will need to make its activation context active when it loads the DLL so that the system knows to follow the instructions in the manifest. For more details, you can read more about <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/talagrand\/2010\/03\/08\/isolating-a-plugin-into-its-own-directory\/\">using manifests to isolate DLLs<\/a> on Eugene&#8217;s blog. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Use the manifest.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-97195","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Use the manifest.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=97195"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97195\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=97195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=97195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=97195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}