2 votes

Impossible d'inclure un manifeste dans mon application c# compilée dynamiquement

Je viens d'être chargé de mettre à niveau une application web d'entreprise interne. L'utilisateur saisit des données, l'application web compile ensuite un EXE winforms personnalisé (type d'application auto-extracteur/installateur), puis le site web le met à disposition en téléchargement.

Nous avons récemment appris que ce programme d'installation compilé de manière personnalisée affiche une erreur/un avertissement de compatibilité dans Windows 7. Après quelques recherches, j'ai appris que je devais fournir un manifeste d'application qui spécifie la compatibilité avec Windows 7 :

Liens connexes :

C'est ma première expérience avec du code personnalisé/compilé dynamiquement, et des manifestes d'application.

Comme cette application est compilée à la volée (à partir d'un seul fichier de code et de quelques ressources intégrées), je ne peux pas simplement ajouter un manifeste à mon projet. J'ai donc utilisé l'option "/win32manifest" du compilateur pour référencer le fichier manifeste lors de la compilation.

Voici un bout de code de la classe personnalisée "Archive Compiler" qui effectue la compilation : (je n'ai ajouté que la partie "Application Manifest").

public void CompileArchive(string archiveFilename, bool run1stItem, string iconFilename)
{
    CodeDomProvider csc = new CSharpCodeProvider();
    CompilerParameters cp = new CompilerParameters();

    cp.GenerateExecutable = true;
    cp.OutputAssembly = archiveFilename;
    cp.CompilerOptions = "/target:winexe";

    // Custom option to run a file after extraction  
    if (run1stItem) {
        cp.CompilerOptions += " /define:RUN_1ST_ITEM";
    }
    if (!string.IsNullOrEmpty(iconFilename)) {
        cp.CompilerOptions += " /win32icon:" + iconFilename;
    }
    cp.ReferencedAssemblies.Add("System.dll");
    cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");

    // Add application manifest to specify operating system compatibility (to fix compatibility warning in Windows 7)
    string AppManifestPath = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "CustomInstaller.exe.manifest" );
    if ( File.Exists( AppManifestPath ) ) {
        cp.CompilerOptions += string.Format( " /win32manifest: \"{0}\"", AppManifestPath );
    }

    // Add compressed files as resource
    cp.EmbeddedResources.AddRange(filenames.ToArray()); 

    // Compile standalone executable with input files embedded as resource
    CompilerResults cr = csc.CompileAssemblyFromFile(cp, sourceCodeFilePath);

    // yell if compilation error
    if (cr.Errors.Count > 0) {
        string msg = "Errors building " + cr.PathToAssembly;
        foreach (CompilerError ce in cr.Errors) { msg += Environment.NewLine + ce.ToString(); }
        throw new ApplicationException(msg);
    }
}

Cependant, lorsque je compile, je continue à rencontrer cette erreur :

Bâtiment des erreurs D:\Projects\MySolution\WebAppName\App_Data\MyUsername\CustomInstaller.exe erreur CS2007 : Option non reconnue : '/win32manifest:'.

J'ai du mal à trouver des informations à ce sujet, à part des articles qui indiquent que ce paramètre existe et est valide. L'application web est dans visual studio 2010 et fonctionne sur framework 2.0. L'application compilée dynamiquement fait également référence à .net 2.0 (vérifié avec un décompilateur). Je ne sais pas quel EXE est appelé pour effectuer la compilation, ou ce que je pourrais vérifier d'autre pour résoudre ce problème. Toute aide serait appréciée.

3voto

sh34 Points 31

Il peut être nécessaire de supprimer l'espace entre /win32manifest: y \"{0}\" dans cette ligne cp.CompilerOptions += string.Format( " /win32manifest: \"{0}\"", AppManifestPath );

sans espace, cela fonctionne bien, mais lorsque j'ajoute un espace, comme dans votre code, j'ai une erreur :

Errors building C:\Projects\Services\Services.WebUI\Binaries\install\temp\codedom.exe
error CS2005: Missing file specification for '/win32manifest:' option
warning CS2008: No source files specified

1voto

jmalmari Points 51

La page de documentation MSDN pour le commutateur /win32manifest existe pour Visual Studio 2008 le plus ancien. Il a donc peut-être été ajouté dans .NET v3.5.

Vous pouvez spécifier "CompilerVersion" dans le constructeur de CSharpCodeProvider.

Je vais devoir m'en tenir à .NET 2.0 et je vais donc utiliser l'approche mt.exe.

0voto

Ben Brandt Points 848

Après plus de recherches, j'ai appris que mt.exe qui est un simple utilitaire en ligne de commande pour ajouter des manifestes d'application. J'ai placé une copie de l'exe dans mon projet web, puis j'ai ajouté du code pour appeler ce processus après la compilation de l'application :

//Add an application manifest using mt.exe
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "mt.exe" );
string AppManifestPath = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "CustomInstaller.exe.manifest" );
startInfo.Arguments = string.Format( "-nologo -manifest \"{0}\" -outputresource:\"{1};#1\"", AppManifestPath, cp.OutputAssembly );
process.StartInfo = startInfo;
process.Start();
process.WaitForExit( 10000 ); //wait until finished (up to 10 sec)

Cela permet d'ajouter mon manifeste à l'EXE compilé rapidement et facilement. J'ai aussi trouvé ceci Visualisateur de manifeste ce qui a permis de vérifier facilement le contenu de mon manifeste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X