我有一些应用程序(一些本机的,一些.NET)使用清单文件,以便它们可以 完全隔离部署, ,无需任何全局 COM 注册。例如,对 dbgrid32.ocx com 服务器的依赖关系在与 myapp.exe 位于同一文件夹中的 myapp.exe.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="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)列表的依赖关系,然后让其余部分自动生成。是否可以?

有帮助吗?

解决方案

它看起来像个完美的解决方案,尚不存在。总结的一些研究:

让我的清单 (链接)

这个工具扫描一个维生素b6项目寻找COM依赖关系,但它也支持宣言》手册的后期限COM依存关系(即那些用于经则).

有趣的是,这个工具,把所有有关的信息的依赖内部应用程序清单。该应用程序exe及其依赖性被描述为一个单一的组成的多个文件。我没有意识到之前,这是可能的。

看起来像一个非常好的工具,但为的版本0.6.6它具有下列限制:

  • 只为维生素b6应用程序,开始 维生素b6从项目文件。耻辱,因为 很多它做什么,真的没有做 与维生素b6.
  • 向导风格应用程序,不 合适的融入建立一个 过程。这不是一个巨大的问题,如果你的 依赖关系不改变很多。
  • 免费的没有来源,危险依赖于它,因为它可能成为放弃在任何时刻。

我没有测试是否支持。净com库。

regsvr42 (演示的链接)

这个命令行工具产生的清单的文件为地COM库。它援引DllRegisterServer然后间谍的自注册,因为它增加了信息纳入注册表。它也可以产生一个客户清单的应用程序。

这个工具不支持。净COM库,因为这些不公DllRegisterServer程序。

该工具是用C++编写的.源代码是可用的。

mt.exe

Windows SDK的一部分(可下载 MSDN),其中你已经有如果你有些工作室安装。它是 记录在这里.你可以产生清单的文件为地COM库,它是这样的:

mt.exe -tlb:mycomlib.ocx -dll:mycomlib.ocx -out:mycomlib.ocx.manifest

你可以产生清单的文件。净COM库,它是这样的:

mt.exe -managedassemblyname:netlib.dll -nodependency -out:netlib.dll.manifest

然而,有一些问题与这种工具:

  • 的第一段不会产生 程序id属性,打破的客户 其使用则与progid.
  • 第二段将产生 <runtime><mvid> 元素 这需要剥离出来之前 该清单的实际工作。
  • 代客户清单 应用程序是不支持的。

也许未来SDK稿将改善这个工具,我测试了一个在窗SDK6.0a(vista)。

其他提示

使用 MSBuild 任务 生成应用程序清单 我在命令行生成了一个与 Visual Studio 生成的清单相同的清单。我怀疑 Visual Studio 使用 生成应用程序清单 在构建期间。下面是我的构建脚本,可以使用 msbuild“msbuild build.xml”从命令行运行

感谢戴夫·坦普林和他的 帖子向我指出了GenerateApplicationManifest任务, ,以及 MSDN 的 任务的进一步记录.

构建.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>

让我的清单(MMM)是这样做的一个很好的工具。它也可以写一个脚本来处理所有的DLL /使用OCX文件 mt.exe 生成清单的每一个,然后将它们合并在一起。 MMM通常是更好/更容易,因为它也处理大量的特殊/怪异的情况。

您可以使用无人让我的清单分拆的自动化生成直接生成清单。它使用一个脚本文件来添加依赖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中运行。

要在ProgIDs的填补mt.exe不包括,你可以调用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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top