Câu hỏi Tạo tệp kê khai cho COM miễn phí đăng ký


Tôi có một số ứng dụng (một số bản địa, một số .NET) sử dụng tệp kê khai để chúng có thể triển khai hoàn toàn cách ly, mà không yêu cầu bất kỳ đăng ký COM toàn cầu nào. Ví dụ, sự phụ thuộc vào máy chủ com dbgrid32.ocx được khai báo như sau trong tệp myapp.exe.manifest nằm trong cùng thư mục với 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 được triển khai vào cùng một thư mục, cùng với tệp dbgrid32.ocx.manifest của chính nó:

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

Điều này tất cả các công trình tốt nhưng duy trì các tập tin biểu hiện bằng tay là một chút đau đớn. Có cách nào để tự động tạo các tệp này không? Lý tưởng nhất là tôi chỉ muốn khai báo sự phụ thuộc của ứng dụng vào danh sách các máy chủ COM (cả bản địa và .NET) và sau đó để phần còn lại được tạo tự động. Có thể không?


76
2018-01-21 16:07


gốc


+1: Regagreecom được gắn thẻ lại vì thẻ đó phổ biến hơn đối với đăng ký miễn phí COM - MarkJ


Các câu trả lời:


Có vẻ như giải pháp hoàn hảo chưa tồn tại. Để tóm tắt một số nghiên cứu:

Tạo Manifest của tôi (liên kết)

Công cụ này quét một dự án VB6 để tìm các phụ thuộc COM, nhưng nó cũng hỗ trợ khai báo thủ công các phụ thuộc COM bị ràng buộc trễ (tức là các phụ thuộc được sử dụng thông qua CreateObject).

Điều thú vị là, công cụ này đặt tất cả thông tin về các phụ thuộc bên trong tệp kê khai ứng dụng. Ứng dụng exe và các phụ thuộc của nó được mô tả như một assembly đơn gồm nhiều tệp. Tôi đã không nhận ra trước đó rằng điều này là có thể.

Trông giống như một công cụ rất tốt nhưng với phiên bản 0.6.6 nó có những hạn chế sau:

  • chỉ dành cho các ứng dụng VB6, bắt đầu từ tệp dự án VB6. Xấu hổ, bởi vì rất nhiều những gì nó thực sự không có gì để làm với VB6.
  • ứng dụng kiểu thuật sĩ, không thích hợp để tích hợp trong một bản dựng quá trình. Đây không phải là một vấn đề lớn nếu phụ thuộc không thay đổi nhiều.
  • phần mềm miễn phí không có nguồn, rủi ro để dựa vào nó bởi vì nó có thể trở thành phần mềm bỏ rơi bất cứ lúc nào.

Tôi không kiểm tra xem nó có hỗ trợ các thư viện .NET com hay không.

regsvr42 (liên kết mã hóa)

Công cụ dòng lệnh này tạo tệp kê khai cho các thư viện COM gốc. Nó gọi DllRegisterServer và sau đó gián điệp vào việc tự đăng ký vì nó thêm thông tin vào sổ đăng ký. Nó cũng có thể tạo ra một bản kê khai ứng dụng cho các ứng dụng.

Tiện ích này không hỗ trợ các thư viện .NET COM, vì các thư viện này không lộ ra một thường trình DllRegisterServer.

Tiện ích được viết bằng C ++. Mã nguồn có sẵn.

mt.exe

Một phần của cửa sổ SDK (có thể được tải xuống từ MSDN), mà bạn đã có nếu bạn đã cài đặt studio trực quan. Nó là tài liệu ở đây. Bạn có thể tạo tệp kê khai cho các thư viện COM gốc với nó như sau:

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

Bạn có thể tạo tệp kê khai cho các thư viện .NET COM với nó như sau:

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

Tuy nhiên, có một số vấn đề với công cụ này:

  • Đoạn mã đầu tiên sẽ không tạo thuộc tính progid, phá vỡ khách hàng sử dụng CreateObject với progids.
  • Đoạn mã thứ hai sẽ tạo <runtime><mvid> yếu tố cần được loại bỏ trước các tệp kê khai thực sự hoạt động.
  • Tạo các tệp kê khai của khách hàng cho các ứng dụng không được hỗ trợ.

Có lẽ các bản phát hành SDK trong tương lai sẽ cải thiện công cụ này, tôi đã thử nghiệm công cụ này trong Windows SDK 6.0a (vista).


56
2018-01-25 00:50



Tôi nghĩ bạn đã bỏ lỡ một lựa chọn: mazecomputer.com nhưng tôi không biết gì về trang web không mô tả. - Bob
MMM cũng sẽ chuyển hướng các tệp DLL không phải COM (chuẩn). Tôi không chắc chắn các công cụ khác làm điều này. - Bob
Chỉ cần một lưu ý cho thần kinh: nguồn cho MMM đã được phát hành. Mặt khác, điều này có vẻ là do tác giả đã quyết định ngừng làm việc trên nó. Vẫn là một dấu hiệu tích cực. - Gavin
Trang web dành cho MMM được nolonger lên nhưng vị trí nơi mã nguồn được đặt vẫn có sẵn cho v0.9và v0.12. - Scott Chamberlain
Chỉ cần thử mt.exe cho các thư viện .NET COM như mô tả ở trên và nó làm việc mà không có sửa đổi đối với tệp kê khai sử dụng v7.1A. Ngoài ra, các liên kết cho MMM không hoạt động nhưng Unattented Tạo Manifest của tôi dường như làm một công việc tốt. - bzuillsmith


Với tác vụ MSBuild GenerateApplicationManifest Tôi tạo ra một biểu hiện tại dòng lệnh giống hệt với tệp kê khai Visual Studio tạo ra. Tôi nghi ngờ Visual Studio sử dụng GenerateApplicationManifest trong quá trình xây dựng. Dưới đây là kịch bản xây dựng của tôi có thể được chạy từ dòng lệnh bằng cách sử dụng msbuild "msbuild build.xml"

Cám ơn Dave Templin và bài viết đã chỉ cho tôi nhiệm vụ GenerateApplicationManifestvà MSDN tài liệu hướng dẫn thêm về nhiệm vụ.

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



Tôi nghĩ điều này thực sự nên được đánh dấu là câu trả lời cho câu hỏi này. Tôi hiện đang sử dụng tính năng này để tự động hóa tất cả các tệp kê khai của chúng tôi. Cảm ơn bạn @mcdon, bạn đã lưu cho tôi rất nhiều công việc. - Pete Magsig
Tôi đồng ý đây là giải pháp tốt nhất khi xây dựng với Visual Studio. Nó có lẽ không được xếp hạng cao hơn chỉ vì nó đã được đăng rất muộn so với các câu trả lời khác - dschaeffer
làm thế nào để thêm này vào một csproj? - jle
@ jle Tôi nghĩ bạn có thể thêm nó vào csproj của bạn trong mục tiêu AfterBuild. Đây là một liên kết từ msdnvà bài đăng khác về chủ đề của sự kiện prebuild và postbuild. chú thích Tôi đã không thử nghiệm bao gồm điều này trong csproj, nhưng tôi nghi ngờ nó sẽ làm việc. - mcdon


Tạo Manifest của tôi (MMM) là một công cụ tốt để làm điều này. Cũng có thể viết một kịch bản để xử lý tất cả các tệp DLL / OCX của bạn bằng cách sử dụng mt.exe để tạo một tệp kê khai cho từng tệp và sau đó hợp nhất chúng lại với nhau. MMM thường tốt hơn / dễ dàng hơn, bởi vì nó cũng xử lý rất nhiều trường hợp đặc biệt / kỳ lạ.


9
2018-01-21 16:17



Tôi hơi lo lắng về điều MMM này; nó chỉ là một blog, phần mềm miễn phí nhưng không có mã nguồn có sẵn, chỉ có một liên kết đến một "exe tự giải nén" và tôi thấy các nhận xét về tiện ích khiến XP bị lỗi. mmm ... - Wim Coenen
Những "sự cố" này là chính bản thân tiện ích MMM chết. Điều này đã được sửa trong phiên bản 0.6.5 nhưng bạn sẽ muốn 0.6.6 dù sao, kể từ khi vẫn còn là một bản beta nó không còn hết hạn. Bạn luôn có thể sử dụng MT.EXE thay vì đã được đề xuất. - Bob
mt.exe không tạo ra progid khi tôi sử dụng nó trên các máy chủ com gốc như dbgrid32.ocx - Wim Coenen
Sử dụng COM miễn phí COM với các thành phần .NET authored dường như có thể khiến XP gặp sự cố - hãy xem stackoverflow.com/questions/617253/… - MarkJ


Bạn có thể dùng Không cần giám sát Tạo Manifest của tôi quay vòng để tạo tệp kê khai trực tiếp trong các bản dựng tự động. Nó sử dụng một tập lệnh để thêm các thành phần COM phụ thuộc. Đây là trích đoạn từ mẫu ini với các lệnh có sẵn:

# 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



+1 Thú vị, đặc biệt là vì mã nguồn có sẵn. Tôi là một chút bối rối bởi sự giống nhau tên, rõ ràng là "làm cho biểu hiện của tôi" và "không giám sát làm cho biểu hiện của tôi" là các công cụ khác nhau của các tác giả khác nhau. - Wim Coenen
Lưu ý - tính đến năm 2017 (8 năm trên ...) dự án này vẫn hoạt động với các cập nhật bảo trì không thường xuyên. github.com/wqweto/UMMM/commits/master . Nó hoạt động tốt và tôi sử dụng nó thường xuyên. - DaveInCaz
Công cụ tuyệt vời, nhưng rõ ràng nó là 16-bit (?) Vì vậy không thể chạy dưới hệ thống x64, hoặc am'I thiếu một cái gì đó? - unlikely
@unlikely Hãy thử bản nhị phân mới nhất từ github.com/wqweto/UMMM/releases - nên hoạt động trên các hệ điều hành x64 - wqw


Để điền vào các ProgID mà mt.exe không bao gồm, bạn có thể gọi ProgIDFromCLSID để tìm kiếm chúng từ sổ đăng ký. Điều này yêu cầu đăng ký COM truyền thống trước khi hoàn thành tệp kê khai, nhưng sau đó, tệp kê khai sẽ tự cung tự cấp.

Mã C # này thêm các ProgID vào tất cả các lớp COM trong tệp kê khai:

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

Mã dựa trên các định nghĩa interop này:

[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