为免注册 COM 生成清单文件
Posted
技术标签:
【中文标题】为免注册 COM 生成清单文件【英文标题】:Generate manifest files for registration-free COM 【发布时间】:2010-10-02 17:26:46 【问题描述】:我有一些使用清单文件的应用程序(一些本机,一些 .NET),因此它们可以是deployed in complete isolation,而不需要任何全局 COM 注册。例如,对 dbgrid32.ocx com 服务器的依赖在 myapp.exe.manifest 文件中声明如下,该文件与 myapp.exe 位于同一文件夹中:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="myapp.exe" version="1.2.3.4" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
</dependentAssembly>
</dependency>
</assembly>
dbgrid32.ocx 连同它自己的 dbgrid32.ocx.manifest 文件一起部署到同一个文件夹:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
<file name="dbgrid32.ocx">
<typelib
tlbid="00028C01-0000-0000-0000-000000000046"
version="1.0"
helpdir=""/>
<comClass progid="MSDBGrid.DBGrid"
clsid="00028C00-0000-0000-0000-000000000046"
description="DBGrid Control" />
</file>
</assembly>
这一切都很好,但是手动维护这些清单文件有点麻烦。有没有办法自动生成这些文件?理想情况下,我只想声明应用程序对 COM 服务器(本机和 .NET)列表的依赖关系,然后让其余的自动生成。有可能吗?
【问题讨论】:
+1 还有:重新标记 regfreecom,因为该标记对于无注册表 COM 更常见 我可以通过清单文件在我自己的安装文件夹中使用更高版本的 mstscax.dll 吗? @acewind 是的。 (您可能想发布一个包含更多详细信息的新问题。) @UuDdLrLrSs 好消息!我在这里发布一个新问题:***.com/questions/63575746/… 【参考方案1】:看起来完美的解决方案还不存在。总结一些研究:
制作我的清单 (link)
此工具扫描 VB6 项目以查找 COM 依赖项,但它也支持手动声明后期绑定的 COM 依赖项(即通过 CreateObject 使用的那些)。
有趣的是,这个工具将所有有关依赖项的信息放入应用程序清单中。应用程序 exe 及其依赖项被描述为由多个文件组成的单个程序集。我之前没有意识到这是可能的。
看起来是一个很好的工具,但从 0.6.6 版开始,它有以下限制:
仅适用于 VB6 应用程序,启动 来自 VB6 项目文件。惭愧,因为 它所做的很多事情真的无关紧要 使用 VB6。 向导风格的应用程序,不是 适合集成在构建中 过程。这不是一个大问题,如果你 依赖项没有太大变化。 没有源代码的免费软件,依赖它有风险,因为它随时可能成为废弃软件。我没有测试它是否支持.NET com 库。
regsvr42 (codeproject link)
此命令行工具为本地 COM 库生成清单文件。它调用 DllRegisterServer,然后在将信息添加到注册表时监视自注册。它还可以为应用程序生成客户端清单。
此实用程序不支持 .NET COM 库,因为它们不公开 DllRegisterServer 例程。
该实用程序是用 C++ 编写的。源代码可用。
mt.exe
windows SDK 的一部分(可以从MSDN 下载),如果你安装了visual studio,你就已经拥有了。它是documented here。 您可以使用它为原生 COM 库生成清单文件,如下所示:
mt.exe -tlb:mycomlib.ocx -dll:mycomlib.ocx -out:mycomlib.ocx.manifest
您可以使用它为 .NET COM 库生成清单文件,如下所示:
mt.exe -managedassemblyname:netlib.dll -nodependency -out:netlib.dll.manifest
但是,这个工具存在一些问题:
第一个 sn-p 不会生成 progid 属性,破坏客户端 将 CreateObject 与 progids 一起使用。 第二个 sn-p 将生成<runtime>
和 <mvid>
元素
需要先去掉
清单确实有效。
生成客户端清单
不支持应用程序。
也许未来的 SDK 版本会改进这个工具,我在 Windows SDK 6.0a (vista) 中测试过。
【讨论】:
我认为您错过了一个选项:mazecomputer.com,但我对此网站一无所知。 MMM 还将重定向非 COM(标准)DLL。我不确定其他工具可以做到这一点。 只是给紧张的一个提示:MMM 的源代码已经发布。不利的一面是,这似乎是因为作者已决定停止研究它。仍然是一个积极的信号。 MMM 的站点已不再上线,但v0.9 和v0.12 仍然可以使用放置源代码的地方。 刚刚为 .NET COM 库尝试了 mt.exe,如上所述,它无需修改使用 v7.1A 的清单即可工作。此外,MMM 的链接不起作用,但 Unattented Make My Manifest 似乎做得不错。【参考方案2】:通过 MSBuild 任务 GenerateApplicationManifest,我在命令行中生成了与 Visual Studio 生成的清单相同的清单。我怀疑 Visual Studio 在构建过程中使用了GenerateApplicationManifest。下面是我的构建脚本,可以使用 msbuild "msbuild build.xml" 从命令行运行
感谢 Dave Templin 和他的 post that pointed me the the GenerateApplicationManifest task,以及 MSDN 的 further documentation of the task。
构建.xml
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<ItemGroup>
<File Include='MyNativeApp.exe'/>
<ComComponent Include='Com1.ocx;Com2.ocx'/>
</ItemGroup>
<GenerateApplicationManifest
AssemblyName="MyNativeApp.exe"
AssemblyVersion="1.0.0.0"
IsolatedComReferences="@(ComComponent)"
Platform="x86"
ManifestType="Native">
<Output
ItemName="ApplicationManifest"
TaskParameter="OutputManifest"/>
</GenerateApplicationManifest>
</Target>
</Project>
【讨论】:
我认为这确实应该被标记为这个问题的答案。我现在正在使用它来自动化我们所有的清单生成。谢谢@mcdon,你为我节省了很多工作。 我同意这是使用 Visual Studio 构建时的最佳解决方案。它可能没有被评为更高,只是因为它比其他答案发布得晚了很多 如何将其添加到 csproj 中? @jle 我认为您可以将其添加到 AfterBuild 目标中的 csproj 中。这是关于预构建和构建后事件主题的link from msdn 和another post。 注意我没有在 csproj 中测试过,但我怀疑它会起作用。 迟到了 11 年,但感谢您的提及!【参考方案3】:Make My Manifest (MMM) 是一个很好的工具。也可以编写一个脚本来处理所有的 DLL/OCX 文件,使用mt.exe 为每个文件生成一个清单,然后将它们合并在一起。 MMM 通常更好/更容易,因为它还可以处理许多特殊/奇怪的情况。
【讨论】:
我对这个 MMM 的事情有点紧张;它只是一个博客,免费软件,但没有可用的源代码,只有一个“自解压 exe”的链接,我看到有关该实用程序导致 XP 崩溃的 cmets。嗯... 那些“崩溃”是 MMM 实用程序本身死亡。这在 0.6.5 版本中已修复,但无论如何您都需要 0.6.6,因为虽然它仍然是测试版,但它不再过期。尽管已经建议,但您始终可以使用 MT.EXE。 mt.exe 在 dbgrid32.ocx 等本地 com 服务器上使用时不会生成 progid 将 reg free COM 与 .NET 编写的组件一起使用显然会导致 XP 崩溃 - 请参阅***.com/questions/617253/…【参考方案4】:您可以使用Unattended Make My Manifest 分拆直接在自动构建中生成清单。它使用脚本文件来添加依赖的 COM 组件。这是带有可用命令的示例 ini 的摘录:
# Unattended MMM script
#
# Command names are case-insensitive. Reference of supported commands:
#
# Command: Identity
#
# Appends assemblyIdentity and description tags.
#
# Parameters <exe_file> [name] [description]
# exe_file file name can be quoted if containing spaces. The containing folder
# of the executable sets base path for relative file names
# name (optional) assembly name. Defaults to MyAssembly
# description (optional) description of assembly
#
# Command: Dependency
#
# Appends dependency tag for referencing dependent assemblies like Common Controls 6.0,
# VC run-time or MFC
#
# Parameters <lib_name>|<assembly_file> [version] [/update]
# lib_name one of comctl, vc90crt, vc90mfc
# assembly_file file name of .NET DLL exporting COM classes
# version (optional) required assembly version. Multiple version of vc90crt can
# be required by a single manifest
# /update (optional) updates assembly_file assembly manifest. Spawns mt.exe
#
# Command: File
#
# Appends file tag and collects information about coclasses and interfaces exposed by
# the referenced COM component typelib.
#
# Parameters <file_name> [interfaces]
# file_name file containing typelib. Can be relative to base path
# interfaces (optional) pipe (|) separated interfaces with or w/o leading
# underscore
#
# Command: Interface
#
# Appends comInterfaceExternalProxyStub tag for inter-thread marshaling of interfaces
#
# Parameters <file_name> <interfaces>
# file_name file containing typelib. Can be relative to base path
# interfaces pipe (|) separated interfaces with or w/o leading underscore
#
# Command: TrustInfo
#
# Appends trustInfo tag for UAC user-rights elevation on Vista and above
#
# Parameters [level] [uiaccess]
# level (optional) one of 1, 2, 3 corresponding to asInvoker,
# highestAvailable, requireAdministrator . Default is 1
# uiaccess (optional) true/false or 0/1. Allows application to gain access to
# the protected system UI. Default is 0
#
# Command: DpiAware
#
# Appends dpiAware tag for custom DPI aware applications
#
# Parameters [on_off]
# on_off (optional) true/false or 0/1. Default is 0
#
# Command: SupportedOS
#
# Appends supportedOS tag
#
# Parameters <os_type>
# os_type one of vista, win7 . Multiple OSes can be supported by a single
# manifest
#
它将在 32 位或 64 位 Windows 上运行。
【讨论】:
+1 很有趣,特别是因为源代码可用。我对名称相似性有点困惑,显然“使我的清单”和“无人参与的使我的清单”是不同作者的不同工具。 注意 - 截至 2017 年(8 年过去了......),该项目仍然活跃,偶尔会进行维护更新。 github.com/wqweto/UMMM/commits/master 。它运作良好,我经常使用它。【参考方案5】:要填写 mt.exe 不包含的 ProgID,您可以调用 ProgIDFromCLSID
从注册表中查找它们。这需要在完成清单文件之前进行传统的 COM 注册,但随后,清单文件将是自给自足的。
此 C# 代码将 ProgID 添加到清单中的所有 COM 类:
var manifest = XDocument.Load(fileName);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("s", "urn:schemas-microsoft-com:asm.v1");
foreach (var classElement in manifest.XPathSelectElements("s:assembly/s:file/s:comClass", namespaceManager))
var clsid = Guid.Parse(classElement.Attribute("clsid").Value);
int result = ProgIDFromCLSID(ref clsid, out string progId); if (result != S_OK) throw new COMException($"ProgID lookup failed for clsid.", result);
classElement.SetAttributeValue("progid", progId);
manifest.Save(fileName);
代码依赖于这些互操作定义:
[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
【讨论】:
如果您通过-rgs:
提供 rgs 文件,mt.exe
的最新版本确实包含 ProgID 以上是关于为免注册 COM 生成清单文件的主要内容,如果未能解决你的问题,请参考以下文章
在AndroidManifest(清单文件)中注册activity(活动)及配置主活动更改App图标App名称修改隐藏标题栏
如何为 Windows 上构建的 libxml2.dll 生成清单文件?