12

WinForms、汎用ライブラリ、Web アプリを含む VS 2008 ソリューションを VS 2010 にアップグレードしましたが、すべてのプロジェクトは依然として .NET 3.5 SP 1 をターゲットにしています。この手法を使用して、汎用ライブラリの XmlSerializers を生成しています。WinForms アプリは問題なく動作します。同じ XmlSerializers を参照するこれらのライブラリを使用して Web アプリを実行しようとすると、次のメッセージがスローされます。

「/WebSubscribers」アプリケーションでサーバー エラーが発生しました。ファイルまたはアセンブリ 'Ceoimage.Basecamp.XmlSerializers' またはその依存関係の 1 つを読み込めませんでした。このアセンブリは、現在読み込まれているランタイムよりも新しいランタイムによってビルドされているため、読み込むことができません。説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。

例外の詳細: System.BadImageFormatException: ファイルまたはアセンブリ 'Ceoimage.Basecamp.XmlSerializers' またはその依存関係の 1 つを読み込めませんでした。このアセンブリは、現在読み込まれているランタイムよりも新しいランタイムによってビルドされているため、読み込むことができません。

.NET Reflectorを使用して XmlSerializer の参照を調べたところ、の 2.0 と 4.0 の両方のバージョンとmscorlibの 3.5 と 4.0 のバージョンを参照していることがわかりますSystem.Data.Linq。奇妙なことに、それは の 4.0 バージョンしか使用していませんSystem.Xml。それはおそらく私の問題です。

これらの XmlSerializers を使用して Web アプリを実行するにはどうすればよいですか? これらの XmlSerializers を削除するだけで、Web アプリは正常に動作します。これはオプションですが、特定のバージョンの CLR 用のシリアライザーを作成するように MSBUILD に強制するにはどうすればよいですか?

XmlSerializers の作成を強制するプロジェクト ファイルに追加する MSBuild タスクを次に示します。

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
 <Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
 <SGen BuildAssemblyName="$(TargetFileName)" BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)" ShouldGenerateSerializer="true" UseProxyTypes="false" KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)" DelaySign="$(DelaySign)" ToolPath="$(SGenToolPath)">
  <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
 </SGen>
</Target>
4

3 に答える 3

8

MSBuild 4 は、3.5 ツールを使用して 3.5 プロジェクトをビルドします (すべきです...)。ただし、3.5 のツールがどこにあり、4.0 のツールを使用しているのかがわからないようです。その結果、3.5 プロジェクト (CLR 2.0.50727 アセンブリを使用) は正しくビルドされますが、4.0 sgen.exe ツールは Ceoimage.Basecamp.XmlSerializers.dll を CLR 4.0.30319 アセンブリとして生成します。

MSBuild は、レジストリを使用して v3.5 ツールへのパスを取得します。v3.5 SDK ツールを必要とする MSBuild タスクは、3.5 ツールへのパスが特定できない場合、v4.0 パスにフォールバックします - C:\Windows\Microsoft で TargetFrameworkSDKToolsDirectory プロパティを設定するために使用されるロジックを見てください。 NET\Framework\v4.0.30319\Microsoft.NETFramework.props 本当に興味がある場合。

次のようにして、考えられるレジストリの問題を診断して修正できます。

Process Monitor をインストールし、フィルターを設定して、msbuild によるレジストリ アクセスを監視します (イベント クラス: Registry、プロセス名: msbuild.exe、すべての種類の結果)。

ビルドを実行する

"MSBuild\ToolsVersions\4.0\SDK35ToolsPath" に一致する RegQueryValue アクセスのプロセス モニターを検索します。これは、「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft」または「HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft」の下にある可能性があることに注意してください。

レジストリでこのキーを見ると、別のレジストリ値にエイリアスが設定されていることがわかります。 InstallationFolder)" この直後に、msbuild が指定されたキーから値を読み込もうとするため、"NAME NOT FOUND" という結果が表示される可能性があります。

ここから追加/修正する必要があるキーは明らかです。

レジストリ値が間違っている理由はいくつか考えられます。私の場合、Microsoft SDK v7.1 のインストールに問題があったため、レジストリ キーの名前が間違っていました。これは、次のバグとして特定されています。

http://connect.microsoft.com/VisualStudio/feedback/details/594338/tfs-2010-build-agent-and-windows-7-1-sdk-targeting-net-3-5-generates-wrong-embedded-資力

于 2011-04-18T12:34:25.257 に答える
2

4.0固有のものに依存していますか?

MSBuild 4.0を呼び出すと、4.0ツールを入手できます。MSBuild 3.5を呼び出すと、3.5ツールが提供されます(2.0 CLRで明確にホストしているため、これが必要です)。

もう1つのオプションは、4.0CLRをWebサーバーに配置することです。それが開いていない場合は、ストリームに4.0をターゲットにしたものを含めるべきではありません。

于 2010-08-24T08:40:09.923 に答える
2

次のように、SGEN タスクのツール パスを明示的に指定して 3.5 バージョンを使用できることがわかりました。

<SGen BuildAssemblyName="$(TargetFileName)" BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)" ShouldGenerateSerializer="true" UseProxyTypes="false" KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)" DelaySign="$(DelaySign)" ToolPath="C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin">
于 2010-08-25T14:55:01.900 に答える