Tạo tệp kê khai cho COM không cần đăng ký


87

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ể được triển khai hoàn toàn riêng biệt 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ủ dbgrid32.ocx com đượ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 riêng 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>

Tất cả điều này đều hoạt động tốt nhưng việc duy trì các tệp kê khai này theo cách thủ công là một chút khó khăn. Có cách nào để tạo các tệp này tự động 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. Nó có khả thi không?


+1 cũng: Retagged regfreecom như thẻ đó là phổ biến hơn đối với đăng ký miễn phí COM
MarkJ

Tôi có thể sử dụng phiên bản cao hơn mstscax.dll trong thư mục cài đặt của riêng tôi bằng tệp kê khai không?
Acewind

@acewind có. (Bạn có thể muốn đăng một câu hỏi mới với nhiều chi tiết hơn.)
UuDdLrLrSs

@UuDdLrLrSs Tin tốt! Tôi đăng một câu hỏi mới ở đây: stackoverflow.com/questions/63575746/…
Acewind

Câu trả lời:


64

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

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

Công cụ này quét một dự án VB6 để tìm kiế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 giới hạn cuối (tức là những phụ thuộc được sử dụng qua CreateObject).

Khá thú vị, 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. Exe của ứng dụng và các phần phụ thuộc của nó được mô tả như một tập hợp đơn bao gồm nhiều tệp. Tôi đã không nhận ra rằng điều này là có thể trước đây.

Có vẻ như một công cụ rất tốt nhưng kể từ 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. Thật xấu hổ, vì rất nhiều thứ nó thực sự không liên quan gì đến VB6.
  • ứng dụng kiểu thuật sĩ, không thích hợp để tích hợp trong một quy trình xây dựng. Đây không phải là một vấn đề lớn nếu sự phụ thuộc của bạn không thay đổi nhiều.
  • phần mềm miễn phí không có nguồn, rủi ro khi dựa vào nó vì nó có thể trở thành phần mềm bị 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 codeproject )

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 đó do thám quá trình tự đăng ký khi nó thêm thông tin vào sổ đăng ký. Nó cũng có thể tạo một tệp kê khai máy khách 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 hiển thị quy 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 Windows SDK (có thể tải xuống từ MSDN ) mà bạn đã có nếu bạn đã cài đặt visual studio. Nó được ghi lại ở đây . Bạn có thể tạo tệp kê khai cho các thư viện COM gốc bằng nó như thế này:

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ư thế này:

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ỡ các khách hàng sử dụng CreateObject với progid.
  • Đoạn mã thứ hai sẽ tạo <runtime><mvid>các phần tử cần được loại bỏ trước khi tệp kê khai thực sự hoạt động.
  • Không hỗ trợ tạo tệp kê khai máy khách cho các ứng dụng.

Có thể 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).


1
Tôi nghĩ rằng bạn đã bỏ lỡ một lựa chọn: mazecomputer.com nhưng tôi không biết gì về nó mà trang web không mô tả.
Bob

MMM cũng sẽ chuyển hướng các DLL không phải COM (tiêu chuẩn). Tôi không chắc các công cụ khác làm được điều này.
Bob

Chỉ cần một lưu ý cho người lo lắng: 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

2
Trang web dành cho MMM vẫn chưa xuất hiện nhưng nơi đặt mã nguồn vẫn có sẵn cho v0.9v0.12 .
Scott Chamberlain

1
Chỉ cần thử mt.exe cho các thư viện .NET COM như được mô tả ở trên và nó hoạt động mà không sửa đổi tệp kê khai bằng v7.1A. Ngoài ra, các liên kết cho MMM không hoạt động nhưng Make My Manifest của Unattented có vẻ hoạt động tốt.
bzuillsmith

28

Với tác vụ MSBuild GenerateApplicationManifest, tôi đã tạo một tệp kê khai tại dòng lệnh giống 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à tập lệnh xây dựng của tôi có thể 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 đăng của anh ấy đã chỉ cho tôi nhiệm vụ GenerateApplicationManifesttài liệu bổ sung của MSDN 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>

Tôi nghĩ rằng đây thực sự nên được đánh dấu là câu trả lời cho câu hỏi này. Bây giờ tôi đang sử dụng điều này để tự động hóa tất cả quá trình tạo tệp kê khai của chúng tôi. Cảm ơn bạn @mcdon, bạn đã tiết kiệm 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 đánh giá cao hơn chỉ vì nó đã được đăng rất nhiều muộn hơn câu trả lời khác
dschaeffer

làm thế nào để thêm cái này vào một csproj?
jle

@jle Tôi nghĩ bạn có thể thêm nó vào csproj của mình trong mục tiêu AfterBuild. Đây là một liên kết từ msdnmột bài đăng khác về chủ đề các sự kiện xây dựng trước và xây dựng sau. Lưu ý rằng tôi chưa thử nghiệm bao gồm điều này trong csproj, nhưng tôi nghi ngờ nó sẽ hoạt động.
mcdon

Có thể biểu hiện được tạo ra cho một C # COM DLL, do đó bất kỳ exe có thể tiêu thụ nó (chứ không phải tạo ra một biểu hiện trên mỗi exe, và bao gồm các file DLL?)
GilesDMiddleton

9

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


3
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ó sẵn mã nguồ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 bình luận về tiện ích khiến XP bị sập. mmm ...
Wim Coenen

Những "sự cố" đó chính là tiện ích MMM đang chết. Điều này đã được sửa trong phiên bản 0.6.5 nhưng bạn vẫn muốn có 0.6.6, vì khi vẫn còn là bản beta, nó không còn hết hạn nữa. Bạn luôn có thể sử dụng MT.EXE thay thế mặc dù như đã được đề xuất.
Bob

mt.exe không tạo của progid khi tôi sử dụng nó trên máy chủ com bản địa như dbgrid32.ocx
Wim Coenen

Sử dụng miễn phí reg COM với .NET là tác giả của các thành phần có thể rõ ràng nguyên nhân XP sụp đổ - xem này stackoverflow.com/questions/617253/...
MarkJ

8

Bạn có thể sử dụng biến Tệp kê khai của tôi không cần giám sát để 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 script để thêm các thành phần COM phụ thuộc vào. Đây là một đoạn trích từ ini mẫu 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
#

Nó sẽ chạy trên Windows 32 hoặc 64 bit.


+1 Thú vị, đặc biệt là vì mã nguồn có sẵn. Tôi hơi bối rối vì sự giống nhau về tên gọi, rõ ràng "tạo bản kê khai của tôi" và "tạo bản kê khai 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

2
Lưu ý - tính đến năm 2017 (8 năm kể từ ngày ...) dự án này vẫn đang hoạt động với các bản 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.
UuDdLrLrSs

0

Để điền vào các ProgID mà mt.exe không bao gồm, bạn có thể gọi ProgIDFromCLSIDđể tra cứu 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 cấp.

Mã C # này thêm ProgID vào tất cả các lớp COM trong một 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 tương tác sau:

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.