无法从app.config运行时元素正确加载UseLegacyPathHandling [英] UseLegacyPathHandling is not loaded properly from app.config runtime element

查看:201
本文介绍了无法从app.config运行时元素正确加载UseLegacyPathHandling的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的应用程序中使用新的长途支持.为了使用它,而不必强迫客户端在其计算机上插入最新的.net 4.6.2版本,应该只将那些元素添加到他的app.config中(有关更多信息,请参见链接

I'm trying to use the new long path support at my app. In order to use it, without forcing clients to have the newest .net 4.6.2 version instelled on their machines, one should only add those elements to his app.config (see the link for more info https://blogs.msdn.microsoft.com/dotnet/2016/08/02/announcing-net-framework-4-6-2/) :

<startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
</startup>
<runtime>
    <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
</runtime>

当我在执行项目中使用它时,它可以完美运行.问题出在我的测试项目(使用Nunit)中.我已经将app.config添加到测试项目中,就像将其添加到执行项目中一样.

When I use it in my execution project it works perfectly. The problem is in my testing projects (which use Nunit). I've added app.config to my test project in the same way I've added it to the execution project.

使用ConfigurationManager类,我设法确保确实加载了应用程序配置(简而言之:使用我可以在单元测试中检索到的应用程序设置).

Using the ConfigurationManager class I've managed to ensure that app config indeed loaded (in short: using an app setting which i was able to retrieve in a unit test).

使用ConfigurationManager.GetSection("runtime"),我什至设法确保已正确加载运行时元素(_rawXml值与app.config中的值相同).

Using ConfigurationManager.GetSection("runtime"), I even managed to ensure the runtime element has been loaded properly (_rawXml value is the same as in app.config).

但是(!)由于某种原因,应用程序配置运行时元素不会影响UseLegacyPathHandling变量,因此,我所有使用长路径的调用都失败了.

But (!) for some reason the app config runtime element is not influence the UseLegacyPathHandling variable and therefore all of my calls with long path fail.

我想问题出在某种程度上与测试项目成为使用Nunit引擎(执行入口点)加载的dll的事实有关.

I guess the problem is somehow relates to the fact that testing projects become dll's that are loaded using the Nunit engine, which is the execution entry point.

在另一个项目中,我正面临着完全相同的问题,这是Office Word应用程序加载的dll.我认为问题在两种情况下都是相同的,并且源于这些项目并非旨在成为执行切入点的事实.

I'm facing the exact same problem in another project I have, which is a dll loaded by Office Word application. I believe the problem is the same in both cases and derived from the fact that the projects are not meant to be an execution entry point.

重要的是要了解我无法访问其自身(Word Office或Nunit)的执行,因此我无法自行配置它们.

It's important to understand that I've no access to the executions their self (Word Office or Nunit) and therefore I can't configure them myself.

是否可以通过某种方式使AppContextSwitchOverrides从头开始动态加载?其他想法将是最受欢迎的.谢谢.

Is there an option to somehow make the AppContextSwitchOverrides get loaded from scratch dynamically? Other ideas will be most welcome. Thanks.

推荐答案

我遇到了同样的问题,并且注意到同样缺少该特定设置的加载.

I've been having the same issue, and have noted the same lack of loading of that particular setting.

到目前为止,我所得到的是设置的缓存至少部分归咎于此. 如果您查看了它的实现方式,则禁用缓存不会对以后的值调用产生任何影响(即,如果启用了缓存并且在此期间访问了某些内容,则将始终对其进行缓存).

So far, what I've got is that the caching of settings is at least partly to blame. If you check out how it's implemented, disabling the cache has no effect on future calls to values (i.e. if caching is enabled and something is accessed during that time, then it will always be cached).

https://referencesource.microsoft.com/#mscorlib/system/AppContext/AppContext.cs

对于大多数设置来说,这似乎不是问题,但是由于某些原因,在我第一次进入代码时,UseLegacyPathHandling和BlockLongPaths设置已被缓存.

This doesn't seem to be an issue for most of the settings, but for some reason the UseLegacyPathHandling and BlockLongPaths settings are getting cached by the time I can first step into the code.

目前,我没有很好的答案,但是如果您在过渡期间需要某些帮助,我会为您提供一个非常可疑的临时解决方案.使用反射,可以在装配初始化中固定设置.它按名称写入私有变量,并使用0的特定值来使高速缓存无效,因此这是一个非常微妙的修复,不适用于长期解决方案.

At this time, I don't have a good answer, but if you need something in the interim, I've got a highly suspect temporary fix for you. Using reflection, you can fix the setting in the assembly init. It writes to private variables by name, and uses the specific value of 0 to invalidate the cache, so it's a very delicate fix and not appropriate for a long term solution.

也就是说,如果您暂时需要一些可以正常使用"的东西,则可以检查设置,并根据需要应用该技巧. 这是一个简单的示例代码.这将是您在测试课程中需要的方法.

That being said, if you need something that 'just works' for the time being, you can check the settings, and apply the hack as needed. Here's a simple example code. This would be a method you'll need in your test class.

    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        // Check to see if we're using legacy paths
        bool stillUsingLegacyPaths;
        if (AppContext.TryGetSwitch("Switch.System.IO.UseLegacyPathHandling", out stillUsingLegacyPaths) && stillUsingLegacyPaths)
        {
            // Here's where we trash the private cached field to get this to ACTUALLY work.
            var switchType = Type.GetType("System.AppContextSwitches"); // <- internal class, bad idea.
            if (switchType != null)
            {
                AppContext.SetSwitch("Switch.System.IO.UseLegacyPathHandling", false);   // <- Should disable legacy path handling

                // Get the private field that is used for caching the path handling value (bad idea).
                var legacyField = switchType.GetField("_useLegacyPathHandling", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
                legacyField?.SetValue(null, (Int32)0); // <- caching uses 0 to indicate no value, -1 for false, 1 for true.

                // Ensure the value is set.  This changes the backing field, but we're stuck with the cached value for now.
                AppContext.TryGetSwitch("Switch.System.IO.UseLegacyPathHandling", out stillUsingLegacyPaths);
                TestAssert.False(stillUsingLegacyPaths, "Testing will fail if we are using legacy path handling.");
            }
        }
    }

这篇关于无法从app.config运行时元素正确加载UseLegacyPathHandling的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆