Создание и установка Typelib с помощью WiX

После вопроса о том, что Visual Studio делает для регистрации библиотеки COM, стало ясно, что VS сделал две вещи для регистрации COM:

  1. Зарегистрировали COM-библиотеку
  2. Создает и регистрирует библиотеку типов

Visual Studio, похоже, выполняет эту регистрацию с помощью regasm.exe. Для первой части (прямая регистрация COM) с использованием tallow или heat (WiX 2.0 или WiX 3.0) кажется, что вся базовая регистрационная информация COM получена правильно.

Однако то, что сало / тепло, похоже, не делает, так это настраивает установку библиотеки типов. Для этого можно было бы создать настраиваемое действие с помощью установщика WiX и regasm.exe, но запуск настраиваемых действий не является оптимальной практикой, когда речь идет об установщиках на основе установщика Microsoft.

При дальнейшем исследовании выяснилось, что msi может создавать библиотеку типов при установке. Фактически, WiX, похоже, имеет прямую поддержку для этого! В элемент файла вы можете добавить элемент Typelib. Фактически, здесь на wix есть пример заполнение элемента TypeLib элементами Interface.

Кажется, есть как минимум два обязательных атрибута для элемента интерфейса:

  1. Id
  2. Имя

Ларри Остерман говорит о других частях интерфейса, которые необходимо зарегистрировать. для TypeLib в целом, и эта запись в интерфейсе, кажется, заботится об отдельных частях. Ларри говорит, что нам нужно указать ProxyStubClassId32 как «{00020424-0000-0000-C000-000000000046}», чтобы мы могли легко это добавить.

Куда идти дальше и что заполнять для различных элементов интерфейса, меня озадачило. Я пошел дальше и добавил элемент TypeLib в свой файл wix, и он успешно компилируется. Я немного не понимаю, как настроить элементы интерфейса. Что нам нужно сделать, чтобы правильно заполнить элемент TypeLib, и какие приложения или инструменты я могу использовать для его получения?

Ответ wcoenen ниже выглядит многообещающим ... Я попробую.

Обновление: в качестве ответа я опубликовал свое окончательное решение.


person Robert P    schedule 20.02.2009    source источник
comment
+1, я бы хотел, чтобы все вопросы на этом сайте были написаны так ...   -  person Dirk Vollmar    schedule 20.02.2009
comment
Хех, я стараюсь изо всех сил. :)   -  person Robert P    schedule 20.02.2009


Ответы (3)


Вот способ решения этой проблемы для ленивых: используйте heat из WiX 3.0.

Если у вас есть библиотека типов, созданная автоматически и установленная через regasm, heat может принимать .tlb в качестве аргумента в

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

Он сгенерирует все элементы библиотеки типов и интерфейса, которые вам нужно зарегистрировать. Это не решит проблему необходимости знать их заранее, и не решит проблему изменения идентификаторов GUID при изменении версии сборки (даже если интерфейс не изменится - это единственный раз, когда вы предполагается, что вы измените его), но это поможет вам частично достичь цели.

person Robert P    schedule 06.03.2009
comment
Хотя я не думаю, что существуют какие-либо переменные GUID, если вы объявляете их в своем .NET-коде с помощью атрибута GUID [assembly: Guid (...)] для библиотеки типов и атрибута [Guid (...)] для COM-интерфейсы и классы - person Wim Coenen; 06.03.2009
comment
Что касается руководства по COM, я думаю, вы правы. К сожалению, в библиотеке типов есть разные руководства. : | Интересно, есть ли атрибут для установки этих руководств ... - person Robert P; 06.03.2009

Следующий трюк может помочь собрать любые изменения реестра и превратить их в файл wxs, включая элемент typelib, который вам нужен.

  1. Во-первых, верните реестр в состояние, в котором библиотека типов не была зарегистрирована:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb /u mylib.dll
    
  2. Экспортируйте это чистое состояние реестра в hklm-before.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-before.reg
    
  3. Зарегистрируйте библиотеку типов еще раз:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb mylib.dll
    
  4. Экспортируйте новое состояние реестра в hklm-after.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-after.reg
    
  5. Теперь у нас есть два текстовых файла: hklm-before.reg и hklm-after.reg. Создайте файл diff.reg, который содержит только соответствующие различия между ними. Вы можете легко найти различия с помощью инструмента сравнения. Мне нравится использовать инструмент сравнения, включенный в TortoiseSVN, так как я уже использую его каждый день. (В этом случае WinDiff не работает из-за проблем с кодировкой текста.)

  6. Теперь мы можем преобразовать diff.reg в .wxs, вызвав heat.exe с командой reg. (Требуется wix 3.5 или новее.)

    heat reg diff.reg -out typelib.wxs
    
person Wim Coenen    schedule 20.02.2009
comment
Ой. Неудивительно, что сейчас говорят, что создание WiX - это ручной процесс, ага! - person Robert P; 20.02.2009
comment
Это потому, что WIX - это в основном просто формат XML, который сопоставляется с базой данных установщика Windows (msi / msm / mst / pcp). Например, есть элемент typelib, потому что есть также таблица typelib. Инструмент для сбора урожая heat.exe является полезным дополнением, но для его завершения нужны специалисты. - person Wim Coenen; 20.02.2009
comment
Начиная с WiX 3.10 heat имеет параметр reg, специально предназначенный для сбора файлов реестра. - person Andriy K; 28.11.2016
comment
@AndriyK, спасибо, я обновил ответ, чтобы использовать эту функцию. - person Wim Coenen; 29.11.2016
comment
Только что проверил: есть опция reg, начиная с WIX 3.5 - person Andriy K; 01.12.2016

Похоже, что зарегистрировать библиотеку типов, лучшим способом было бы сгенерировать ваш собственный файл IDL или ODL, который будет содержать ваши GUID. Библиотеки типов, созданные непосредственно из сборки, [i] зависят [/ i] от номеров версий сборки: идентификаторы GUID создаются на основе этой информации, даже если интерфейс не изменился. Visual Studio использует regasm для регистрации и создания библиотеки типов. Под этим он использует RegisterTypeLib, вызов win32. Похоже, что использование элемента typelib делает нечто подобное. Не хорошо.

Тем не мение! Создание библиотеки типов вручную - дело болезненное. Эти GUID можно получить другим способом: выкапывая их из библиотеки типов и создавая элементы самостоятельно.

У Ларри Остермана есть необходимая информация: есть определенные ключи реестра, которые необходимо настроить. Вы можете сделать это с помощью таблицы реестра (а в Wix3 это означает элементы RegistryValue). Хитрость здесь заключается в получении GUID: любой старый GUID не будет работать. Обычно для получения идентификаторов GUID достаточно просто посмотреть в IDL для вашей библиотеки (вы написали свой собственный IDL, верно? :)).

Если вы не написали файл IDL или ODL для компиляции в библиотеку типов, они все еще существуют в файле. Microsoft предоставляет несколько удобных инструментов: LoadTypeLibEx и интерфейс ITypeLib. С помощью этих интерфейсов вы можете просматривать библиотеку типов и получать всевозможную информацию. Как мы просматриваем библиотеку?

Я просто посмотрел, как это сделал Regasm! После быстрого дизассемблирования мы обнаруживаем, что regasm тоже написан на C #. День славы. Я запустил проект, и с несколькими операторами using и PInvoke позже у нас есть:

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

Ух! Как только мы это получим, нам нужно будет перемещаться по структуре. Это взаимодействие с неуправляемыми ресурсами, так что будьте готовы Marshal возиться.

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;

Уф. Итак, вам нужно написать код для извлечения информации. Как только вы это сделаете, вам нужно будет заполнить эту информацию в записях реестра, как указано Автор Ларри Остерман.

Конечно, вы можете избежать этого шага, просто написав для начала свой собственный файл IDL. Выбор в боли: решать вам!

person Robert P    schedule 26.02.2009
comment
Я перечитал это пару раз, но сильно запутался. Понятия не имею, чего ты здесь добился. - person Wim Coenen; 06.03.2009
comment
Код - это не решение. Visual Studio генерирует всю информацию, которую вы должны сделать самостоятельно, в файле IDL как часть regasm. Это позволяет вам выяснить, что регазм сделал от вашего имени. Что вам нужно сделать, так это создать файл IDL. - person Robert P; 06.03.2009
comment
Если вы пытались выяснить, что regasm помещает в tlb, то почему бы просто не открыть файл tlb, сгенерированный regasm, с помощью oleview.exe? - person Wim Coenen; 06.03.2009
comment
Да, вы могли бы сделать это простым способом ... Я хотел инструмент, который мог бы это сделать, и вы действительно не можете быть намного ближе к металлу, чем этот. :) - person Robert P; 06.03.2009
comment
Я с уважением отношусь к тому, что вы сделали свою домашнюю работу и узнали, что на самом деле произошло с регазмом. Даже если я не использую кодовое решение сейчас, полезно знать, как подключить для этого мое собственное программное обеспечение. Спасибо за отличную информацию. - person Jeremy E; 14.08.2009