Generieren Sie Manifestdateien für registrierungsfreies COM

86

Ich habe einige Anwendungen (einige native, einige .NET), die Manifestdateien verwenden, damit sie vollständig isoliert bereitgestellt werden können , ohne dass eine globale COM-Registrierung erforderlich ist. Beispielsweise wird die Abhängigkeit vom com-Server dbgrid32.ocx in der Datei myapp.exe.manifest, die sich im selben Ordner wie myapp.exe befindet, wie folgt deklariert:

<?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 Datei dbgrid32.ocx wird zusammen mit ihrer eigenen Datei dbgrid32.ocx.manifest im selben Ordner bereitgestellt:

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

Dies alles funktioniert gut, aber das manuelle Verwalten dieser Manifestdateien ist ein bisschen mühsam. Gibt es eine Möglichkeit, diese Dateien automatisch zu generieren? Im Idealfall möchte ich nur die Abhängigkeit der Anwendung von einer Liste von COM-Servern (sowohl native als auch .NET) deklarieren und dann den Rest automatisch generieren lassen. Ist es möglich?

Wim Coenen
quelle
+1 auch: Retagged regfreecom, da dieses Tag häufiger für registrierungsfreies COM
MarkJ

Antworten:

62

Es sieht so aus, als ob die perfekte Lösung noch nicht existiert. Um einige Forschungsergebnisse zusammenzufassen:

Mein Manifest machen ( Link )

Dieses Tool durchsucht ein VB6-Projekt nach COM-Abhängigkeiten, unterstützt jedoch auch die manuelle Deklaration spät gebundener COM-Abhängigkeiten (dh der über CreateObject verwendeten).

Interessanterweise fügt dieses Tool alle Informationen zu den Abhängigkeiten in das Anwendungsmanifest ein. Die Anwendungs-Exe und ihre Abhängigkeiten werden als eine einzelne Assembly beschrieben, die aus mehreren Dateien besteht. Ich hatte vorher nicht bemerkt, dass dies möglich war.

Sieht nach einem sehr guten Tool aus, hat jedoch ab Version 0.6.6 die folgenden Einschränkungen:

  • Startet nur für VB6-Anwendungen mit der VB6-Projektdatei. Schade, denn vieles, was es tut, hat wirklich nichts mit VB6 zu tun.
  • Anwendung im Assistentenstil, nicht zur Integration in einen Erstellungsprozess geeignet. Dies ist kein großes Problem, wenn sich Ihre Abhängigkeiten nicht wesentlich ändern.
  • Freeware ohne Quelle, riskant, sich darauf zu verlassen, da es jederzeit zu Abbruchware werden kann.

Ich habe nicht getestet, ob es .NET-Com-Bibliotheken unterstützt.

regsvr42 ( Codeprojekt-Link )

Dieses Befehlszeilentool generiert Manifestdateien für native COM-Bibliotheken. Es ruft DllRegisterServer auf und spioniert dann die Selbstregistrierung aus, während es Informationen zur Registrierung hinzufügt. Es kann auch ein Client-Manifest für Anwendungen generieren.

Dieses Dienstprogramm unterstützt keine .NET COM-Bibliotheken, da diese keine DllRegisterServer-Routine verfügbar machen.

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

mt.exe

Ein Teil des Windows SDK (kann von MSDN heruntergeladen werden ), das Sie bereits haben, wenn Sie Visual Studio installiert haben. Es ist hier dokumentiert . Sie können damit Manifestdateien für native COM-Bibliotheken wie folgt generieren:

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

Sie können damit Manifestdateien für .NET COM-Bibliotheken wie folgt generieren:

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

Es gibt jedoch einige Probleme mit diesem Tool:

  • Das erste Snippet generiert keine Progid-Attribute, wodurch Clients beschädigt werden, die CreateObject mit Progids verwenden.
  • Das zweite Snippet generiert <runtime>und <mvid>Elemente, die entfernt werden müssen, bevor die Manifeste tatsächlich funktionieren.
  • Die Generierung von Client-Manifesten für Anwendungen wird nicht unterstützt.

Vielleicht werden zukünftige SDK-Versionen dieses Tool verbessern. Ich habe das im Windows SDK 6.0a (Vista) getestet.

Wim Coenen
quelle
1
Ich denke, Sie haben eine Option verpasst: mazecomputer.com, aber ich weiß nichts darüber, was die Website nicht beschreibt.
Bob
MMM leitet auch Nicht-COM-DLLs (Standard-DLLs) um. Ich bin mir nicht sicher, ob die anderen Tools dies tun.
Bob
Nur ein Hinweis für die Nerven: Die Quelle für MMM wurde veröffentlicht. Auf der anderen Seite scheint dies daran zu liegen, dass der Autor beschlossen hat, die Arbeit daran einzustellen. Immer noch ein positives Zeichen.
Gavin
1
Die Site für MMM ist nicht mehr aktiv, aber der Ort, an dem der Quellcode abgelegt wurde, ist für Version 0.9 und Version 0.12 weiterhin verfügbar .
Scott Chamberlain
1
Ich habe gerade mt.exe für .NET COM-Bibliotheken wie oben beschrieben ausprobiert und es funktionierte ohne Änderung des Manifests mit v7.1A. Auch die Links für MMM haben nicht funktioniert, aber Unbeaufsichtigt Make My Manifest scheint einen anständigen Job zu machen.
Bzuillsmith
28

Mit der MSBuild-Task GenerateApplicationManifest habe ich in der Befehlszeile ein Manifest generiert, das mit dem von Visual Studio generierten Manifest identisch ist. Ich vermute, dass Visual Studio während des Builds das GenerateApplicationManifest verwendet . Unten ist mein Build-Skript, das über die Befehlszeile mit msbuild "msbuild build.xml" ausgeführt werden kann.

Vielen Dank an Dave Templin und seinen Beitrag, der mich auf die GenerateApplicationManifest-Aufgabe und die weitere Dokumentation der Aufgabe durch MSDN hingewiesen hat .

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>
mcdon
quelle
Ich denke, dies sollte wirklich als Antwort auf diese Frage markiert werden. Ich benutze dies jetzt, um alle unsere Manifest-Generationen zu automatisieren. Danke @mcdon, du hast mir viel Arbeit erspart.
Pete Magsig
Ich bin damit einverstanden, dass dies die beste Lösung beim Erstellen mit Visual Studio ist. Es ist wahrscheinlich nicht höher bewertet, nur weil es so viel später als die anderen Antworten veröffentlicht wurde
Dschaeffer
Wie füge ich das einem csproj hinzu?
Jle
@jle Ich denke, Sie könnten es Ihrem csproj im AfterBuild-Ziel hinzufügen. Hier ist ein Link von msdn und ein weiterer Beitrag zum Thema Prebuild- und Postbuild-Ereignisse. Hinweis Ich habe nicht getestet, ob dies im csproj enthalten ist, aber ich vermute, dass es funktionieren würde.
Mcdon
Kann das Manifest für eine C # COM-DLL generiert werden, sodass jede Exe es verwenden kann (anstatt für jede Exe ein Manifest zu generieren und die DLLs
einzuschließen
9

Make My Manifest (MMM) ist ein gutes Werkzeug dafür. Es ist auch möglich, ein Skript zu schreiben, um alle Ihre DLL / OCX-Dateien mit mt.exe zu verarbeiten , um für jede ein Manifest zu generieren und sie dann alle zusammenzuführen. MMM ist normalerweise besser / einfacher, da es auch viele spezielle / seltsame Fälle behandelt.

jdve
quelle
3
Ich bin etwas nervös wegen dieser MMM-Sache; Es ist nur ein Blog, Freeware, aber kein Quellcode verfügbar, nur ein Link zu einer "selbstextrahierenden Exe" und ich sehe Kommentare über das Dienstprogramm, das XP zum Absturz bringt. mmm ...
Wim Coenen
Diese "Abstürze" waren das MMM-Dienstprogramm selbst im Sterben. Dies wurde in Version 0.6.5 behoben, aber Sie werden trotzdem 0.6.6 wollen, da es noch eine Beta ist und nicht mehr abläuft. Sie können stattdessen immer MT.EXE verwenden, wie bereits vorgeschlagen.
Bob
mt.exe generiert keine Progids, wenn ich sie auf nativen Com-Servern wie dbgrid32.ocx verwende
Wim Coenen
Die Verwendung von reg free COM mit von .NET erstellten Komponenten kann anscheinend zum Absturz von XP führen - siehe dies stackoverflow.com/questions/617253/…
MarkJ
7

Mit dem Spin-off " Unbeaufsichtigtes Make My Manifest" können Sie Manifeste direkt in automatisierten Builds generieren. Es verwendet eine Skriptdatei, um abhängige COM-Komponenten hinzuzufügen. Dies ist ein Auszug aus dem Beispiel ini mit den verfügbaren Befehlen:

# 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 läuft unter 32- oder 64-Bit-Windows.

wqw
quelle
+1 Interessant, vor allem, weil der Quellcode verfügbar ist. Ich bin ein bisschen verwirrt von der Namensähnlichkeit, anscheinend sind "mach mein Manifest" und "unbeaufsichtigt mach mein Manifest" verschiedene Werkzeuge von verschiedenen Autoren.
Wim Coenen
1
Hinweis - Ab 2017 (8 Jahre später ...) ist dieses Projekt mit gelegentlichen Wartungsupdates noch aktiv. github.com/wqweto/UMMM/commits/master . Es funktioniert gut und ich benutze es routinemäßig.
UuDdLrLrSs
0

Um die ProgIDs auszufüllen, die in mt.exe nicht enthalten sind, können Sie sie aufrufen ProgIDFromCLSID, um sie in der Registrierung nachzuschlagen . Dies erfordert eine herkömmliche COM-Registrierung vor dem Ausfüllen der Manifestdatei. Anschließend ist die Manifestdatei jedoch autark.

Dieser C # -Code fügt die ProgIDs allen COM-Klassen in einem Manifest hinzu:

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 basiert 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;
Edward Brey
quelle