Поколение Typelib и установка с WiX

Если вы прочитали документацию , то есть javadoc из ListIterator.add() , вы увидите:

Вставляет указанный элемент в список (необязательно) операция). Элемент вставляется непосредственно перед элементом, который будет возвращен next(), если таковой имеется, и после элемента, который будет возвращен previous(), если таковой имеется. (Если список не содержит элементов, новый элемент становится единственным элементом в списке.) Новый элемент вставляется перед неявным курсором: последующий вызов next не будет затронут, а последующий вызов [ 116] вернет новый элемент . (Этот вызов увеличивается на единицу значения, которое будет возвращено вызовом к nextIndex или previousIndex.)

blockquote>

Таким образом, чередующиеся вызовы к previous() и add() сохранят вставку значения в той же позиции в списке, и, следовательно, никогда не закончится (пока не закончится память).

Чтобы показать, что происходит, попробуйте следующий код:

public static void main(String[] args) {
    List list = new ArrayList<>(Arrays.asList(10, 20, 30, 40));
    ListIterator listIter = list.listIterator(list.size());
    print(list, listIter); // Iterator is at end (after 40)

    System.out.println("previous(): " + listIter.previous()); // prints: 40
    print(list, listIter); // Iterator is between 30 and 40

    for (int i = 39; i >= 31; i--) {
        listIter.add(i);   System.out.printf("add(i)%n", i);
        print(list, listIter);

        System.out.println("previous(): " + listIter.previous());
        print(list, listIter);
    }
}
static void print(List list, ListIterator listIter) {
    for (Integer i : list)
        System.out.printf("%5d", i);
    System.out.printf("%n%" + (listIter.nextIndex() * 5 + 2) + "s%n", "^");
}

Вывод

   10   20   30   40
                     ^
previous(): 40
   10   20   30   40
                ^
add(i)
   10   20   30   39   40
                     ^
previous(): 39
   10   20   30   39   40
                ^
add(i)
   10   20   30   38   39   40
                     ^
previous(): 38
   10   20   30   38   39   40
                ^
add(i)
   10   20   30   37   38   39   40
                     ^
previous(): 37
   10   20   30   37   38   39   40
                ^
add(i)
   10   20   30   36   37   38   39   40
                     ^
previous(): 36
   10   20   30   36   37   38   39   40
                ^
add(i)
   10   20   30   35   36   37   38   39   40
                     ^
previous(): 35
   10   20   30   35   36   37   38   39   40
                ^
add(i)
   10   20   30   34   35   36   37   38   39   40
                     ^
previous(): 34
   10   20   30   34   35   36   37   38   39   40
                ^
add(i)
   10   20   30   33   34   35   36   37   38   39   40
                     ^
previous(): 33
   10   20   30   33   34   35   36   37   38   39   40
                ^
add(i)
   10   20   30   32   33   34   35   36   37   38   39   40
                     ^
previous(): 32
   10   20   30   32   33   34   35   36   37   38   39   40
                ^
add(i)
   10   20   30   31   32   33   34   35   36   37   38   39   40
                     ^
previous(): 31
   10   20   30   31   32   33   34   35   36   37   38   39   40
                ^

22
задан Community 23 May 2017 в 11:45
поделиться

3 ответа

Вот способ ленивого человека решить эту проблему: Используйте heat от WiX 3.0.

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

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

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

16
ответ дан 29 November 2019 в 05:26
поделиться

Следующий прием может помочь со сбором урожая любых изменений реестра и превращением их в 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, который только содержит соответствующие различия между ними. Можно найти различия легко с diffing инструментом. Мне нравится использовать различный инструмент, включенный в TortoiseSVN, так как я уже использую это каждый день. (WinDiff, кажется, не работает хорошо в этом случае из-за кодирующих текст проблем.)

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

    heat reg diff.reg -out typelib.wxs
    
8
ответ дан 29 November 2019 в 05:26
поделиться

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

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

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

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

я просто смотрел на то, как Regasm сделал это! Быстрое демонтирует позже, и мы находим, что regasm записан в C# также. Славный день. Я запустил проект, и с несколькими операторами использования и 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;

Ух. Так, необходимо написать некоторый код для извлечения информации. Как только Вы делаете, необходимо заполнить ту информацию в Записи Registy, как определено Larry Osterman .

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

3
ответ дан 29 November 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: