Frage

Ich habe einige Anwendungen (einige einheimische, einige .NET), die so Manifest-Dateien verwenden, dass sie in völligen Isolation eingesetzt werden, ohne dass globale COM-Registrierung erforderlich ist. Zum Beispiel wird die Abhängigkeit von dem DBGRID32.OCX com-Server erklärt, wie in der myapp.exe.manifest Datei folgt, die in dem gleichen Ordner wie myapp.exe sitzt:

<?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>

Die DBGRID32.OCX in demselben Ordner bereitgestellt wird, zusammen mit einem eigenen dbgrid32.ocx.manifest-Datei:

<?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>

Das alles funktioniert gut, aber diese Manifest-Dateien manuell beibehalten ist ein bisschen wie ein Schmerz. Gibt es eine Möglichkeit, diese Dateien automatisch zu generieren? Im Idealfall würde Ich mag nur die Abhängigkeit der Anwendung erklärt auf einer Liste von COM-Server (sowohl native als auch .NET) und dann der Rest automatisch generiert werden kann. Ist es möglich?

War es hilfreich?

Lösung

Es sieht aus wie die perfekte Lösung ist noch nicht vorhanden. Zusammenfassend einige der Forschung:

Mein Manifest ( Link )

Dieses Tool scannt ein VB6-Projekt für COM Abhängigkeiten zu suchen, aber es unterstützt auch manuelle Erklärung spät gebundene COM Abhängigkeiten (das heißt solche, die über Create verwendet wird).

Interessanterweise stellt dieses Tool alle Informationen über die Abhängigkeiten innerhalb der Anwendung manifestieren. Die Anwendung exe und ihre Abhängigkeiten als eine einzige Einheit aus mehreren Dateien beschrieben. Ich hatte nicht bemerkt, vor, dass dies möglich war.

Sieht aus wie ein sehr gutes Werkzeug, aber ab der Version 0.6.6 hat die folgenden Einschränkungen:

  • nur für VB6-Anwendungen, startet von VB6 Projektdatei. Schade, denn eine Menge von dem, was es tut, hat wirklich nichts zu tun mit VB6.
  • Zaubererartschnittstelle Anwendung nicht geeignet in einem Build zu integrieren Prozess. Das ist kein großes Problem, wenn Ihr Abhängigkeiten nicht viel ändern.
  • Freeware ohne Quelle, riskant, sich auf sie verlassen, weil es abandonware jederzeit werden könnte.

Ich habe nicht testen, ob es .NET unterstützt COM-Bibliotheken.

regsvr42 ( Codeproject Link )

Dieses Kommandozeilen-Tool erzeugt Manifest-Dateien für native COM-Bibliotheken. Es ruft DllRegisterServer und dann Spione auf der Selbstregistrierung, wie sie Informationen in die Registrierung hinzufügt. Es kann auch ein Client-Manifest für Anwendungen erzeugen.

Dieses Dienstprogramm unterstützt Bibliotheken nicht .NET COM, da diese keine DllRegisterServer Routine aus.

Das Dienstprogramm ist in C ++ geschrieben. Der Quellcode ist verfügbar.

mt.exe

Ein Teil des Windows SDK (kann von MSDN ), die Sie bereits haben, wenn Sie Visual Studio installiert haben. Es ist hier dokumentiert. Sie können mit ihm wie dieses Manifest-Dateien für native COM-Bibliotheken generieren:

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

Sie können generieren Manifest-Dateien für .NET COM-Bibliotheken mit es wie folgt aus:

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

Es gibt jedoch einige Probleme mit diesem Tool:

  • Der erste Schnipsel nicht erzeugen progid Attribute, brechen Kunden die Verwendung von Create mit ProgIDs.
  • Die zweite Snippet generieren Elemente <runtime> und <mvid> die müssen vor gezupft werden die Manifeste tatsächlich funktionieren.
  • Generation von Client manifestiert für Anwendungen werden nicht unterstützt.

Vielleicht Zukunft SDK Versionen werden dieses Tool verbessern, ich die eine im Windows SDK 6.0a (vista) getestet.

Andere Tipps

Mit der MSBuild-Aufgabe GenerateApplicationManifest erzeugen ich ein Manifest auf Befehl Linie identisch mit dem Manifest Visual Studio erzeugt. Ich vermute, dass Visual Studio verwendet den GenerateApplicationManifest während des Baus. Unten ist mein Build-Skript, das von der Kommandozeile ausgeführt werden kann mit msbuild „msbuild build.xml“

Dank Dave Templin und seine Post, die mir die die GenerateApplicationManifest Aufgabe zugespitzt und MSDN < a href = "http://msdn.microsoft.com/en-us/library/6wc2ccdc.aspx" rel = "noreferrer"> weitere Dokumentation der Aufgabe .

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) ein nettes Tool ist, dies zu tun. Es ist auch möglich, ein Skript zu schreiben, alle Ihre DLL / OCX-Dateien mit mt.exe zu verarbeiten eine Manifest für jeden zu erzeugen, und kombiniert sich dann alle zusammen. MMM ist in der Regel besser / einfacher, weil es auch viele spezielle / seltsame Fälle behandelt.

Sie können mit Unattended Make My Manifest ausgliedern Manifeste direkt zu erzeugen, die in automatisierten Builds. Es verwendet eine Skriptdatei abhing COM-Komponenten hinzuzufügen. Dies ist ein Auszug aus der Probe ini mit den zur Verfügung stehenden Befehle:

# 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
#

Es wird auf 32 oder 64 Bit-Windows ausgeführt werden.

in den ProgIDs zu füllen, die mt.exe nicht enthalten, können Sie ProgIDFromCLSID nennen sie aus der Registrierung zu suchen. Dies erfordert traditionelle COM-Registrierung vor der Manifest-Datei abgeschlossen, aber anschließend wird die Manifest-Datei autark sein.

Der C # -Code fügt die ProgIDs für alle COM-Klassen in einem Manifest:

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);

Der Code stützt sich auf diesen Interop-Definitionen:

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top