Подтвердить что ты не робот

Использование ILMerge с log4net вызывает ошибку "недопустимый из-за уровня защиты"

Я создал класс-оболочку для инициализации моих объектов журналирования log4net, чтобы упростить создание настраиваемых свойств в ThreadContext. Это происходит в библиотеке классов, которую я создал вместе со многими другими полезными функциями. Чтобы присоединиться ко всем различным библиотекам, я также добавил цель AfterBuild в ILMerge с помощью переключателя '/internalize'.

Все ссылки на этот метод инициализации внутри библиотеки, на которые нацелен ILMerge, как представляется, работают очень хорошо. Однако, когда я ссылаюсь на эту объединенную библиотеку в других местах. Моя реализация вызывает ошибки уровня защиты. Я попытался добавить различные вещи в необязательный файл exclude (/internalize:excludes.txt), но это не работает.

Пример excludes.txt:

log4net.Config
log4net.ThreadContext
log4net.LogManager

У кого-нибудь еще была эта проблема?

[EDIT]:

Вот код:

 [assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Logging
{
    public static class Log4NetThreadContext
    {
        public static ILog Initialize(Type declaringType)
        {
            // Read from configuration
            XmlConfigurator.Configure();

            // Set Properties
            ThreadContext.Properties["ID"] = ...
                ...
                ...
                ...

            if(System.Diagnostics.Debugger.IsAttached)
            {
                // Special debugging logger
                return LogManager.GetLogger("DEBUG_MODE");
            }
            else
            {
                // Root logger
                return LogManager.GetLogger(declaringType);
            }
        }
    }
}

Я использую этот код так.

private static readonly Type declaringType = 
    MethodBase.GetCurrentMethod().DeclaringType;
private static readonly ILog log =
    Log4NetThreadContext.Initialize(declaringType);
...
log.Info("Something useful");

[EDIT]:

Это моя цель AfterBuild

<Target Name="AfterBuild">
<CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
  <Output ItemName="AssembliesToMerge" TaskParameter="Include" />
</CreateItem>
<Message Text="MERGING: @(AssembliesToMerge->'%(Filename)')" Importance="High" />
<Exec Command="&quot;$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe&quot; /targetplatform:v2 /log /internalize:&quot;ilmerge.excludes.txt&quot; /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
<Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />

Есть ли лучший способ вообще отладить проблемы с уровнем защиты?

Log4NetThreadContext.Initialize(System.Type)' is inaccessible due to its protection level
4b9b3361

Ответ 1

В конечном счете, самое простое - полностью исключить log4net из процесса ilmerge и поддерживать его как зависимую сборку.

Итак, после многих пыток здесь "не столь очевидное" решение.

В любом случае исключение не требовалось, реальный ответ заключается в использовании переключателя /lib:[path] в ilmerge.

Я обновил цель AfterBuild, чтобы удалить исключения из переключателя /internalize. Затем я добавил коммутатор /lib, чтобы передать местоположение dll log4net в качестве зависимой ссылки. Это выглядит так:

<Target Name="AfterBuild">
  <CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
    <Output ItemName="AssembliesToMerge" TaskParameter="Include" />
  </CreateItem>
  <Message Text="MERGING: @(AssembliesToMerge->'%(Filename)')" Importance="High" />
  <Exec Command="&quot;$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe&quot; /lib:..\packages\log4net.2.0.0\lib\net35-full\ /targetplatform:v2 /log /internalize /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
  <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>

Кроме того, я добавил еще одну цель, чтобы ограничить список сборок, включенных в слияние, добавив уникальный элемент <ILMerge /> к ссылкам, расположенным в моем файле .csproj

<Target Name="AfterResolveReferences">
  <Message Text="Filtering out ILMerge assemblies from ReferenceCopyLocalPaths..." Importance="High" />
  <ItemGroup>
    <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.ILMerge)'=='false'" />
  </ItemGroup>
</Target>

Таким образом, ссылочные элементы были перечислены следующим образом:

...
<Reference Include="Ionic.Zip">
  <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
  <ILMerge>True</ILMerge>
</Reference>
<Reference Include="log4net">
  <HintPath>..\packages\log4net.2.0.0\lib\net35-full\log4net.dll</HintPath>
  <ILMerge>False</ILMerge>
...

Вероятно, есть более эффективная (программная) альтернатива для явного добавления значений ILMerge = False в переключатель /lib, но в моем случае этого достаточно из-за наличия только одного исключенного элемента. В противном случае вам может потребоваться добавить дополнительные пути вручную.

Кредит для метода AfterResolveReferences, который я перечислил, относится к http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx

Надеюсь, это поможет кому-то!   

Ответ 2

Это обычно происходит со мной, когда я запускаю код из удаленного места..NET имеет проблемы с правами доступа при доступе к файлу конфигурации из удаленного места. Например, настройка репозитория кода в общем сетевом ресурсе.

Мне удалось преодолеть все это, переместив мой код на локальный жесткий диск (поскольку у меня нет прав администратора для повышения безопасности сетевого ресурса до "Надежный" и т.д.).

(Обратите внимание, что это прежде всего проблема с версиями Visual Studio до 2005 года. Я думаю, что это было исправлено в 2008 году, поэтому это может не повлиять на вас. Однако вы не скажете, какую версию вы используете.)