使用ILMerge和log4net会导致“由于保护级别”无法访问.错误

本文关键字:保护 错误 访问 log4net ILMerge 于保护 使用 | 更新日期: 2023-09-27 17:54:14

我为log4net日志对象的初始化创建了一个包装器类,以便更容易在ThreadContext中建立自定义属性。这发生在我与许多其他有用的函数一起建立的类库中。为了加入所有不同的库,我还使用'/internalize'开关添加了一个AfterBuild目标到ILMerge。

在ILMerge所针对的库中对这个初始化方法的所有引用似乎都工作得很好。但是,当我在其他地方引用这个合并库时。我的实现抛出保护级别错误。我试过添加各种东西到可选的排除(/internalize:exclude .txt)文件,但这似乎不起作用。

excludes.txt例子:

log4net.Config
log4net.ThreadContext
log4net.LogManager

还有其他人有这个问题吗?

[编辑]:

代码如下:

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

[编辑]:

这是我的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

使用ILMerge和log4net会导致“由于保护级别”无法访问.错误

最终,最简单的方法是将log4net完全排除在ilmerge过程之外,并将其作为一个独立的程序集进行维护。

所以,经过一番折磨,这里有一个"不太明显"的解决方案…

毕竟不需要排除,真正的答案是在ilmerge中使用/lib:[path]开关。

我更新了AfterBuild目标以从/internalize开关中删除排除项。接下来,我添加了/lib开关,以传递log4net dll的位置作为依赖引用。它看起来像这样:

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

此外,我添加了另一个目标,通过向位于我的.csproj文件

中的引用添加唯一的<ILMerge />元素来限制合并中包含的程序集列表
<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

希望这能帮助到一些人!

这通常发生在我从远程位置运行代码时,. net在从远程位置访问配置文件时有权限问题。例如,在网络共享上设置代码存储库。

我只能通过将我的代码移动到本地硬盘来克服它(因为我没有管理员权限将网络共享的安全性提升到"可信"等)。

(注意,这主要是2005年之前版本的Visual Studio的问题。我想这个问题在2008年就已经解决了,所以它可能不会影响到你。但是你不能说你使用的是哪个版本

相关文章: