{"id":1612,"date":"2016-02-07T21:38:37","date_gmt":"2016-02-07T19:38:37","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=1612"},"modified":"2016-02-07T21:38:37","modified_gmt":"2016-02-07T19:38:37","slug":"manifestcomdependency-addingremoving-registration-free-com-dependencies","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/1612","title":{"rendered":"ManifestComDependency: Adding\/Removing Registration-Free COM dependencies"},"content":{"rendered":"<p>In <a href=\"https:\/\/alax.info\/blog\/1561\">one of the earlier posts<\/a> I mentioned a problem with registration-free COM dependency setup up by Visual Studio as a part of build process. This post is about the tool that offers an alternate solution for the problems, and also gives more:<\/p>\n<ul>\n<li>standalone, independent from build, addition\/removal registration-free COM links<\/li>\n<li>automation of registration-free COM links for native code builds<\/li>\n<\/ul>\n<p>Unless one deals with <code>ACTCTX<\/code> activation contexts programmatically, taking advantage of registration-free COM is essentially a setup of respective side-by-side manifests, either standalone or embedded into executable. The manifests override standard global COM object lookup procedure and point to COM servers directly, in some way similar to the way static links to exported DLL functions work.<\/p>\n<p>To enable, registration-free COM reference COM client needs to prepare respective manifest file (declare an assembly) and list its COM dependencies. The COM dependency list is not just COM server files but rather their COM classes and type libraries. That is, when it comes to automation, the tool needs to go over the COM servers and extract respective identifiers, so that it could properly shape this information and include into manifest XML.<\/p>\n<p>To deal with the challenge, I am using <code>ManifestComDependency<\/code> tool (no better came to mind when it was created). The command line tool syntax is the following:<\/p>\n<pre> ManifestComDependency &lt;path&gt; [options]\r\n \r\n Options:\r\n \u00c2\u00a0* \/i[:&lt;assembly-name&gt;] - updates &lt;assemblyIdentity&gt; element replacing it with automatically generated\r\n \u00c2\u00a0* \/a[:tc] &lt;dependency-path&gt;[|LIBID[;X.Y]] - adds file &lt;dependency-path&gt; dependency, optionally without type library and COM classes reference\r\n \u00c2\u00a0* \/r &lt;dependency-path&gt; - removes dependency from file &lt;dependency-path&gt;\r\n \u00c2\u00a0* \/e &lt;export-path&gt; - exports manifest to file &lt;export-path&gt;<\/pre>\n<p>The tool opens a file <code>&lt;path&gt;<\/code> for manifest modification. The file can be a binary file, such as <code>.exe<\/code> or <code>.dll<\/code>, in which case the tool will be working with embedded manifest resource. Or, if the path extension is <code>.manifest<\/code> or <code>.xml<\/code>, then the file is treated as standalone XML manifest file. Both options are good for manifests associated with .NET builds as well, even though this surely does not need to be managed code development &#8211; native COM consumers are okay.<\/p>\n<p><code>\/i<\/code> option updates <code>&lt;assemblyIdentity&gt;<\/code> element in the manifest data because it is mandatory and in the same time it might so happen that it is missing or incomplete, which ends up in painful troubleshooting. The tool will name file name, architecture and version information from the binary resource information (product version; the <code>VERSIONINFO<\/code> resource has to be present).<\/p>\n<p><a href=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2.png\" rel=\"attachment wp-att-1613\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1613\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2-800x184.png\" alt=\"ManifestComDependency Output\" width=\"625\" height=\"144\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2-800x184.png 800w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2-320x74.png 320w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2-768x177.png 768w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2-624x144.png 624w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2016\/02\/Clipbrd2.png 847w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p><code>\/a<\/code> option adds a dependency, defined by either path or registered type library identifier the tool would use to resolve the path. <code>t<\/code> and <code>c<\/code> modifiers exclude type library and COM server information respectively. The tool created a <code>file<\/code> element for the dependency and populates it with COM servers discovered there. Type library is obtained using <code>LoadTypeLib<\/code> API and COM servers are picked up by a trick with <code>RegOverridePredefKey<\/code> and friends (e.g. see example in <a href=\"http:\/\/www.codeproject.com\/Articles\/28682\/regsvr-Generate-SxS-Manifest-Files-from-Native-D\">regsvr42 source<\/a> or <a href=\"https:\/\/github.com\/cplussharp\/graph-studio-next\/search?utf8=%E2%9C%93&amp;q=RegOverridePredefKey\">GraphStudioNext source<\/a> &#8211; both are excellent sources of code snippets for the curious).<\/p>\n<p>The task of COM server discovery assumes load of the library into process (<code>LoadLibrary<\/code> API call), which assumes bitness match between the tool and the loaded module. This is where you need both <code>Win32<\/code> and <code>x64<\/code> builds of the tool: if wrong bitness is detected, the tool restarts its sister build passing respective command line arguments, just like <code>regsvr32<\/code> does with the only difference that <code>regsvr32<\/code> uses binaries in <code>system32<\/code> and <code>syswow64<\/code> directories, and my tool looks for <code>-Win32<\/code> and <code>-x64<\/code> suffixes and the files in the same directory.<\/p>\n<p><code>\/r<\/code> option removes dependencies by name. It is safe to remove certain dependency before adding it back because addition does not check if dependency already exists.<\/p>\n<p><code>\/e<\/code> option writes the current version of the manifest in external file, esp. for review and troubleshooting if the actual manifest is embedded.<\/p>\n<p>The order of options is important because they are executed one by one in the order of appearance. Then the result is saved\/re-embedded once all tasks are done.<\/p>\n<p>Command line example of re-adding registration-free COM dependencies:<\/p>\n<blockquote><p>ManifestComDependency-x64.exe BatchExport-x64.exe \/i \/r Player.dll \/r mp4demux.dll \/a Player.dll \/a mp4demux.dll<\/p><\/blockquote>\n<p>This can be set as post-build event in the project settings, or put into batch file or run on-demand.<\/p>\n<h3>Download links<\/h3>\n<ul>\n<li>Binaries:\n<ul>\n<li>32-bit: <a href=\"https:\/\/www.alax.info\/svn\/public\/trunk\/Toolbox\/ManifestComDependency-Win32.exe\">ManifestComDependency-Win32.exe<\/a><\/li>\n<li>64-bit: <a href=\"https:\/\/www.alax.info\/svn\/public\/trunk\/Toolbox\/ManifestComDependency-x64.exe\">ManifestComDependency-x64.exe<\/a><\/li>\n<\/ul>\n<\/li>\n<li>License: This software is free to use<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In one of the earlier posts I mentioned a problem with registration-free COM dependency setup up by Visual Studio as a part of build process. This post is about the tool that offers an alternate solution for the problems, and also gives more: standalone, independent from build, addition\/removal registration-free COM links automation of registration-free COM&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/1612\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[38,95,496,70],"class_list":["post-1612","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c","tag-com","tag-regfree","tag-winapi"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1612","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=1612"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1612\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=1612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=1612"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=1612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}