2009-02-20 36 views
20

Sau asking about what Visual Studio does to register a COM Library, nó trở nên rõ ràng rằng VS đã làm hai việc đăng ký COM:Typelib Generation và cài đặt với WiX

  1. đăng ký COM Library
  2. Tạo và đăng ký một thư viện kiểu

trực quan Studio dường như thực hiện việc đăng ký này bằng regasm.exe. Đối với phần đầu tiên (đăng ký COM trực tiếp) sử dụng tallow hoặc heat (WiX 2.0 hoặc WiX 3.0) dường như nhận được tất cả thông tin đăng ký COM cơ bản chính xác.

Tuy nhiên, những gì tallow/nhiệt dường như không làm là thiết lập cài đặt thư viện kiểu. Nó sẽ có thể tạo ra một hành động tùy chỉnh để làm điều này với một trình cài đặt WiX và regasm.exe, nhưng gọi hành động tùy chỉnh không phải là thực hành tốt nhất khi nói đến trình cài đặt dựa trên trình cài đặt Microsoft.

Sau khi nghiên cứu thêm, có vẻ như một msi có khả năng tạo thư viện kiểu khi cài đặt. Trong thực tế, WiX dường như có sự hỗ trợ trực tiếp cho nó! Trong phần tử tệp, bạn có thể thêm phần tử Typelib. Trên thực tế, an article over here on wix có ví dụ về việc điền phần tử TypeLib với các phần tử Interface.

Dường như có ít nhất hai thuộc tính cần thiết để một yếu tố giao diện:

  1. Id
  2. Tên

Larry Osterman speaks about the other parts of the interface that need to be registered for a TypeLib in general, nhập cảnh giao diện này có vẻ để chăm sóc các bộ phận cá nhân. Larry nói rằng chúng ta cần phải xác định ProxyStubClassId32 là "{00020424-0000-0000-C000-000000000046}", vì vậy chúng ta có thể dễ dàng thêm điều đó.

Nơi để đi từ đó và những gì cần điền cho các yếu tố Giao diện khác nhau đã khiến tôi bối rối. Tôi đã đi trước và thêm phần tử TypeLib vào tệp wix của tôi và nó biên dịch thành công. Tôi là một chút clueless như thế nào để thiết lập các yếu tố giao diện mặc dù. Chúng ta cần phải làm gì để điền vào phần tử TypeLib đúng cách và tôi có thể sử dụng những ứng dụng hoặc công cụ nào để có được nó?

Câu trả lời dưới đây của wcoenen có vẻ hứa hẹn ... Tôi sẽ cho nó một shot.

Cập nhật: Đã đăng giải pháp cuối cùng của tôi dưới đây làm câu trả lời.

+0

+1, tôi muốn tất cả các câu hỏi trên trang web này được viết như thế này ... –

+0

Heh, tôi cho nó ảnh đẹp nhất của tôi. :) –

Trả lời

13

Đây là cách giải quyết vấn đề này của người đàn ông lười biếng: Sử dụng heat từ WiX 3.0.

Nếu bạn có một thư viện kiểu tạo tự động và cài đặt thông qua regasm, heat thể lấy .tlb như một cuộc tranh cãi trong

heat file c:\my\path\to\my.tlb -out tlb.wxs 

Nó sẽ tạo ra tất cả các typelib và giao diện yếu tố mà bạn cần phải đăng ký. Điều này sẽ không giải quyết được vấn đề cần phải biết chúng trước thời hạn, và nó sẽ không giải quyết vấn đề GUID thay đổi khi phiên bản của hội đồng thay đổi (ngay cả khi giao diện không - đó là lần duy nhất bạn ' có nghĩa vụ phải thay đổi nó) nhưng nó sẽ giúp bạn tiến tới đó.

+2

+1 Tôi không biết bạn có thể thu thập tập tin tlb với heat.exe –

+1

Mặc dù tôi không nghĩ rằng có bất kỳ GUIDs biến nếu bạn khai báo chúng trong mã .NET của bạn với một GUID [lắp ráp: Guid ("... ")] thuộc tính cho các typelib và một [Guid (" ... ")] thuộc tính cho các giao diện COM và các lớp học –

+1

Đối với COM guid của tôi nghĩ rằng bạn là chính xác. Thật không may là Thư viện kiểu có các hướng dẫn khác nhau. : | Tôi tự hỏi nếu có một thuộc tính để thiết lập những guids quá ... –

7

Bí quyết sau đây có thể giúp thu thập bất kỳ thay đổi đăng ký nào và chuyển chúng thành tệp wxs, bao gồm phần tử typelib bạn đang theo dõi.

  1. Thứ nhất, mang lại registry của bạn trở lại trong một tiểu bang nơi thư viện kiểu không được đăng ký:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb /u mylib.dll 
    
  2. xuất khẩu nhà nước trong sạch này của registry để HKLM-trước.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-before.reg 
    
  3. Đăng ký thư viện kiểu một lần nữa:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb mylib.dll 
    
  4. Xuất trạng thái mới của registry để HKLM-after.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-after.reg 
    
  5. Bây giờ chúng ta có hai tệp văn bản, hklm-before.reg và hklm-after.reg. Tạo một tệp diff.reg chỉ chứa các khác biệt có liên quan giữa các tệp này. Bạn có thể tìm thấy sự khác biệt một cách dễ dàng với một công cụ khác. Tôi thích sử dụng công cụ khác có trong TortoiseSVN vì tôi đã sử dụng nó mỗi ngày. (WinDiff dường như không hoạt động tốt trong trường hợp này do các vấn đề mã hóa văn bản.)

  6. Bây giờ chúng tôi có thể chuyển đổi diff.reg thành một .wx bằng cách gọi heat.exe với lệnh reg. (Yêu cầu wix 3.5 hoặc mới hơn.)

    heat reg diff.reg -out typelib.wxs 
    
+2

Ouch. Không có thắc mắc họ nói rằng việc tạo ra WiX ngay bây giờ là một quá trình thủ công, euch! –

+1

Đó là vì WIX chủ yếu chỉ là một định dạng XML ánh xạ tới cơ sở dữ liệu trình cài đặt Windows (msi/msm/mst/pcp). Ví dụ, có một phần tử "typelib" vì cũng có một bảng "typelib". Công cụ thu thập heat.exe là giá trị gia tăng hữu ích nhưng nó cần các chuyên gia để hoàn thành nó. –

+0

Do WiX 3.10 nhiệt có tham số reg đặc biệt dành riêng cho việc thu thập tệp đăng ký. –

3

Dường như đăng ký một thư viện Type, các cách tốt nhất là nên tạo riêng IDL hoặc ODL tập tin của bạn, mà sẽ chứa các GUID của bạn. Typelib được tạo trực tiếp từ Assembly là [i] phụ thuộc [/ i] vào số phiên bản assembly: GUID được tạo dựa trên thông tin đó, ngay cả khi giao diện không thay đổi. Visual Studio sử dụng regasm để đăng ký và tạo ra typelib. Bên dưới đó, nó sử dụng RegisterTypeLib, một cuộc gọi win32. Sử dụng phần tử typelib dường như làm một cái gì đó tương tự. Không tốt.

Tuy nhiên! Tạo thư viện kiểu bằng tay rất đau đớn. Có thể nhận được những GUID theo cách khác: đào chúng ra khỏi typelib và tự tạo ra các phần tử.

Larry Osterman có thông tin cần thiết: có các khóa đăng ký nhất định cần được đặt. Bạn có thể làm những người có bảng Registry (và trong Wix3, có nghĩa là các yếu tố RegistryValue.) Bí quyết ở đây là nhận được GUIDs: bất kỳ GUID cũ sẽ không hoạt động. Thông thường, việc nhận được GUID chỉ đơn giản là vấn đề tìm kiếm IDL cho thư viện của bạn (bạn đã viết IDL của riêng mình, phải không? :)).

Nếu bạn không viết tệp IDL hoặc ODL để biên dịch thành một typelib, chúng vẫn tồn tại, trong tệp. Microsoft cung cấp một số công cụ hữu ích: LoadTypeLibEx và giao diện ITypeLib. Với các giao diện này, bạn có thể duyệt thư viện kiểu và nhận tất cả các loại thông tin. Làm cách nào để chúng tôi duyệt qua thư viện?

Tôi chỉ cần xem cách Regasm đã làm điều đó! Sau đó, chúng ta sẽ nhanh chóng tháo rời, và chúng ta thấy rằng regasm được viết bằng C#. Ngay đẹp trơi. Tôi đã bắt đầu một dự án và với một vài câu sử dụng và PInvoke sau, chúng tôi có:

using System.Runtime.InteropServices;   // for struct marshaling 
using System.Runtime.InteropServices.ComTypes; // for the ITypeLib + related types 

// TYPELIBATTR lives in two places: Interop and ComTypes, but the one 
// in Interop is deprecated. 
using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; 

/// <summary> 
/// The registry kind enumeration for LoadTypeLibEx. This must be made 
/// here, since it doesn't exist anywhere else in C# afaik. This is found 
/// here: http://msdn.microsoft.com/en-us/library/ms221159.aspx 
/// </summary> 
enum REGKIND 
{ 
    REGKIND_DEFAULT, 
    REGKIND_REGISTER, 
    REGKIND_NONE 
} 

// and this is how we get the library. 
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)] 
    private static extern void LoadTypeLibEx(string strTypeLibName, REGKIND regKind, out ITypeLib TypeLib); 

Whew! Khi chúng ta có điều này, chúng ta phải điều hướng cấu trúc. Điều này tương tác với các tài nguyên không được quản lý, do đó hãy sẵn sàng để được Marshal nhập nội dung.

ITypeLib lib = null; 
LoadTypeLibEx(Value, REGKIND.REGKIND_NONE, out lib); 
IntPtr libInfoPtr = IntPtr.Zero; 
lib.GetLibAttr(out libInfoPtr); 
TYPELIBATTR libInfo = 
    (TYPELIBATTR) Marshal.PtrToStructure(libInfoPtr, typeof(TYPELIBATTR)); 
int typeCount = lib.GetTypeInfoCount(); 
for (int i = 0; i < typeCount; ++i) 
{ 
    ITypeInfo info; 
    lib.GetTypeInfo(i, out info); 
    IntPtr typeDescrPtr = IntPtr.Zero; 
    info.GetTypeAttr(out typeDescrPtr); 
    TYPELIBATTR type = 
     (TYPELIBATTR)Marshal.PtrToStructure(typeDescrPtr, typeof(TYPELIBATTR)); 
    // get GUID, other info from the specific type 
} 

lib.ReleaseTLibAttr(libInfoPtr); 
libInfoPtr = IntPtr.Zero; 

Whew. Vì vậy, bạn phải viết một số mã để trích xuất thông tin. Sau khi thực hiện, bạn phải điền thông tin đó vào mục Đăng ký, như được chỉ định By Larry Osterman.

Tất nhiên, bạn có thể tránh bước đó bằng cách chỉ cần viết tệp IDL của riêng bạn để bắt đầu.Sự lựa chọn trong đau đớn: nó thuộc vào bạn!

+0

Tôi đọc lại điều này một vài lần, nhưng tôi vô cùng bối rối. Không biết bạn đã đạt được điều gì ở đây. –

+0

Mã không phải là giải pháp. Visual Studio tạo ra tất cả các thông tin bạn phải làm cho mình trong một tập tin IDL như một phần của regasm. Điều này cho phép bạn tìm ra sự thay đổi của bạn. Những gì bạn phải làm là tạo một tập tin IDL. –

+1

Nếu bạn đang cố gắng tìm ra những gì regasm đặt trong tlb, thì tại sao không chỉ mở tệp tlb được tạo bởi regasm với oleview.exe? –

Các vấn đề liên quan