登録不要のCOM用のマニフェストファイルを生成する
-
19-08-2019 - |
質問
マニフェストファイルを使用して、完全な分離で展開、グローバルな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の両方)のリストに対するアプリケーションの依存関係を宣言し、残りが自動的に生成されるようにします。可能ですか?
解決
完璧なソリューションはまだ存在しないようです。いくつかの研究を要約するには:
マニフェストを作成(リンク)
このツールはVB6プロジェクトをスキャンしてCOM依存関係を探しますが、遅延バインドされたCOM依存関係(つまり、CreateObjectを介して使用されるもの)の手動宣言もサポートします。
興味深いことに、このツールは依存関係に関するすべての情報をアプリケーションマニフェストに入れます。アプリケーションexeとその依存関係は、複数のファイルで構成される単一のアセンブリとして記述されます。これが可能であることを私は前に気づかなかった。
非常に優れたツールのように見えますが、バージョン0.6.6の時点では、次の制限があります。
- VB6アプリケーションのみ、開始 VB6プロジェクトファイルから。恥、なぜなら それがすることの多くは本当に何の関係もない VB6で。
- ウィザード形式のアプリケーションではなく ビルドに統合するのに適しています プロセス。あなたの場合、これは大きな問題ではありません 依存関係はそれほど変わりません。
- ソースのないフリーウェア。いつでも放棄される可能性があるため、信頼するのは危険です。
.NET comライブラリをサポートしているかどうかはテストしませんでした。
regsvr42 ( codeprojectリンク)
このコマンドラインツールは、ネイティブCOMライブラリのマニフェストファイルを生成します。 DllRegisterServerを呼び出してから、レジストリに情報を追加するときに自己登録をスパイします。また、アプリケーションのクライアントマニフェストを生成できます。
.NET COMライブラリはDllRegisterServerルーチンを公開しないため、このユーティリティは.NET COMライブラリをサポートしません。
ユーティリティはC ++で記述されています。ソースコードが利用可能です。
mt.exe
Windows SDKの一部( MSDN )。これは、Visual Studioがインストールされている場合に既に持っています。 ここに記載されています。 次のようにして、ネイティブ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
ただし、このツールにはいくつかの問題があります:
- 最初のスニペットは生成されません progid属性、クライアントの破壊 CreateObjectをprogidsで使用します。
- 2番目のスニペットは生成します
<runtime>
および<mvid>
要素 前に除去する必要があります マニフェストは実際に機能します。 - のクライアントマニフェストの生成 アプリケーションはサポートされていません。
今後のSDKリリースでこのツールが改善される可能性があるため、Windows SDK 6.0a(vista)でテストしました。
他のヒント
MSBuildタスクで GenerateApplicationManifest コマンドでマニフェストを生成しましたVisual Studioが生成するマニフェストと同一の行。 Visual Studioは、ビルド中に GenerateApplicationManifest を使用していると思われます。以下は、msbuild <!> quot; msbuild build.xml <!> quot;
を使用してコマンドラインから実行できるビルドスクリプトです。Dave Templinと彼の GenerateApplicationManifestタスクを示した投稿、およびMSDNの< a href = "http://msdn.microsoft.com/en-us/library/6wc2ccdc.aspx" rel = "noreferrer">タスクの詳細ドキュメント。
build.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>
Make My Manifest(MMM)は、これを行うための便利なツールです。 mt.exeを使用して、すべてのDLL / OCXファイルを処理するスクリプトを作成することもできます。 を使用して、それぞれのマニフェストを生成し、それらをすべてマージします。 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で実行されます。
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;