web-dev-qa-db-ja.com

ビルドの一部としてXml Serialization Assemblyを生成する

このコードはFileNotFoundExceptionを生成しますが、最終的には問題なく実行されます。

void ReadXml()
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    //...
}

例外は次のとおりです。


Mscorlib.dllで「System.IO.FileNotFoundException」タイプの最初のチャンス例外が発生しました

追加情報:ファイルまたはアセンブリ「MyAssembly.XmlSerializers、バージョン= 1.4.3190.15950、Culture = neutral、PublicKeyToken = null」またはその依存関係の1つをロードできませんでした。システムは、指定されたファイルを見つけることができません。


フレームワークが見つからない場合、シリアル化アセンブリを自動的に生成するようです。 sgen.exeを使用して手動で生成し、例外を軽減できます。

Visual StudioでXMLシリアル化アセンブリを自動的に生成するにはどうすればよいですか?


更新:シリアル化アセンブリの生成:オン設定は何もしないようです

64
Adam Tegen

これは、.CSPROJファイルのMSBUILDスクリプトを変更することにより、どうやってそれを行うことができたかです。

最初に、プロジェクトとしてではなくファイルとして.CSPROJファイルを開きます。 Projectタグを閉じる直前に、このコメント化されたコードが見つかるまで、ファイルの下部までスクロールします。

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

次のように、独自のAfterBuildターゲットを挿入して、既存のXmlSerializerとSGenを削除します。

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
   <!-- Delete the file because I can't figure out how to force the SGen task. -->
   <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="$(TargetFrameworkSDKToolsDirectory)"
     Platform="$(Platform)">
      <Output
       TaskParameter="SerializationAssembly"
       ItemName="SerializationAssembly" />
   </SGen>
</Target>

それは私のために働く。

56
flipdoubt

Martinが 彼の答え で説明したように、SGenタスクが/proxytypesスイッチをsgen.exeコマンドラインに追加しているため、プロジェクトプロパティを介したシリアル化アセンブリの生成をオンにするだけでは不十分です。

Microsoftには 文書化されたMSBuildプロパティ があり、/proxytypesスイッチを無効にして、アセンブリにプロキシタイプがない場合でもSGenタスクにシリアル化アセンブリを生成させることができます。

SGenUseProxyTypes

SGen.exeによってプロキシタイプを生成する必要があるかどうかを示すブール値。 SGenターゲットは、このプロパティを使用してUseProxyTypesフラグを設定します。このプロパティのデフォルトはtrueであり、これを変更するUIはありません。非Webサービスタイプのシリアル化アセンブリを生成するには、Microsoft.Common.TargetsまたはC#/ VB.targetsをインポートする前に、このプロパティをプロジェクトファイルに追加し、falseに設定します。

ドキュメントが示唆するように、プロジェクトファイルを手動で変更する必要がありますが、生成を有効にするためにSGenUseProxyTypesプロパティを構成に追加できます。プロジェクトファイルの構成は次のようになります。

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
67
heavyd

この質問に対する他の回答では、プロジェクトプロパティ->ビルド-> シリアル化アセンブリの生成設定について既に言及していますが、デフォルトでは、「XML Webサービスプロキシタイプ "プロジェクト内。

Visual Studioの正確な動作を理解する最良の方法は、C:\ WINDOWS\Microsoft.NET\Framework\v2.0.50727 ** Microsoft.Common.targets **内のGenerateSerializationAssembliesターゲットを調べることです。ファイル。

Visual Studio Outputウィンドウからこのビルドタスクの結果を確認し、Show output from:ドロップダウンボックスからBuildを選択できます。あなたはの線に沿って何かを見るはずです

C:\ Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\sgen.exe /Assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll/proxytypes/reference :../compiler:/ delaysign- LibraryA-> D:\ Temp\LibraryA\bin\Debug\LibraryA.dll

ここで重要なのは、/ proxytypesスイッチです。 XML Serializer Generator Tool(Sgen.exe) のさまざまなスイッチについて読むことができます

MSBuildに精通している場合は、GenerateSerializationAssembliesターゲットをカスタマイズして、SGenタスクの属性をtrueではなくUseProxyTypes = "false"にすることができますが、Visual Studio/MSBuildシステムのカスタマイズに関連するすべての責任を負う必要があります。または、/ proxytypesスイッチなしで手動でSGenを呼び出すようにビルドプロセスを拡張することもできます。

SGenのドキュメントを読むと、Microsoftがこの機能の使用を制限したかったのは明らかです。このトピックに関するノイズの量を考えると、MicrosoftがVisual Studioのエクスペリエンスをドキュメント化する上で素晴らしい仕事をしていないことは明らかです。この問題には Connect Feedback 項目もあり、応答は良くありません。

29

新しいsgenタスク定義を作成すると、ホイールのフライが壊れます。必要な変数を設定するだけで、タスクが意図したとおりに機能します。とにかく、Microsoftのドキュメントにはいくつかの重要な情報が欠けています。

シリアル化アセンブリを事前生成する手順

http://msdn.Microsoft.com/en-us/library/ff798449.aspx の一部を使用)

  1. Visual Studio 2010のソリューションエクスプローラーで、シリアル化アセンブリを生成するプロジェクトを右クリックし、[プロジェクトのアンロード]をクリックします。
  2. ソリューションエクスプローラーで、シリアル化アセンブリを生成するプロジェクトを右クリックし、[。csprojの編集]をクリックします。
  3. .csprojファイルで、_<TargetFrameworkVersion>v?.?</TargetFrameworkVersion>_要素の直後に、次の要素を追加します。

    _<SGenUseProxyTypes>false</SGenUseProxyTypes>_ <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. .csprojファイル内の各プラットフォーム構成

    例えば<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    次の行を追加します。

    _<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>_

  5. .csprojファイルを保存して閉じます。

  6. ソリューションエクスプローラーで、編集したプロジェクトを右クリックし、[プロジェクトの再読み込み]をクリックします。

この手順により、出力フォルダーに.xmlSerializers.dllという名前の追加のアセンブリが生成されます。このアセンブリをソリューションと共に展開する必要があります。


説明

SGenは、デフォルトで「任意のCPU」のプロキシタイプのみを生成します。これは、プロジェクトファイルで対応する変数を設定しない場合に発生します。

PlatformTargetと一致させるには、SGenPlatformTargetが必要です。これはプロジェクトテンプレートのバグだと思う傾向があります。 sgenターゲットプラットフォームがプロジェクトのプラットフォームと異なるのはなぜですか?実行すると、ランタイム例外が発生します

0x80131040:見つかったアセンブリのマニフェスト定義がアセンブリ参照と一致しません

プロジェクトファイルを分析することにより、msbuildタスク定義を見つけることができます。

_<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
_

mSBuildToolsPathは_<TargetFrameworkVersion>_に依存します http://msdn.Microsoft.com/en-us/library/bb397428.aspx

からTargetFrameworkVersion 4.0のSGenタスク定義を見てください

Windowsインストールパス\ Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets

$(SGenPlatformTarget)などのドキュメント化されていない変数を表示するには、プロジェクトファイルに自由に設定できます

_<Target
    Name="GenerateSerializationAssemblies"
    Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
    DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
    Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
    Outputs="$(IntermediateOutputPath)$(_SGenDllName)">

    <SGen
        BuildAssemblyName="$(TargetFileName)"
        BuildAssemblyPath="$(IntermediateOutputPath)"
        References="@(ReferencePath)"
        ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
        UseProxyTypes="$(SGenUseProxyTypes)"
        KeyContainer="$(KeyContainerName)"
        KeyFile="$(KeyOriginatorFile)"
        DelaySign="$(DelaySign)"
        ToolPath="$(SGenToolPath)"
        SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
        EnvironmentVariables="$(SGenEnvironment)"
        SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
        Platform="$(SGenPlatformTarget)"
        Types="$(SGenSerializationTypes)">
            <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
    </SGen>
</Target>
_
9
brain backup

私はパーティーに少し遅れましたが、前の答えを扱うのは難しいと感じました。具体的には、プロジェクトのプロパティを表示しようとすると、Visual Studioがクラッシュします。これは、csprojファイルの読み方を理解できなくなったためだと思います。とはいえ...

ビルド後のイベントコマンドラインに次を追加します。

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force

これにより、デバッグまたはリリース用にプロジェクトをビルドするたびに、sgen.exeを直接活用してXmlシリアル化アセンブリが再構築されます。

2
mcfea

以前にすべてが正常に機能していた後に突然他の誰かがこの問題に遭遇した場合:私にとっては、オプションメニュー([オプション]-> [デバッグ])で[Just My Code(Managed Only) .NET Reflectorのインストール後に自動的にオフになります)。

編集:もちろん、この例外は以前に発生していましたが、「コードのみを有効にする」がオフの場合、デバッグアシスタント(有効になっている場合)は、スローされるとこの時点で停止します。

2
joniba

ソリューションのプロパティを確認します。下部の[ビルド]タブには、[シリアル化アセンブリの生成]というドロップダウンがあります

1
Darren Kopp

brain backup によって提供されるソリューションとは少し異なるソリューションは、使用する必要がある場所でプラットフォームターゲットを直接指定することです。

<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition=" '$(PlatformTarget)'=='' ">
  <SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(PlatformTarget)'!='' ">
  <SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>

<!-- Delete the file because I can't figure out how to force the SGen task. -->
<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)"
  SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
  EnvironmentVariables="$(SGenEnvironment)"
  Platform="$(SGenPlatform)">
  <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
1
Timoty Weis