Pertanyaan Hasilkan file manifes untuk COM yang bebas registrasi


Saya punya beberapa aplikasi (beberapa asli, beberapa. NET) yang menggunakan file manifes sehingga mereka bisa dikerahkan dalam isolasi lengkap, tanpa memerlukan registrasi COM global. Sebagai contoh, ketergantungan pada server com dbgrid32.ocx dideklarasikan sebagai berikut di file myapp.exe.manifest yang berada di folder yang sama dengan 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 ditempatkan ke folder yang sama, bersama dengan file dbgrid32.ocx.manifest itu sendiri:

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

Ini semua berfungsi dengan baik tetapi mempertahankan file manifes ini secara manual adalah sedikit rasa sakit. Apakah ada cara untuk menghasilkan file-file ini secara otomatis? Idealnya saya hanya ingin menyatakan ketergantungan aplikasi pada daftar server COM (baik yang asli maupun .NET) dan kemudian biarkan sisanya dibuat secara otomatis. Apa itu mungkin?


76
2018-01-21 16:07


asal


Jawaban:


Sepertinya solusi sempurna belum ada. Untuk meringkas beberapa penelitian:

Jadikan Manifesku (link)

Alat ini memindai proyek VB6 untuk mencari dependensi COM, tetapi juga mendukung deklarasi manual dependensi COM yang terlambat terikat (yaitu yang digunakan melalui CreateObject).

Yang cukup menarik, alat ini menempatkan semua informasi tentang dependensi di dalam manifes aplikasi. Aplikasi exe dan dependensinya digambarkan sebagai rakitan tunggal yang terdiri dari banyak file. Saya tidak menyadari sebelumnya bahwa ini mungkin.

Sepertinya alat yang sangat bagus tetapi pada versi 0.6.6 memiliki batasan berikut:

  • hanya untuk aplikasi VB6, dimulai dari file proyek VB6. Malu, karena banyak hal yang benar-benar tidak ada hubungannya dengan VB6.
  • aplikasi gaya penyihir, tidak cocok untuk diintegrasikan dalam sebuah build proses. Ini bukan masalah besar jika Anda dependensi tidak banyak berubah.
  • freeware tanpa sumber, berisiko untuk mengandalkannya karena bisa menjadi perangkat lunak yang tidak aktif setiap saat.

Saya tidak menguji apakah itu mendukung .NET com libraries.

regsvr42 (tautan codeproject)

Alat baris perintah ini menghasilkan file manifes untuk pustaka COM asli. Ini memanggil DllRegisterServer dan kemudian memata-matai registrasi diri saat menambahkan informasi ke dalam registri. Ini juga dapat menghasilkan manifes klien untuk aplikasi.

Utilitas ini tidak mendukung .NET COM libraries, karena ini tidak mengekspos rutin DllRegisterServer.

Utilitas ditulis dalam C ++. Kode sumber tersedia.

mt.exe

Bagian dari jendela SDK (dapat diunduh dari MSDN), yang sudah Anda miliki jika Anda memasang studio visual. ini didokumentasikan di sini. Anda dapat menghasilkan file manifes untuk pustaka COM asli dengan ini seperti ini:

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

Anda dapat menghasilkan file manifes untuk .NET COM libraries dengan ini seperti ini:

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

Namun, ada beberapa masalah dengan alat ini:

  • Cuplikan pertama tidak akan dihasilkan atribut progid, melanggar klien yang menggunakan CreateObject dengan progids.
  • Cuplikan kedua akan menghasilkan <runtime>dan <mvid> elemen yang harus dilucuti sebelumnya manifes benar-benar berfungsi.
  • Generasi klien bermanifestasi untuk aplikasi tidak didukung.

Mungkin rilis SDK di masa mendatang akan meningkatkan alat ini, saya menguji yang ada di Windows SDK 6.0a (vista).


56
2018-01-25 00:50



Dengan tugas MSBuild GenerateApplicationManifest Saya menghasilkan manifes pada baris perintah yang identik dengan manifes yang dihasilkan Visual Studio. Saya menduga Visual Studio menggunakan GenerateApplicationManifest selama membangun. Di bawah ini adalah skrip build saya yang dapat dijalankan dari baris perintah menggunakan msbuild "msbuild build.xml"

Terima kasih pada Dave Templin dan dia posting yang menunjukkan saya tugas GenerateApplicationManifest, dan MSDN dokumentasi lebih lanjut dari tugas.

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>

23
2018-06-14 15:22



Make My Manifest (MMM) adalah alat yang bagus untuk melakukan ini. Anda juga dapat menulis skrip untuk memproses semua file DLL / OCX Anda menggunakan mt.exe untuk menghasilkan manifes untuk masing-masing dan kemudian menggabungkannya bersama-sama. MMM biasanya lebih baik / mudah, karena juga menangani banyak kasus khusus / aneh.


9
2018-01-21 16:17



Kamu dapat memakai Tanpa pengawasan Make My Manifest spin off untuk menghasilkan manifes secara langsung di build otomatis. Ini menggunakan file skrip untuk menambahkan komponen COM yang bergantung. Ini adalah kutipan dari contoh ini dengan perintah yang tersedia:

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

7
2017-10-14 19:22



Untuk mengisi ProgID yang tidak disertakan oleh mt.exe, Anda bisa menelepon ProgIDFromCLSID untuk mencari mereka dari registri. Ini memerlukan registrasi COM tradisional sebelum menyelesaikan file manifes, tetapi kemudian, file manifes akan mandiri.

Kode C # ini menambahkan ProgID ke semua kelas COM dalam manifes:

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

Kode bergantung pada definisi interop ini:

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;

0
2018-04-06 02:32