2016-11-21 9 views
1

私のアプリケーションで新しいロングパスサポートを使用しようとしています。 (詳細https://blogs.msdn.microsoft.com/dotnet/2016/08/02/announcing-net-framework-4-6-2/のリンクを参照)、それを使用するためには、自分のマシン上でinstelled最新の.NET 4.6.2バージョンを持っているようにクライアントを強制することなく、1が唯一の彼はapp.configにそれらの要素を追加する必要がありますUseLegacyPathHandlingがapp.configランタイム要素から正しくロードされていません

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

実行プロジェクトで使用すると完全に動作します。問題は私のテストプロジェクト(Nunitを使用している)です。実行プロジェクトに追加したのと同じ方法でapp.configをテストプロジェクトに追加しました。

ConfigurationManagerクラスを使用すると、私はアプリの設定が実際に読み込まれるように管理しています(短く:ユニットテストで取得できたアプリ設定を使用して)。

ConfigurationManager.GetSection(「ランタイム」)を使用して、ランタイム要素が正しくロードされていることを管理することさえできました(_rawXmlの値はapp.configと同じです)。

しかし、何らかの理由でapp configのランタイム要素がUseLegacyPathHandling変数に影響を及ぼさないため、長いパスでのすべての呼び出しが失敗します。

この問題は、テストプロジェクトが、実行エントリポイントであるNunitエンジンを使用してロードされたDLLになるという事実と関係していると思います。

私はOffice Wordアプリケーションによって読み込まれたDLLである別のプロジェクトでまったく同じ問題に直面しています。両方のケースで問題は同じだと思うし、プロジェクトが実行のエントリーポイントではないという事実から派生していると思う。

私は自分の実行形式(Word OfficeまたはNunit)にアクセスできないため、自分で設定することはできません。

どうやらAppContextSwitchOverridesをゼロから動的にロードさせるオプションがありますか?その他のアイデアは大歓迎です。ありがとう。

答えて

2

私は同じ問題を抱えていて、その特定の設定の読み込みと同じ不足があることに気付きました。

これまでのところ、設定のキャッシングは少なくとも部分的には責任があるということです。 キャッシュの実装方法をチェックすると、キャッシュを無効にしても将来の値の呼び出しに影響しません(キャッシュが有効になっていて、その間に何かにアクセスすると、キャッシュされます)。

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

これは設定のほとんどのための問題ではないようですが、いくつかの理由でUseLegacyPathHandlingとBlockLongPaths設定は、私が最初のコードにステップすることができ、時間によってキャッシュされてきています。

現時点では、私には良い答えはありませんが、一時的に何かが必要な場合は、疑いの余地のない一時的な修正があります。リフレクションを使用すると、アセンブリのinitで設定を修正できます。それはプライベート変数に名前で書き出し、0の特定の値を使用してキャッシュを無効にするので、非常に繊細な修正であり、長期的な解決策としては適切ではありません。

当然のことながら、「今すぐ動作する」ものが必要な場合は、設定を確認し、必要に応じてハックを適用することができます。 ここに簡単なコード例があります。これはテストクラスで必要となるメソッドです。

[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."); 
      } 
     } 
    } 
+0

また、app.configに使用するスタイルシートをチェックアウトすると、rutimeセクションにはprocessContents = "skip"プロパティがあります。私はこれがこのセクションの処理を全く妨げているのだろうかと思います。 –

+0

詳しい調査によれば、より多くの問題があることがわかります。 AppContextDefaultsはユーザーコードが実行される前に設定されているため、設定を正しく読み込むことができない場合は、反映されずにこれらのオプションを再構成する方法はありません。また、テストエンジンは、アセンブリ用に指定されたものではなく、テストエンジン用の.configファイル(ユニットテストセッションウィンドウのvstest.executionengine.x86.exe.Config)を使用することも明らかです。これは、ランタイムセクションが無視される理由を説明します(既にロードされているので不要です)。悲劇的に、私はこれの回避策をまだ見つけていない。 –

+0

また、私の最後のコメントを読んで、なぜ私が実行時に設定を読み込んでいるのではないか疑問に思うなら、AppContextSwitchesでキャッシングがどのように実装されているかチェックしてください(一度設定すれば設定で.NET4.6.1以前)。したがって、AppContextDefaultValues.Defaults.csに5つの既定値がデフォルト設定されている場合、これらの変更に対してテストを書くことはできません。 –

関連する問題