6

.NET 2 から .NET 4 に変換しようとしているソリューションがあります。このソリューションには複数のプロジェクトがあり、その一部は C# にあり、一部は VB にあります。それらのほとんどは、XML の作成と解析に system.xml を使用します。

すべてのプロジェクトを .NET 4 に再ターゲットし、コンパイルしました。ただし、実行しようとすると、ほとんどすぐに System.FieldAccessException が発生し、「クラス ライブラリ内のフィールドのアクセス レベルが変更された場合は、そのライブラリを参照するアセンブリを再コンパイルしてください」と表示されます。この前にソリューション全体を再コンパイルしました(その後、再試行しましたが、変更はありませんでした)。

次に、Assembly Binding Log Viewer を使用して、バインドが失敗していないかどうかを確認しました。これは、プロジェクト内の別の dll を参照したときに発生していたためです。そして確かに、そこには失敗があります。これらは 2 つの異なる VB プロジェクトにあり、どちらも次のようになります。


The operation failed. 
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll 
Running under executable  <path to my exe>
--- A detailed error log follows. 

=== Pre-bind state information === 
LOG: DisplayName = <projname>.XmlSerializers, Version=2013.20.0.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL  (Fully-specified) 
LOG: Appbase = <projectpath> 
LOG: Initial PrivatePath = NULL 
LOG: Dynamic Base = NULL 
LOG: Cache Base = NULL 
LOG: AppName = <projname>.vshost.exe Calling assembly : System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
=== LOG: This bind starts in default load context. 
LOG: Using application configuration file: <project path\config file> 
LOG: Using host configuration file:  
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. 
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.DLL. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers/CMG.XmlSerializers.DLL. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.EXE. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.EXE. 
LOG: All probing URLs attempted and failed.

案の定、私の obj フォルダーにはそのようなファイルはありません。しかし、以前にもありませんでしたし、うまくいきました。(注: これらのバインド エラーは、XML を使用する 2 つの VB プロジェクトでのみ表示され、C# では表示されません。) system.xml への参照を削除して再度追加し、ソリューションをクリーンアップして再ビルドしましたが、まだ何もありません。

確認したところ、system.xml v4 が GAC にあり、公開鍵はここで探しているものと同じです。[ビルド] タブの [シリアル化アセンブリの生成] というプロジェクト オプションへの参照を見てきました。VB プロジェクトでは、[コンパイル] > [詳細オプション] の下にあります。オートに設定しました。電源を入れて再構築してみましたが、変化はありません。次にどこを見ればいいのかわかりません。これは、私にとってまったく新しい領域でした。では、このファイルはどこから来ているのでしょうか?なぜそこにないのでしょうか?なぜそれなしで v2 で機能したのでしょうか? それとも、このすべての xml はおせっかいで、元の問題とは何の関係もないのでしょうか? 私はそれを恐れ始めていますが、どちらの方法でもまだ確信が持てません。ガイダンスをいただければ幸いです。

ETA : VS の外部でこれを実行すると、エラー ログにクラッシュがイベント 1000 として表示され、"Faulting module name: kernelbase.dll" が表示されます。これまでに行った検索では、64 ビット OS で実行されている 32 ビット アプリに問題があることが示されていますが、すべてを Any CPU としてコンパイルするように設定しています。.NET 2 バージョンを実行すると、問題なく動作するにもかかわらず、同じバインド エラーが表示されることが判明しました。私は、XML のことはニシンだとますます考え始めています。

さらなる ETA : XML のことは確かにニシンでした。以下の回答としてソリューションを追加しました。

4

1 に答える 1

2

結局のところ、それはセキュリティでした。http://msdn.microsoft.com/en-us/library/stfy7tfc.aspxに従って:

メンバーが SecurityCriticalAttribute を持っている場合、SecurityCriticalAttribute を持っている型に属している場合、またはセキュリティ クリティカルなアセンブリにある場合、メンバーはセキュリティ クリティカルです。.NET Framework 4 以降、セキュリティ クリティカルなメンバーにアクセスするための規則は次のとおりです。

透過的なコードは、コードが完全に信頼されている場合でも、リフレクションを使用してセキュリティ クリティカルなメンバーにアクセスすることはできません。MethodAccessException、FieldAccessException、または TypeAccessException がスローされます。

部分信頼で実行されているコードは、透過的として扱われます。

さらに読んでみると、.NET 4 のこの変更により、実際にはこれらのルールに 2 つのレベルが導入されていることがわかりました。レベル 2 はこれらの新しいルールであり、レベル 1 は下位互換性のために .NET 2 ルールです。以下を追加して、レベル 1 ルールを使用するようにアクセスできないアセンブリを設定しました。

<Assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)> 

AssemblyInfo.vb ファイルに (および system.security を参照として追加します)。すべてが正常に動作するようになりました。明らかに、レベル 2 ルールを使用するように変更することが理想ですが、それはまだ先の話です。これにより、少なくとも当面の問題が修正されるだけでなく、問題の内容が正確にわかります。みんな、ありがとう!

于 2013-08-16T23:02:16.493 に答える