2009-10-05 3 views
13

Je veux que ma demande soit distribuable sous forme de fichier .exe unique mais je veux être en mesure d'obtenir de beaux rapports d'erreur avec les numéros de ligne de code source (l'application envoie simplement email avec exception.ToString() et quelques informations supplémentaires quand une exception non gérée se produit).Intégrer pdb dans l'assemblage

Y at-il un moyen d'intégrer .pdb dans l'assembly?

Répondre

8

Utilisez MiniDumps au lieu de "exception.ToString()". Cela vous donnera beaucoup plus d'informations et n'aura pas besoin que le fichier .pdb soit distribué avec le fichier .exe.

Lien utile: Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET

+0

Absolument, mais vous devez garder les PDB de chaque navire pour vous construire que pour travailler de manière fiable - mieux pour configurer un serveur de symboles en interne (voir http://msdn.microsoft.com/en-us/library /ms680693(VS.85).aspx) –

+0

Puis-je faire minidump d'une application en cours d'exécution? Par exemple, si je reçois une exception non gérée dans WinForms, je vais afficher une boîte de dialogue d'erreur à l'utilisateur avec une option pour envoyer un rapport d'erreur et ** continuer ** travailler avec l'application (contrairement à l'application de terminaison). –

+0

Oui, lisez l'article lié. –

3

Vous pouvez écrire un exécutable stub, qui contient des ressources intégrées, à la fois votre exécutable réel et son fichier pdb. Au démarrage de l'exécutable staub, il extrait l'exécutable réel et le pdb dans un répertoire temporaire et le lance.

Tout comme certains installateurs ou d'autres applications font.

Je ne sais pas si cela vaut la peine de faire des efforts supplémentaires.

+0

J'ai aussi eu cette idée. Cela me permettra également d'appliquer une compression à mes binaires et de réduire .exe. L'inconvénient est plus long temps de démarrage. J'espère juste qu'il y a une façon plus simple de le faire. –

3

J'ai utilisé le gestionnaire AssemblyResolve suivant, puis j'ai incorporé à la fois dll et pdb de tous les assemblages. Vous pouvez définir cela comme tout ce qui s'exécute en premier dans l'application avant que les dépendances ne soient nécessaires.

private static void SetupEmbeddedAssemblyResolve() 
    { 
     // Based on http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx 
     AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
     { 
      var name = args.Name; 
      var asmName = new AssemblyName(name); 

      // Any retargetable assembly should be resolved directly using normal load e.g. System.Core issue: 
      // http://stackoverflow.com/questions/18793959/filenotfoundexception-when-trying-to-load-autofac-as-an-embedded-assembly 
      if (name.EndsWith("Retargetable=Yes")) 
      { 
       return Assembly.Load(asmName); 
      } 

      var executingAssembly = Assembly.GetExecutingAssembly(); 
      var resourceNames = executingAssembly.GetManifestResourceNames(); 

      var resourceToFind = asmName.Name + ".dll"; 
      var resourceName = resourceNames.SingleOrDefault(n => n.Contains(resourceToFind)); 

      if (string.IsNullOrWhiteSpace(resourceName)) { return null; } 

      var symbolsToFind = asmName.Name + ".pdb"; 
      var symbolsName = resourceNames.SingleOrDefault(n => n.Contains(symbolsToFind)); 

      var assemblyData = LoadResourceBytes(executingAssembly, resourceName); 

      if (string.IsNullOrWhiteSpace(symbolsName)) 
      { 
       Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}'", resourceToFind, resourceName)); 

       return Assembly.Load(assemblyData); 
      } 
      else 
      { 
       var symbolsData = LoadResourceBytes(executingAssembly, symbolsName); 

       Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}' with symbols '{2}'", resourceToFind, resourceName, symbolsName)); 

       return Assembly.Load(assemblyData, symbolsData); 
      } 
     }; 
    } 

    private static byte[] LoadResourceBytes(Assembly executingAssembly, string resourceName) 
    { 
     using (var stream = executingAssembly.GetManifestResourceStream(resourceName)) 
     { 
      var assemblyData = new Byte[stream.Length]; 

      stream.Read(assemblyData, 0, assemblyData.Length); 

      return assemblyData; 
     } 
    } 
+1

J'ai fait un petit billet de blog avec ceci aussi à: http://www.codingmurmur.com/2014/02/embedded-assembly-loading-with-support.html – nietras

+0

Woah. Je savais que vous pouviez le faire avec des fichiers dll, mais cela fonctionne aussi avec les fichiers pdb? Soigné. Cela signifie que, pour l'utiliser pour créer un projet dans une distribution à un seul fichier, vous devez cependant placer votre application principale dans un projet de DLL externe. – Nyerguds

+0

Eh bien seulement si vous ne voulez pas que l'application principale pdb soit à côté de l'exe. Nous pouvons vivre avec ça. – nietras