Question

Ce code génère une exception FileNotFoundException, mais s'exécute finalement sans problème:

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

Voici l'exception:

Une exception de première chance du type 'System.IO.FileNotFoundException' s'est produite dans mscorlib.dll

Informations complémentaires: Impossible de charger le fichier ou l'assembly 'MyAssembly.XmlSerializers, Version = 1.4.3190.15950, Culture = neutre, PublicKeyToken = null' ou l'une de ses dépendances. Le système ne trouve pas le fichier spécifié.

Il semble que le framework génère automatiquement l'assembly de sérialisation s'il n'est pas trouvé. Je peux le générer manuellement à l'aide de sgen.exe, ce qui atténue l'exception.

Comment faire pour que Visual Studio génère automatiquement l'assemblage de sérialisation XML?

Mise à jour: le paramètre Generate Serialization Assembly: On ne semble rien faire.

Était-ce utile?

La solution

Voici comment j'ai réussi à le faire en modifiant le script MSBUILD dans mon fichier .CSPROJ:

Tout d’abord, ouvrez votre fichier .CSPROJ en tant que fichier plutôt qu’en tant que projet. Faites défiler l'écran jusqu'au bas du fichier jusqu'à trouver ce code mis en commentaire, juste avant la fermeture de la balise 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>
-->

Maintenant, nous venons d'insérer notre propre cible AfterBuild pour supprimer tout XmlSerializer et SGen existants, comme suit:

<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>

Cela fonctionne pour moi.

Autres conseils

Comme l'a expliqué Martin dans sa réponse , l'activation de la génération de l'assemblage de sérialisation via les propriétés du projet ne suffit pas car la tâche SGen ajoute le /proxytypes commutateur à la ligne de commande sgen.exe.

Microsoft possède une propriété MSBuild documentée qui vous permet de désactiver le SGenUseProxyTypes switch et amène la tâche SGen à générer les assemblys de sérialisation même s’il n’ya aucun type de proxy dans l’assemblage.

  

SGenUseProxyTypes

     

Une valeur booléenne qui indique si les types de proxy   devrait être généré par SGen.exe. La cible SGen utilise cette propriété pour   définir l'indicateur UseProxyTypes. La propriété par défaut est true, et là   n'y a pas d'interface utilisateur pour changer cela. Pour générer l'assemblage de sérialisation pour   types non-webservice, ajoutez cette propriété au fichier de projet et définissez-la   false avant d'importer les fichiers Microsoft.Common.Targets ou   C # / VB.targets

Comme le suggère la documentation, vous devez modifier votre fichier de projet manuellement, mais vous pouvez ajouter la propriété <=> à votre configuration pour activer la génération. La configuration de vos fichiers de projet ressemblerait à quelque chose comme ceci:

  <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>

Les autres réponses à cette question ont déjà mentionné le paramètre Propriétés du projet - > Construire - > Générer des assemblages de sérialisation , mais par défaut, cela ne générera l'assemblage que si are " Types de proxy de service Web XML " dans le projet.

Le meilleur moyen de comprendre le comportement exact de Visual Studio consiste à examiner la cible GenerateSerializationAssemblies dans C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 ** Microsoft.Common. fichier de cibles **.

Vous pouvez vérifier le résultat de cette tâche de construction à partir de la fenêtre Sortie de Visual Studio et sélectionner Construire dans la liste Afficher la sortie de : boîte. Vous devriez voir quelque chose le long des lignes de

C: \ Programmes \ Visual Studio 8 \ SDK \ v2.0 \ bin \ sgen.exe /assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll / types de proxy / reference: .. / compiler: / delayign- LibraryA - & Gt; D: \ Temp \ LibraryA \ bin \ Debug \ LibraryA.dll

Le point clé ici est le commutateur / types de proxy . Pour en savoir plus sur les différents commutateurs du outil générateur de sérialiseur XML ( Sgen.exe)

Si vous connaissez MSBuild, vous pouvez personnaliser la cible GenerateSerializationAssemblies afin que la tâche SGen ait un attribut UseProxyTypes = " false " au lieu de vrai mais vous devez ensuite assumer toutes les responsabilités associées à la personnalisation du système Visual Studio / MSBuild. Sinon, vous pouvez simplement étendre votre processus de génération pour appeler manuellement SGen sans le commutateur / proxytypes.

Si vous lisez la documentation de SGen, ils sont assez clairs pour indiquer que Microsoft souhaitait limiter l'utilisation de cette fonctionnalité. Compte tenu de la quantité de bruit sur ce sujet, il est assez clair que Microsoft n'a pas très bien documenté l'expérience de Visual Studio. Il existe même un commentaire de connexion pour ce problème et la réponse. n'est pas génial.

la création d'une nouvelle définition de tâche sgen casse une mouche sur le volant. Il suffit de définir les variables nécessaires pour que la tâche fonctionne comme prévu. Quoi qu'il en soit, la documentation de Microsoft ne contient pas certaines informations importantes.

Procédure de pré-génération des assemblys de sérialisation

(avec des éléments de http://msdn.microsoft.com/en-us/library/ff798449 .aspx )

  1. Dans Visual Studio 2010, dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet pour lequel vous souhaitez générer des assemblys de sérialisation, puis cliquez sur Décharger le projet.
  2. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet pour lequel vous souhaitez générer des assemblys de sérialisation, puis cliquez sur Modifier .csproj.
  3. Dans le fichier .csproj, immédiatement après l'élément <TargetFrameworkVersion>v?.?</TargetFrameworkVersion>, ajoutez les éléments suivants:

      

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

  4. Dans le fichier .csproj, dans chaque configuration de plate-forme

    par exemple. <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    ajoutez la ligne suivante:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. Enregistrez et fermez le fichier .csproj.

  6. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet que vous venez de modifier, puis cliquez sur Recharger le projet.

Cette procédure génère un assembly supplémentaire nommé .xmlSerializers.dll dans votre dossier de sortie. Vous devrez déployer cet assemblage avec votre solution.

Explication

Par défaut, SGen uniquement pour les types de proxy génère pour & # 8220; Tous les processeurs & # 8221 ;. Cela se produit si vous ne définissez pas les variables correspondantes dans votre fichier de projet.

SGenPlatformTarget est requis pour correspondre à votre PlatformTarget. J'ai tendance à penser qu'il s'agit d'un bogue dans le modèle de projet. Pourquoi la plateforme cible sgen devrait-elle différer de celle de votre projet? Si c'est le cas, vous obtiendrez une exception d'exécution

  

0x80131040: La définition du manifeste de l'assembly localisé ne correspond pas à la référence de l'assembly

Vous pouvez localiser la définition de la tâche msbuild en analysant votre fichier de projet:

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

où MSBuildToolsPath dépend de votre <TargetFrameworkVersion> http://msdn.microsoft.com/en-us /library/bb397428.aspx

Recherchez à l'intérieur de la définition de tâche SGen pour TargetFrameworkVersion 4.0 à partir de

  

Chemin d'installation Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.CSharp.targets

pour voir les variables non documentées telles que $ (SGenPlatformTarget), vous êtes libre de les définir dans votre fichier de projet

<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>

Si quelqu'un d'autre se heurte soudainement à ce problème alors que tout fonctionnait bien auparavant: Pour moi, cela concernait & "Activer uniquement mon code (géré uniquement) &"; décochez la case dans le menu des options (Options - > Débogage) (qui était automatiquement désactivée après l'installation de .NET Reflector).

EDIT: Ce qui veut dire, bien sûr, que cette exception se produisait auparavant, mais lorsque & Cochez uniquement mon code & Quot; est désactivé, l’assistant de débogage (s’il est activé) s’arrêtera à ce stade lorsqu’il sera lancé.

Je suis un peu en retard à la fête, mais j’ai trouvé difficile de travailler avec la réponse précédente. Plus précisément, Visual Studio se bloquait chaque fois que j'essayais d'afficher les propriétés de mon projet. Je suppose que cela était dû au fait qu'il ne comprenait plus comment lire le fichier csproj. Cela dit ...

Ajoutez les éléments suivants à la ligne de commande de votre événement post-build:

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

Ceci utilisera sgen.exe directement pour reconstruire l’assemblage de sérialisation XML à chaque fois que vous construisez votre projet pour Debug ou Release.

Recherchez les propriétés de la solution. Dans l'onglet de construction en bas, vous trouverez une liste déroulante intitulée & "Générer l'assemblage de sérialisation &";

.

Une solution légèrement différente de celle fournie par la sauvegarde du cerveau pourrait consister à spécifier directement la cible de la plate-forme à l'endroit où vous devez utiliser comme ça:

<!-- 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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top