2010-08-02 1 views
0

J'ai rencontré un problème étrange la semaine dernière. Un appel à new XMLSerializer(typeof(MyType)) s'est écrasé avec une exception ExternalException, me disant que csc.exe n'a pas pu être exécuté. Après quelques recherches, j'ai trouvé que cette exception ne se produit que si la taille de l'environnement de processus atteint une limite "critique". J'ai créé un petit exemple d'application pour vérifier cette raison.Comment éviter l'échec de XmlSerializer si l'environnement de traitement est trop grand?

namespace EnvironmentTester 
{ 
    public class Program 
    { 
     private static void Main(string[] args) 
     { 
      FillProcessEnvironmentBlock(false); 
      SerializeDataObject(); 
     } 

     private static void SerializeDataObject() 
     { 
      var dto = new DataObject {Name = "MyDto"}; 

      try 
      { 
       var xmlSerializer = new XmlSerializer(dto.GetType()); // throws exception 
       xmlSerializer.Serialize(TextWriter.Null, dto); 

       Console.WriteLine("No exception occured."); 
      } 
      catch(Exception e) 
      { 
       Console.WriteLine("Exception occured : " + e.GetType()); 
      } 

      Console.ReadKey(); 
     } 

     private static void FillProcessEnvironmentBlock(bool fillToMax) 
     { 
      var currentEnvVarIndex = 0; 
      var environmentSize = GetEnvironmentSize(); 

      int criticalEnvironmentSize = fillToMax ? 30692 : 30691; 

      while (environmentSize < criticalEnvironmentSize) 
      { 
       var envVarName = "Env" + currentEnvVarIndex; 
       var envVarValueLength = (criticalEnvironmentSize - environmentSize - envVarName.Length - 2) % 32000; 
       Environment.SetEnvironmentVariable(envVarName, new string('a', envVarValueLength)); 
       currentEnvVarIndex++; 
       environmentSize = GetEnvironmentSize(); 
      } 
     } 

     private static int GetEnvironmentSize() 
     { 
      var envVars = Environment.GetEnvironmentVariables(); 
      int environmentSize = 0; 


      foreach (string envKey in envVars.Keys) 
      { 
       environmentSize += envKey.Length; 
      } 

      foreach (string envVar in envVars.Values) 
      { 
       environmentSize += envVar.Length; 
      } 

      environmentSize += 2*envVars.Keys.Count; // add the '=' and the '\0' 

      return environmentSize; 
     } 

     public class DataObject 
     { 
      [XmlAttribute("ObjectName")] 
      public string Name { get; set; } 
     } 
    } 
} 

Si FillProcessEnvironmentBlock est appelé avec le paramètre false, la taille critique est pas atteinte, si elle est appelée avec vrai, le ExternalException est jeté. Je l'ai testé sur deux machines Windows XP 32 bits SP2 différentes, avec le même résultat.

Je sais que csc.exe est appelée pour créer un assembly temporaire utilisé pour lire/écrire le fichier xml. Mais je ne sais pas pourquoi l'appel à csc.exe échoue si l'environnement de processus est trop grand.

Est-ce que quelqu'un connaît la raison de cette exception? Et comment puis-je contourner cela (si je ne veux pas écrire ma propre sérialisation xml)? Y a-t-il d'autres problèmes connus causés par un environnement de processus trop important?

+0

Est-ce votre application originale en train d'écrire ~ 30 000 variables d'environnement? – Paolo

+0

Non, mais l'environnement dans lequel l'application s'exécute peut atteindre cette taille car elle utilise des scripts de traitement par lots étendus pour configurer ses paramètres. –

Répondre

1

Vous pouvez précompiler serializers en utilisant l'outil Sgen ou MSBuild Sgen task

+0

Je ne sais pas quelles classes peuvent être stockées dans le fichier XML, car il s'agit d'une sérialisation générique d'un type T fourni par d'autres assemblys. –

Questions connexes