Каков 'корректный' способ регистрироваться/устанавливать блок к GAC?

Значение RTNLGRP_NEIGH будет равно 3. Вы можете легко проверить это с помощью следующей программы.

#include <stdio.h>

/* RTnetlink multicast groups */
enum rtnetlink_groups {
        RTNLGRP_NONE,
#define RTNLGRP_NONE            RTNLGRP_NONE
        RTNLGRP_LINK,
#define RTNLGRP_LINK            RTNLGRP_LINK
        RTNLGRP_NOTIFY,
#define RTNLGRP_NOTIFY          RTNLGRP_NOTIFY
        RTNLGRP_NEIGH,
#define RTNLGRP_NEIGH           RTNLGRP_NEIGH
        RTNLGRP_TC,
#define RTNLGRP_TC              RTNLGRP_TC
        RTNLGRP_IPV4_IFADDR,
#define RTNLGRP_IPV4_IFADDR     RTNLGRP_IPV4_IFADDR
        /* ... */
#define RTNLGRP_PHONET_IFADDR   RTNLGRP_PHONET_IFADDR
        RTNLGRP_PHONET_ROUTE,
#define RTNLGRP_PHONET_ROUTE    RTNLGRP_PHONET_ROUTE
        __RTNLGRP_MAX
};
#define RTNLGRP_MAX     (__RTNLGRP_MAX - 1)

int
main()
{
  printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}

Он выводит это:

RTNLGRP_NEIGH = 3

Поскольку каждый макрос #define d для своего имени, RTNLGRP_NEIGH в main будет заменен на RTNLGRP_NEIGH. Но так как расширение не является рекурсивным, оно останавливается в этой точке, и программа использует константу enum, которая является четвертой и поэтому имеет значение 3.

Если вы не знаете, что препроцессор, вы всегда можете скомпилировать с помощью переключателя -E и посмотреть на предварительно обработанный вывод. Компиляция приведенного выше примера с gcc -E дает (не отображая 840 строк стандартных заголовков библиотеки #include d)

# 4 "main.c"
enum rtnetlink_groups {
        RTNLGRP_NONE,

        RTNLGRP_LINK,

        RTNLGRP_NOTIFY,

        RTNLGRP_NEIGH,

        RTNLGRP_TC,

        RTNLGRP_IPV4_IFADDR,



        RTNLGRP_PHONET_ROUTE,

        __RTNLGRP_MAX
};


int
main()
{
  printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}

, который, надеюсь, гораздо менее запутанным.

#define s, смешанные с определением enum, не влияют на определение enum. Не имеет значения, где находятся #define s. Они могли (и, вероятно, должны были) быть размещены до или после определения.

/* RTnetlink multicast groups */
enum rtnetlink_groups {
        RTNLGRP_NONE,
        RTNLGRP_LINK,
        RTNLGRP_NOTIFY,
        RTNLGRP_NEIGH,
        RTNLGRP_TC,
        RTNLGRP_IPV4_IFADDR,
        /* ... */
        RTNLGRP_PHONET_ROUTE,
        __RTNLGRP_MAX
};

#define RTNLGRP_NONE            RTNLGRP_NONE
#define RTNLGRP_LINK            RTNLGRP_LINK
#define RTNLGRP_NOTIFY          RTNLGRP_NOTIFY
#define RTNLGRP_NEIGH           RTNLGRP_NEIGH
#define RTNLGRP_TC              RTNLGRP_TC
#define RTNLGRP_IPV4_IFADDR     RTNLGRP_IPV4_IFADDR
#define RTNLGRP_PHONET_IFADDR   RTNLGRP_PHONET_IFADDR
/* ... */
#define RTNLGRP_PHONET_ROUTE    RTNLGRP_PHONET_ROUTE
#define RTNLGRP_MAX     (__RTNLGRP_MAX - 1)

Причина, по которой они написали этот прошитый код, вероятно, что они хотели реорганизовать старый код с помощью

#define RTNLGRP_NONE          0
#define RTNLGRP_LINK          1
#define RTNLGRP_NOTIFY        2
#define RTNLGRP_NEIGH         3
#define RTNLGRP_TC            4
#define RTNLGRP_IPV4_IFADDR   5
/* ... */

использовать вместо enum. Но поскольку существующий код может полагаться на то, что идентификаторы являются макросами (например, тестирование #ifdef RTNLGRP_NEIGH), они хотели бы предоставить макросы с одинаковым значением. Обратите внимание, что этот подход является ошибочным, поскольку препроцессор не знает значения константы, поэтому вы не можете делать такие вещи, как #if RTNLGRP_NEIGH >= 3, которые вы могли бы, RTNLGRP_NEIGH были #define d до 3 буквально. Таким образом, по сути, их подход сочетает в себе недостатки использования макросов (загрязнение именных пространств) с использованием методов enum s (недоступно во время предварительной обработки).

Возможно, более полезный образец I прежде были #define константы действительных целых чисел.

enum rtnetlink_groups {
        RTNLGRP_NONE
#define RTNLGRP_NONE            0
        = RTNLGRP_NONE,
        RTNLGRP_LINK
#define RTNLGRP_LINK            1
        = RTNLGRP_LINK,
        RTNLGRP_NOTIFY
#define RTNLGRP_NOTIFY          2
        = RTNLGRP_NOTIFY,
        RTNLGRP_NEIGH
#define RTNLGRP_NEIGH           3
        = RTNLGRP_NEIGH,
        RTNLGRP_TC
#define RTNLGRP_TC              4
        = RTNLGRP_TC,
        RTNLGRP_IPV4_IFADDR
#define RTNLGRP_IPV4_IFADDR     5
        = RTNLGRP_IPV4_IFADDR,
        /* ... */
};

, которые будут предварительно обработаны следующим.

enum rtnetlink_groups {
        RTNLGRP_NONE

        = 0,
        RTNLGRP_LINK

        = 1,
        RTNLGRP_NOTIFY

        = 2,
        RTNLGRP_NEIGH

        = 3,
        RTNLGRP_TC

        = 4,
        RTNLGRP_IPV4_IFADDR

        = 5,

};

Обратите внимание, что здесь что #define s смешиваются с определением enum, иначе мы получили бы недопустимый код, например 3 = 3,, а не желаемый RTNLGRP_NEIGH = 3.

О, и, пожалуйста, не делайте используйте __RTNLGRP_MAX как идентификатор. Имена, содержащие два смежных подчеркивания или начинающиеся с символа подчеркивания, за которым следует буква верхнего регистра, зарезервированы по стандарту C. Использование их в вашем собственном коде приводит к неопределенному поведению.

14
задан Robert P 14 January 2009 в 17:36
поделиться

8 ответов

С Wix я сделал бы что-то вроде этого:


<DirectoryRef Id="MyDirectory" >
    <Component Id="MyComponent" Guid="PUT-GUID-HERE" DiskId="1">
        <File Id="MyAssembly" Name="MyAssembly.dll" Assembly=".net" KeyPath="yes" Source="MyAssembly.dll" />
    </Component>
</DirectoryRef>

, Когда Вы используете блок атрибута = ". сеть" для файла в WiX, это создаст записи в таблице MsiAssembly и MsiAssemblyName для этого компонента и отметит его как компонент GAC.

17
ответ дан 1 December 2019 в 14:12
поделиться

http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx

похоже, что gacutil нужно избежать; это не распространяемое приложение. Вместо этого 'надлежащий' способ установить их, кажется, использует MSI, один способ быть WIX, как отправлено CheGueVerra или другим сценарием.

2
ответ дан 1 December 2019 в 14:12
поделиться

Разве у Вашего производителя установщика нет способа установить блок в GAC? Самостоятельно, я сказал бы GACUTIL:

http://msdn.microsoft.com/en-us/library/ex0ss12c (По сравнению с 80) .aspx

0
ответ дан 1 December 2019 в 14:12
поделиться

Если Вы не хотите обрабатывать gacutil, наполняют себя, можно всегда создавать проект установки в Visual Studio.

, Но я придерживался бы gacutil сам.

0
ответ дан 1 December 2019 в 14:12
поделиться

Используйте System.EnterpriseServices.Internal.Publish GacInstall метод.

Преимущества: Кажется, внутренний инструмент. Вероятно, делает весь правильный материал.

Недостатки: Как часть установщика, необходимо было бы все еще сделать и запустить приложение, которое называет это (если установщик, который Вы делаете, не является пользовательским приложением, которое делает это так или иначе).

2
ответ дан 1 December 2019 в 14:12
поделиться

Лучший способ состоит в том, чтобы использовать gacutil -i Library.dll.

единственная проблема с gacutil состоит в том, что это не находится в ПУТИ по умолчанию системы. Это находится однако в фиксированном месте относительно каталога окон для данной версии.Net Framework. Таким образом, можно использовать следующую командную строку для выполнения его отовсюду:

%SystemRoot%\Microsoft.Net\Framework\v1.1.4322\gacutil -i

пз: просто копирование Вашего блока в c:\windows\assembly не будет работать. Проводник только показывает упрощенное представление папки, которая содержит на самом деле много различных папок для различных видов блоков. Выполнение копии в нем из установщика не инициирует все операции, сделанные проводником на перетаскивании. (записанный здесь, потому что у меня нет достаточной репутации все же для комментария других сообщений).

-1
ответ дан 1 December 2019 в 14:12
поделиться

используйте gacutil.

Преимущества: кажется, всегда работает. Недостатки:

  • должен упаковать дополнительный исполняемый файл с Вашим установщиком.
  • Как утилита разработки, кажется, имеет дополнительные побочные эффекты (как принуждение установки независимо от того, что).
  • не Должен быть включен ни в какой распространяемый файл, данный клиентам.
0
ответ дан 1 December 2019 в 14:12
поделиться

скопируйте непосредственно в %WINDIR %\Assembly.

Преимущество: Простой.

Недостаток: AFAIK, %WINDIR %\Assembly всего происходит , чтобы быть, где это прямо сейчас, и это - местоположение, подвержен изменениям. Это заставило бы его прервать будущие версии окон или если поведение той папки chaneges. Это, вероятно, не правильный путь.

Экстремальный Недостаток: Как сказано madmath:

просто копирование Вашего блока в c:\windows\assembly не будет работать. Проводник только показывает упрощенное представление папки, которая содержит на самом деле много различных папок для различных видов блоков. Выполнение копии в нем из установщика не инициирует все операции, сделанные проводником на перетаскивании. (записанный здесь, потому что у меня нет достаточной репутации все же для комментария других сообщений).
-5
ответ дан 1 December 2019 в 14:12
поделиться
Другие вопросы по тегам:

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