Runtime: Prise en charge de la distribution de fichiers uniques

Créé le 5 oct. 2018  ·  225Commentaires  ·  Source: dotnet/runtime

Ce problème suit la progression de la fonctionnalité de distribution de fichier unique .NET Core 3.0.
Voici le document de conception et le plan de mise en scène de la fonctionnalité.

area-Single-File

Commentaire le plus utile

Le premier démarrage devrait être beaucoup plus lent - il extrait l'application sur le disque - donc beaucoup d'E/S.

Cela n'aurait jamais dû arriver, vous rendez l'expérience utilisateur horrible PAR CONCEPTION, choix horrible, c'est ainsi que vous faites détester aux utilisateurs la technologie que le développeur utilise pour eux

Comme mentionné par @Safirion, nous travaillons sur la prochaine amélioration pour le fichier unique qui devrait exécuter directement la plupart du code géré à partir du .exe (pas d'extraction sur le disque). Je ne peux pas encore promettre un train de sortie.

Pourquoi sortir ça officiellement maintenant si ça va changer bientôt ? doit être marqué comme aperçu/expérimental

à mon avis, c'est une perte de temps et de ressources, concentrez-vous sur la compilation AOT et le tree-shaking, mettez toutes vos ressources là-bas, arrêtez avec les hacks

Tous les 225 commentaires

Par intérêt, comment cette initiative se compare-t-elle à CoreRT ? Ils ressemblent à des efforts similaires ?

Est-ce lié au " code utilisateur éventuellement natif ", c'est-à-dire que cela permettra toujours au code d'être compilé JIT, pas seulement AOT?

De plus, je suppose que les composants d'exécution (' Code natif (runtime, hôte, parties natives du framework.. ') seront ceux du repo CoreCLR ?

Vous posez de bonnes questions, mais comme c'est encore tôt dans la conception, je n'ai pas encore de bonnes réponses.

Par intérêt, comment cette initiative se compare-t-elle à CoreRT ? Ils ressemblent à des efforts similaires?

Il y aurait probablement des résultats quelque peu similaires (un seul fichier), mais la conception peut avoir des caractéristiques de performance différentes ou des fonctionnalités qui fonctionnent/ne fonctionnent pas. Par exemple, une conception possible pourrait consister à concaténer essentiellement tous les fichiers d'une application autonome .NET Core dans un seul fichier. C'est 10s de Mo et cela pourrait démarrer plus lentement, mais d'un autre côté, cela permettrait toutes les capacités de CoreCLR, y compris le chargement des plugins, l'émission de réflexion et les diagnostics avancés. CoreRT pourrait être considéré comme l'autre extrémité du spectre - c'est un Mo à un chiffre et a un temps de démarrage très rapide, mais en n'ayant pas de JIT, il ne peut pas charger de plugins ou utiliser l'émission de réflexion et le temps de construction est plus lent que la plupart. Les développeurs NET sont habitués à. Il a actuellement quelques autres limitations qui pourraient s'améliorer avec le temps, mais pourraient ne pas être meilleures avec .NET Core 3.0 (nécessitant éventuellement des annotations pour la réflexion, manquant certains scénarios d'interopérabilité, diagnostics limités sous Linux). Il y a aussi des idées quelque part entre les deux. Si les gens ont des compromis qu'ils aimeraient faire/éviter, nous serions curieux d'en entendre parler.

Est-ce lié au «code utilisateur éventuellement natif», c'est-à-dire que cela permettra toujours au code d'être compilé JIT, pas seulement AOT?

Par "code utilisateur natif", je voulais dire que votre application peut avoir du code natif C++ (écrit par vous ou par un composant tiers). Il peut y avoir des limites à ce que nous pouvons faire avec ce code - s'il est compilé dans un fichier .dll, la seule façon de l'exécuter est hors du disque ; s'il s'agit d'un .lib, il est peut-être possible de le lier, mais cela entraîne d'autres complications.

De plus, je suppose que les composants d'exécution ("Code natif (exécution, hôte, parties natives du framework ..") seront ceux du référentiel CoreCLR ?

Sur la base de tout ce qui précède, nous déterminerons quels dépôts sont impliqués. Les "parties natives du framework" incluraient les fichiers natifs CoreFX comme ClrCompression et Unix PAL.

Une distribution de fichier unique de cette manière, même si elle a un temps de démarrage légèrement plus lent, peut être inestimable pour faciliter le déploiement. Je préférerais de beaucoup avoir la capacité d'avoir le plein pouvoir plutôt que d'être obligé d'en abandonner une partie.

Quelques scénarios qui nous intéressent. Comment cela fonctionnerait-il en termes de plateforme croisée ?
Je suppose que nous aurons un "fichier" séparé par plate-forme ?

En ce qui concerne le code natif, comment pourrais-je choisir différents composants natifs en fonction de la plate-forme ?

Quelques scénarios qui nous intéressent. Comment cela fonctionnerait-il en termes de plateforme croisée ?
Je suppose que nous aurons un "fichier" séparé par plate-forme ?
En ce qui concerne le code natif, comment pourrais-je choisir différents composants natifs en fonction de la plate-forme ?

@ayende , je cite le commentaire de @morganbr :

une conception possible pourrait consister à concaténer essentiellement tous les fichiers d'une application autonome .NET Core dans un seul fichier.

L'histoire multiplateforme actuelle pour les applications autonomes consiste à créer un package de déploiement par plate-forme que vous souhaitez cibler, car vous livrez l'application avec le runtime, qui est spécifique à la plate-forme.

@morganbr J'apprécie que vous preniez le temps de fournir une réponse aussi détaillée

Je serai intéressé de voir où va le design, c'est une initiative vraiment intéressante

J'ai quelques questions pour les personnes qui souhaitent utiliser le fichier unique. Vos réponses nous aideront à affiner nos options :

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)
  2. Votre application inclut-elle du code C++/natif (non-.NET) ?
  3. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?
  4. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?
  5. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?
  6. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?
  7. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?
  8. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?
  1. Application console/interface utilisateur sur toutes les plateformes.
  2. Peut-être en tant que composant tiers.
  3. Peut-être oui.
  4. Oui, surtout s'il existe un système simple de type ClickOnce.
  5. Un certain ralentissement initial peut être toléré. Le point 3 peut-il vous aider ?
  6. Dépend des actifs. Hello world devrait avoir une taille de l'ordre de MB.
  7. Peu importe si ce n'est que de la production.
  8. Vous aimez la liste blanche des éléments de réflexion ? Oui.

@morganbr , pensez-vous qu'il vaut mieux poser ces questions à un public plus large ; c'est-à-dire, plus large que les personnes qui connaissent ce problème GitHub ?

Par exemple, une conception possible pourrait consister à concaténer essentiellement tous les fichiers d'une application autonome .NET Core dans un seul fichier.

En regardant le compresser; ou en utilisant un système de fichiers compressé dans le fichier ?

@tpetrina , merci ! Le point 3 couvre quelques angles de conception :

  1. Le secouage d'arbres ne va pas bien avec le chargement de plugins que le secoueur d'arbres n'a pas vus car il pourrait éliminer le code sur lequel le plugin s'appuie.
  2. CoreRT n'a actuellement aucun moyen de charger des plugins
    Le point 5 concerne davantage la question de savoir si nous optimiserions la taille ou le temps de démarrage (et combien)
    Point 8, oui je pensais surtout à des trucs de réflexion

@TheBlueSky , nous avons également contacté d'autres personnes, mais cela aide à obtenir l'avis des passionnés de la communauté GitHub.

@benaadams , la compression est sur la table, mais je la considère actuellement comme orthogonale à la conception globale. Une expérimentation légère suggère que la compression peut obtenir une réduction de taille d'environ 50 % au prix de plusieurs secondes de temps de démarrage (et de temps de construction). Pour moi, c'est un compromis suffisamment radical pour que, si nous le faisons, ce soit facultatif.

@morganbr plusieurs secondes de temps de démarrage lors de l'utilisation de la compression ? Je trouve cela difficile à croire si l'on considère que l' UPX revendique des vitesses de décompression de

~10 Mo/s sur un ancien Pentium 133, ~200 Mo/s sur un Athlon XP 2000+.

@morganbr , pour moi les réponses sont :

1) Service (application console exécutant Kestrel, en gros). Exécuté en tant que service Windows / démon Linux ou dans docker.
2) Oui
3) Oui, généralement des assemblages gérés à l'aide AssemblyContext.LoadFrom . Ceux-ci sont fournis par l'utilisateur final.
4) Oui, c'est prévu. En fait, nous regroupons déjà l'ensemble du cadre de toute façon, donc aucun changement de ce point de vue.
5) En tant que service, nous nous soucions peu du temps de démarrage. 5 secondes serait raisonnable.
6) 75 Mo est probablement la limite. Cela dépend beaucoup de la taille compressée réelle, car tous les packages sont livrés compressés.
7) Pour les builds de version, des temps de build plus longs (voire beaucoup plus longs) sont acceptables.
8) Oui, absolument. La taille n'a pas beaucoup d'importance, mais plus petit, c'est mieux.

Quelque chose que je n'ai pas vu mentionné et qui est très important est le débogage de ceci.
J'espère que cela ne va pas altérer les traces de la pile, et nous voudrions pouvoir inclure des fichiers pdb ou une sorte de symboles de débogage.

À propos de la compression, tenez compte du fait que dans presque tous les cas, le mécanisme de livraison réel est déjà compressé.
Par exemple, les packages de nuget.
Les utilisateurs sont également assez versés dans la décompression des choses, donc ce n'est pas vraiment un problème.
Je pense que tu peux faire de la compression sur le côté.

Merci, @ayende ! Vous avez raison, j'aurais dû appeler le débogage. Je pense qu'il n'y a que quelques façons mineures dont le débogage pourrait être affecté :

  1. Il peut ne pas être possible d'utiliser Modifier et continuer sur un seul fichier (en raison de la nécessité d'un moyen de reconstruire et de recharger l'assemblage d'origine)
  2. La construction à fichier unique peut produire un PDB ou d'autres fichiers requis pour le débogage au-delà de ceux fournis avec vos assemblys.
  3. Si CoreRT est utilisé, il peut avoir des fonctionnalités de débogage qui se remplissent au fil du temps (en particulier sur Linux/Mac).

Lorsque vous dites "inclure les fichiers pdb", voulez-vous ces fichiers _à l'intérieur_ du fichier unique ou simplement la possibilité de les générer et de les conserver au cas où vous auriez besoin de déboguer la version à fichier unique ?

1) Pas un problème pour nous. L'E&C n'est pas pertinent ici car il est susceptible d'être utilisé uniquement pour le déploiement réel, et non au jour le jour.
2) Idéalement, nous avons un seul fichier pour tout, y compris les PDB, pas un seul fichier et un ensemble de pdb sur le côté. Il existe déjà l'option PDB intégrée, si cela fonctionnait, ce serait génial.
3) Quand on parle de débogage, je parle plus de temps de production plutôt que d'attacher un débogueur en direct. Plus précisément, les informations de trace de la pile, y compris les numéros de fichier et de ligne, la capacité de résoudre les symboles lors de la lecture du vidage, etc.

  1. Principalement des services mais une certaine interface utilisateur
  2. Certains le font, mais ce ne serait pas urgent
  3. Oui
  4. Oui
  5. Quelques secondes c'est bien
  6. Peu importe pour nous. La somme de la taille des dll est correcte
  7. Idéalement pas
  8. La taille n'est pas primordiale pour nous

Une autre question pour nous est de savoir si vous pourriez également le faire pour des composants individuels (peut-être même mis en scène) ? Par exemple, nous avons des dll de bibliothèque qui utilisent de nombreuses dépendances. Si nous pouvions les empaqueter, cela éviterait beaucoup de problèmes de gestion de version, etc. Si ceux-ci pouvaient à leur tour être empaquetés dans un exe, ce serait encore mieux?

  1. Services et certaines interfaces utilisateur.
  2. Pas pour le moment.
  3. Oui. Idéalement, des plugins qui pourraient être chargés à partir d'un dossier et rechargés au moment de l'exécution.
  4. Oui
  5. Pas de problème tant que nous ne poussons pas 10-15+.
  6. Somme de la taille des DLL, ou similaire.
  7. Oui. Pour une production, le temps de construction n'est pas vraiment un problème tant que les versions de débogage/test se construisent assez rapidement.
  8. Ça dépend, mais l'option serait pratique.
  1. Service et interface utilisateur.
  2. Parfois.
  3. Oui, généralement.
  4. Oui.
  5. Il est préférable d'être inférieur à 5 secondes.
  6. L'interface utilisateur est inférieure à 5 secondes, le service n'a pas d'importance.
  7. Le temps de construction n'est pas important, et l'effet d'optimisation est le plus important.
  8. Oui.

@tpetrina @ayende @bencyoung @Kosyne @expcat vous avez répondu oui à la question 3 ("Votre application chargerait-elle des plugins ou d'autres dll externes que vous n'aviez pas inclus à l'origine dans la construction de votre application ?") - pouvez-vous nous en dire plus sur votre utilisation Cas?

Le principal argument de vente d'une distribution de fichier unique est qu'il n'y a qu'un seul fichier à distribuer. Si votre application contient des plug-ins dans des fichiers séparés, quelle valeur obtiendriez-vous d'une distribution de fichiers unique contenant de toute façon plusieurs fichiers ? Pourquoi "app.exe+plugin1.dll+plugin2.dll" est meilleur que "app.exe+coreclr.dll+clrjit.dll+...+plugin1.dll+plugin2.dll" ?

app.exe + 300+ dll - ce qui est l'état actuel aujourd'hui est vraiment gênant.
app.exe + 1-5 dll qui sont généralement définies par l'utilisateur lui-même est beaucoup plus facile.

Notre scénario est que nous autorisons certaines extensions par l'utilisateur, donc nous ne déployons généralement qu'un seul exe et l'utilisateur peut ajouter des fonctionnalités supplémentaires si nécessaire.

Ce n'est pas tellement que nous _prévoyons_ de le faire, mais nous voulons _pouvoir_ le faire si le besoin s'en fait sentir.

@ayende D'accord, pareil avec nous.

De plus, si nous pouvions le faire au niveau de la dll, nous pourrions regrouper les dépendances à l'intérieur de nos assemblages afin qu'elles n'entrent pas en conflit avec les assemblages clients. C'est-à-dire qu'en choisissant une version de NewtonSoft.Json, vous la définissez actuellement pour tous les programmes, plugins et assemblages tiers dans le même dossier, mais si vous pouviez l'intégrer, les tiers ont de la flexibilité et augmentent la compatibilité des versions.

D'accord avec @ayende .

Merci à tous pour vos réponses ! Sur la base du nombre de personnes qui utiliseront du code natif ou qui auront besoin de charger des plugins, nous pensons que l'approche la plus compatible que nous pouvons gérer est le bon point de départ. Pour ce faire, nous adopterons une approche « emballer et extraire ».

Ce sera un outil qui intègre essentiellement tous les fichiers de l'application et de .NET en tant que ressources dans un exécutable d'extracteur. Lorsque l'exécutable s'exécute, il extrait tous ces fichiers dans un répertoire temporaire, puis s'exécute comme si l'application était publiée en tant qu'application à fichier non unique. Il ne commencera pas avec la compression, mais nous pourrions potentiellement l'ajouter à l'avenir si cela est justifié.

Le détail le plus délicat de ce plan est de savoir où extraire les fichiers. Nous devons tenir compte de plusieurs scénarios :

  • Premier lancement - l'application a juste besoin d'être extraite quelque part sur le disque
  • Lancements ultérieurs - pour éviter de payer le coût de l'extraction (probablement plusieurs secondes) à chaque lancement, il serait préférable que l'emplacement d'extraction soit déterministe et permette au deuxième lancement d'utiliser les fichiers extraits par le premier lancement.
  • Mise à niveau -- Si une nouvelle version de l'application est lancée, elle ne doit pas utiliser les fichiers extraits par une ancienne version. (L'inverse est également vrai ; les gens peuvent vouloir exécuter plusieurs versions côte à côte). Cela suggère que le chemin déterministe devrait être basé sur le contenu de l'application.
  • Désinstaller -- Les utilisateurs devraient pouvoir trouver les répertoires extraits pour les supprimer s'ils le souhaitent.
  • Tolérance aux pannes -- Si un premier lancement échoue après avoir partiellement extrait son contenu, un second lancement devrait refaire l'extraction
  • Exécution élevée - Les processus exécutés en tant qu'administrateur ne doivent s'exécuter qu'à partir d'emplacements accessibles en écriture par l'administrateur pour empêcher les processus à faible intégrité de les altérer.
  • Exécution non élevée - Les processus exécutés sans privilèges d'administrateur doivent être exécutés à partir d'emplacements accessibles en écriture par l'utilisateur

Je pense que nous pouvons rendre compte de tout cela en construisant un chemin qui intègre :

  1. Un répertoire de base bien connu (par exemple %LOCALAPPDATA%\dotnetApps sous Windows et les emplacements des profils utilisateur sur d'autres systèmes d'exploitation)
  2. Un sous-répertoire séparé pour les
  3. Identité de l'application (peut-être juste le nom de l'exe)
  4. Un identifiant de version. La version numérique est probablement utile, mais insuffisante car elle doit également incorporer des versions de dépendance exactes. Un guide ou un hachage par build peut être approprié.

Ensemble, cela pourrait ressembler à c:\users\username\AppData\Local\dotnetApps\elevated\MyCoolApp\1.0.0.0_abc123\MyCoolApp.dll
(Là où l'application s'appelle MyCoolApp, son numéro de version est 1.0.0.0 et son hachage/guid est abc123 et elle a été lancée en mode élevé).

Il y aura également du travail nécessaire pour intégrer des fichiers dans l'extracteur. Sous Windows, nous pouvons simplement utiliser des ressources natives, mais Linux et Mac peuvent nécessiter un travail personnalisé.

Enfin, cela peut également nécessiter des ajustements dans l'hôte (pour trouver les fichiers extraits) et des diagnostics (pour trouver le DAC ou d'autres fichiers).

CC @swaroop-sridhar @jeffschwMSFT @vitek-karas

J'ai l'impression que ce remède est pire que le mal. Si nous devons gérer des répertoires externes (différents selon les systèmes d'exploitation), mettre à jour, désinstaller, etc., cela va à l'encontre de ma raison de vouloir cette fonctionnalité en premier lieu (garder tout simple, portable, autonome et propre).

S'il doit absolument en être ainsi, pour mon projet, je préférerais de loin un seul exécutable principal et les fichiers décompressés dans un répertoire à côté de cet exécutable, ou éventuellement la possibilité de décider où va ce répertoire.

Ce n'est que moi, je suis curieux d'avoir des nouvelles d'autres aussi.

Je suis d'accord ici, l'utilisation d'un répertoire différent peut poser de nombreux problèmes passionnants - par exemple, vous placez un fichier de configuration à côté de l'exe et cet exe n'est pas récupéré car le "vrai" répertoire est ailleurs.
L'espace disque peut être un problème, ainsi que les verrous de fichiers aléatoires dus aux politiques d'accès, etc. pp.
J'aimerais utiliser cette fonctionnalité, mais pas si elle ajoute une multitude de modes d'échec impossibles à détecter auparavant.

D'accord avec @Kosyne - La solution initiale proposée semble simplement automatiser une sorte "d'installateur". Si c'était la limite du problème que nous essayons de résoudre avec un seul exécutable, je pense que nous aurions tous simplement effectué cette automatisation nous-mêmes.

L'objectif principal de la proposition d'exécution unique devrait être de pouvoir exécuter un exécutable sur un système non géré. Qui sait s'il a même un accès en écriture à n'importe quel répertoire "d'installation" de destination choisi ? Il ne devrait certainement pas non plus laisser d'artefacts après le lancement (pas par défaut).

En tant que petite modification de la proposition existante pour satisfaire ce qui précède : ne pourrions-nous pas décompresser en mémoire et exécuter à partir de là ?

D'accord avec le reste des commentaires. Décompresser vers un autre emplacement est quelque chose qui est _déjà_ disponible.
Nous pouvons avoir un zip auto-extractible qui exécutera les valeurs extraites assez facilement. Cela ne répond pas à beaucoup des préoccupations auxquelles cela est censé répondre et n'est qu'un autre nom pour l'installation.

L'emplacement du fichier est important. Par exemple, dans notre cas, cela signifierait :

  • Trouver le fichier de configuration (que nous générons à la volée s'il n'est pas là et que l'utilisateur le personnalise)
  • Recherche / création de fichiers de données, généralement relatifs à l'exe source.
  • Le PID/nom du processus doit correspondre, pour assurer une surveillance/assistance appropriée.

Un de nos utilisateurs a besoin d'exécuter notre logiciel à partir d'un DVD, comment cela fonctionne-t-il, sur un système qui n'a peut-être pas réellement de disque dur sur lequel s'exécuter.

Je suis d'accord qu'il vaudrait mieux tout faire en mémoire. Et la préoccupation concernant le temps de démarrage n'est pas si grande, je serais bien de payer cela pour chaque redémarrage, ou de faire manuellement une étape pour atténuer cela si nécessaire.

Un autre problème ici est la taille réelle. S'il ne s'agit que (effectivement) d'un programme d'installation, cela signifie que nous parlons de tailles de fichiers pour une application raisonnable dans les 100 Mo, non ?

Il semble que la construction de la solution proposée ne nécessite pas (beaucoup, le cas échéant) de modifications du CLR. Les utilisateurs peuvent déjà créer une solution comme celle-là. Il est inutile d'ajouter ceci à CoreCLR. Surtout, puisque le cas d'utilisation pour cela est assez étroit et spécifique.

@GSPP Cela semble être fondamentalement quelque chose que je peux faire aujourd'hui avec 7z-Extra , je suis d'accord que si tel est le cas, il serait préférable de ne pas l'avoir du tout.

Désolé, je suis en retard à cette fête, je suis arrivé ici après avoir suivi un lien posté dans un ticket en double que je suivais.
Après avoir lu les derniers commentaires ici, je suis désolé de voir que vous envisagez d'emballer et d'extraire. Cela semble exagéré, pourquoi ne pas commencer par la possibilité de déployer des SFA pour les applications console de base ? Il me semble qu'il devrait être possible de créer une application de console rudimentaire avec un réseau, des E/S et des dépendances externes (nuget, etc.) qui se trouvent dans un seul fichier.
Je suppose que ce que j'essaie de dire, c'est qu'au lieu de rassembler les exigences de tout le monde, rassemblez les exigences de personne et commencez petit avec une première itération qui a du sens pour tout le monde et donne des résultats rapidement.

Cela semble être fondamentalement quelque chose que je peux faire aujourd'hui avec 7z-Extra

Vous avez raison de dire qu'il existe aujourd'hui un certain nombre de solutions indépendantes de l'environnement de programmation pour résoudre ce problème. Un autre exemple parmi tant d'autres : https://www.boxedapp.com/exe_bundle.html

La valeur ajoutée ici serait l'intégration dans l'outil dotnet afin que même les utilisateurs non experts puissent le faire facilement. Les utilisateurs experts peuvent le faire aujourd'hui en assemblant des outils existants comme vous l'avez souligné.

Personnellement, je suis d'accord avec vous qu'il n'est pas clair que nous fassions ici le bon choix. Nous avons eu beaucoup de discussions à ce sujet au sein de l'équipe de base.

Mettre un stagiaire dessus et sortir avec un outil global (qui est recommandé, mais pas pris en charge) ferait tout aussi bien, et peut être assez facile à installer également.

Effectivement, on parle de dotnet publish-single-file et cela ferait tout ce qu'il faut dans les coulisses.

Je ne vois rien qui soit réellement requis par le framework ou le runtime pour prendre en charge ce scénario, et en en faisant quelque chose qui est explicitement en dehors du framework, vous allez donner aux utilisateurs beaucoup plus de liberté sur la façon de modifier cela.
Pas "besoin" d'obtenir un PR (avec toute la cérémonie associée, le pacte rétrograde, la sécurité, etc.) que vous obtiendriez si vous souhaitez modifier le cadre.
Vous venez de bifurquer un projet secondaire commun et de l'utiliser.

Notez que même si j'aimerais cette fonctionnalité, je préférerais ne pas avoir quelque chose à l'intérieur (ce qui signifie qu'il sera _toujours_ à l'intérieur) qui puisse être fait aussi bien de l'extérieur.

Je souhaite poser une question de niveau supérieur : quelle est la principale motivation des clients souhaitant une distribution en fichier unique ?
Est-ce principalement :

  1. Emballage? Si oui, que la solution soit une boîte de réception ou un outil tiers, quelles sont les caractéristiques les plus importantes ?
    a) Temps de démarrage (au-delà de la première manche)
    b) Capacité à fonctionner dans des environnements non inscriptibles
    c) Ne pas laisser de fichiers après la course
    d) Ne pas avoir à exécuter un programme d'installation
    2) Performances ?
    a) Rapidité (liaison statique du code natif, évitant plusieurs chargements de bibliothèques, optimisations inter-modules, etc.)
    b) Taille du code (nécessite un seul certificat, secouage d'arbres, etc.)
    3) D'autres ?

Je suis un peu inquiet que cette fonctionnalité soit lue par certains comme n'étant pas si importante, ou du moins ne soit pas un bon objectif à inclure dans l'ensemble de fonctionnalités de base ici. Je voudrais juste répéter que je pense que ce serait extrêmement puissant pour toute application qui agit comme un service ou un sous-module d'une application plus large. Celui dont vous, l'auteur, n'êtes peut-être même pas le développeur. Je ne veux pas avoir à transmettre des exigences de dépendance qui ne peuvent être résolues qu'avec des installations (automatiques ou autres), ou des artefacts post-exécution sur le disque qui pourraient nécessiter une élévation de sécurité supplémentaire par l'utilisateur, etc.
À l'heure actuelle, .NET n'est tout simplement pas un bon choix pour ce problème de niche. Mais cela pourrait être (et devrait être IMO).

L'exécutable compilé doit :

  • Empaqueter toutes les dépendances pertinentes
  • Ne pas avoir d'artefacts d'exécution (pas d'écriture sur disque)

Re @swaroop-sridhar J'ose dire que chaque application aura son propre ordre unique de besoins en performances et j'imagine donc que la meilleure approche après avoir abordé la solution de base est de choisir le fruit à portée de main et de partir de là.

@swaroop-sridhar Pour moi, il s'agit d'emballage et de facilité d'utilisation pour l'utilisateur final.
Pas besoin de s'occuper de l'installation de choses à l'échelle du système, il suffit de cliquer et d'exécuter.

Ceci est important car nous permettons à notre logiciel d'être intégré, et un seul addon de fichier est beaucoup plus facile à gérer.

@strich Le point sur l'intégration est bon. Nous sommes couramment utilisés comme composant dans une architecture de microservices, et la réduction des frais généraux de déploiement facilitera cela.

Le problème n'est pas quelconque ou non, c'est une caractéristique importante. Le problème est quelle que soit la solution proposée (essentiellement compresser les choses, à ce stade) doit être _dans le noyau_.
Les choses qui sont dans le noyau ont une norme beaucoup plus élevée pour les changements. L'avoir comme outil externe serait préférable, car il est plus facile à modifier et à étendre.

Pour être honnête, je préférerais de loin voir une meilleure option. Par exemple, il est possible de charger des dll depuis la mémoire, au lieu de fichiers (nécessite un peu de travail, mais possible).
Si cela se produit, vous pouvez exécuter l'intégralité de la chose uniquement à partir de la mémoire, le déballage étant effectué en mémoire pure et sans accès au disque.

C'est quelque chose qui devrait aller dans le noyau, car cela nécessitera très probablement des modifications du runtime pour permettre cela.
Et ce serait précieux en soi. Et pas quelque chose que nous pouvons faire actuellement.

Un bon exemple est donc de regarder l'expérience des outils Go comme Consul de Hashicorp. Un seul fichier exe que vous pouvez déposer sur n'importe quelle machine et exécuter. Pas d'installateurs, pas de copie de dossiers, pas de recherche de fichiers de configuration dans des listes de centaines de fichiers, juste une expérience utilisateur vraiment agréable.

Pour nous, je ne suis pas sûr que l'approche en mémoire fonctionnerait car nous aimerions également que cela fonctionne également pour les dll de plugin (donc supprimer un plugin serait également un fichier unique plutôt que toutes ses dépendances), mais tout progrès serait sois sage. Nous avons examiné Fody.Costura et cela fonctionne bien pour certaines choses, mais nous avons eu des problèmes avec .NET Core pour cela.

Donc, un bon exemple est de regarder l'expérience des outils Go comme Consul de Hashicorp

Eh, pour des outils comme consul la solution idéale serait corert, pas cette improvisation auto-extractible.

@mikedn Pourquoi ça? Je ne vois pas ce que la compilation AOT ou JIT a à voir avec la méthode de déploiement ?

Je veux appuyer les mots de @strich , les déploiements de fichiers uniques seraient une bouffée d'air frais pour les déploiements d'architecture de microservices, ainsi que pour toute application de console qui est - ou du moins commence sa vie comme - un petit outil avec ligne de commande commutateurs.

Pourquoi ça? Je ne vois pas ce que la compilation AOT ou JIT a à voir avec la méthode de déploiement ?

Parce qu'il vous donne exactement ce que vous voulez - un seul fichier exe que vous pouvez déposer sur n'importe quelle machine (enfin, n'importe quelle machine ayant un système d'exploitation approprié, c'est un fichier natif après tout) et exécuter. Il a également tendance à utiliser moins de ressources, ce qui est une bonne chose pour des agents comme le consul. C'est à peu près l'équivalent de ce que Go vous offre, plus qu'une solution d'auto-extraction.

@mikedn je suppose, mais

1) Il n'existe pas encore vraiment sous forme de production (pour autant que je sache) !
2) Nous utilisons beaucoup de fonctionnalités dynamiques (génération IL, réflexion arbitraire)
3) On souhaite tout de même pouvoir ajouter des plugins (encore une fois idéalement compactés)

Vu que ce numéro consistait à demander aux gens ce qu'ils veulent, nous ne donnons que notre avis ! Nous ne voulons pas vraiment avoir à passer à un modèle d'exécution différent juste pour obtenir cet avantage. Pour moi, ce sont des préoccupations orthogonales

Je ne vois pas ce que la compilation AOT ou JIT a à voir avec la méthode de déploiement ?

Sans JIT, il est plus facile d'obtenir des choses comme l'histoire de débogage assez bonnes. La partie JIT rend le problème plus difficile, c'est pourquoi vous ne le trouverez pas dans Go. C'est de l'ingénierie, donc soit vous envoyez plus d'ingénieurs au problème le plus difficile et vous vivez avec la nouvelle complexité, soit vous l'étendez ailleurs. L'auto-extraction consiste à réduire la portée car le nombre d'ingénieurs possédant les compétences nécessaires est limité.

Les personnes ayant des projets qui ressemblent davantage à des projets Go (pas d'exigences JIT) pourraient être assez satisfaites de CoreRT, si elles acceptent l'étiquette "expérimental". Il est assez facile d'essayer ces jours-ci. Il utilise le même ramasse-miettes, générateur de code, CoreFX et la plupart de CoreLib que le CoreCLR complet, et produit des exécutables de petite taille (mégaoctets à un chiffre) qui sont autonomes.

Il n'existe pas encore vraiment sous forme de production (pour autant que je sache) !

Oui, mon commentaire s'adressait surtout aux personnes atteintes de SEP : grin:. Ils ont tous ces projets / idées parallèles, liés et en cours (corert, illinker) et maintenant ils en ajoutent un de plus, ce truc d'auto-extraction qui, comme beaucoup l'ont déjà souligné, c'est un peu un "meh, on peut faire ça nous-mêmes" genre de chose. Et cela présente également des inconvénients, tels que l'extraction de fichiers dans un répertoire "caché".

Nous utilisons beaucoup de fonctionnalités dynamiques (génération IL, réflexion arbitraire)

C'est quelque chose que la communauté dans son ensemble pourrait vouloir réfléchir à deux fois. Bien sûr, il est utile de pouvoir le faire, mais cela entre en conflit avec d'autres désirs, comme le déploiement d'un seul fichier. Vous pouvez toujours obtenir un déploiement de fichier unique, mais cela a généralement un coût - un fichier assez volumineux. Si vous êtes d'accord avec cela, alors c'est parfaitement bien. Mais d'après mon expérience, plus le fichier est volumineux, moins l'aspect "fichier unique" devient utile.

@MichalStrehovsky bien sûr, il existe différentes options. Cependant, pour nous, nous ne pouvons pas utiliser expérimental (convaincre qu'il était temps de passer à .NET Core était déjà assez difficile) et je ne pense pas que l'extraction dans un dossier temporaire fonctionnera dans notre cas non plus. Cependant, dans le pire des cas, nous continuons comme nous sommes et n'utilisons pas cette fonctionnalité.

C'est quelque chose que nous aimerions bien si cela se passait comme nous le voudrions :)

@mikedn Je suis d'accord. Plusieurs solutions parallèles sont encore plus déroutantes. Je pense que notre solution idéale serait une sorte d'approche super ILLinker/weaver, mais je suis heureux de laisser cela se dérouler et de voir où nous nous retrouvons.

Je suis vraiment très enthousiasmé par cette fonctionnalité, mais TBH, je ne suis pas non plus enthousiasmé par la proposition initiale que vous avez publiée @morganbr. Mes réponses à la liste de questions que vous avez posées sont similaires à ce que d'autres ont posté (donc je pense qu'il existe un ensemble commun de fonctionnalités souhaitées), mais à mon humble avis, la solution proposée de "décompresser sur disque" n'est pas du tout ce que j'espère voir mis en œuvre et, comme d'autres l'ont dit, serait presque pire que la « maladie ». @jkotas

Je suis d'accord avec @strich et @ayende
L'exécutable compilé doit :
Empaqueter toutes les dépendances pertinentes
Ne pas avoir d'artefacts d'exécution (pas d'écriture sur disque)

Le chargement de fichiers .dll à partir de la mémoire au lieu du disque n'est peut-être pas facile, mais c'est le genre de capacités que l'OMI vaudrait l'expertise approfondie des développeurs de bas niveau MSFT (puis en tirant parti de CoreClr) par rapport à la proposition ci-dessus qui pourrait simplement être implémentée comme un outil externe (et l'a déjà, voir https://github.com/dgiagio/warp). Si cela était réalisé, je me demande quelle différence de temps il y aurait entre la première exécution et les suivantes ? Pour inspiration/exemple, je pense que Linux 3.17+ a memfd_create qui peut être utilisé par dlopen.

Sur un autre sujet, je me demande si l'obligation de prendre en charge les plugins sur-indexe la proposition de conception ? Cela vaudrait-il la peine de rendre cette fonctionnalité opt-in, de sorte que seules les personnes qui ont besoin de cette capacité encourent les pénalités potentielles (absence de secousses d'arbres, etc.) et que tous les autres (majorité significative ?) Bénéficiaient d'une taille déployable réduite, d'avantages de performances (?)

En prenant du recul @swaroop-sridhar @MichalStrehovsky , je peux voir deux grands cas d'utilisation qui pourraient avoir des objectifs/désirs suffisamment différents pour qu'il soit difficile de satisfaire tout le monde avec une seule solution :

  • L'outillage CLI doit idéalement être exécuté rapidement à chaque fois, petit distribuable ; peut-être mieux adapté à CoreRT ?
  • microservice peut probablement tolérer une première exécution plus longue (idéalement <1s), une plus grande distribution, en échange de fonctionnalités plus riches comme JIT et des fonctionnalités de code dynamique.

J'espère que ce braindump a du sens, je n'essaie pas d'être un imbécile, mais juste de donner mon avis car je suis très intéressé par ce sujet. Merci pour tout votre travail acharné et pour solliciter la contribution de la communauté ! :)

À propos des plugins.
Fondamentalement, la seule chose que je voudrais, c'est _ne pas_ être bloqué sur les appels Assembly.LoadFrom ou LoadLibrary .
Je n'ai besoin de rien d'autre et je peux faire le reste moi-même.

@ayende Pouvez-vous s'il vous plaît expliquer un peu plus en détail ce que vous entendez par "être bloqué sur LoadFrom et autres" ?

Par exemple, certaines des suggestions pour cela incluaient CoreRT, ce qui signifiait que nous ne pourrions (probablement) pas simplement charger une dll gérée.
Mais tant que je peux fournir un chemin vers une dll gérée et obtenir un assembly ou appeler LoadLibrary sur une dll native, cela me convient comme mécanisme de plug-in.

Je dis cela pour qu'il soit clair que les scénarios de plugins ne sont pas quelque chose qui devrait être _considéré_, mais plutôt quelque chose qui ne devrait pas être _bloqué_.

J'ai passé du temps à fouiller dans le code et à première vue, il semble qu'il devrait être _possible_ de (parler de Windows uniquement pour simplifier les choses):

  • Emballez l'intégralité de CoreCLR dans un exec (disons qu'il s'agit d'une ressource intégrée ou quelque chose comme ça).
  • Énumérez les dll natives, appelez quelque chose comme MemoryModule (https://github.com/fancycode/MemoryModule) pour les charger en mémoire
  • Appelez le runtime et chargez un assembly à partir de la mémoire.

Je vais supposer que ce n'est _pas_ aussi simple que cela. Par exemple, ICLRRuntimeHost2::ExecuteAssembly ne fournit aucun moyen de lui donner un tampon, seulement un fichier sur le disque.
Cela en fait le premier (de ce que je suis sûr qu'il y en aura beaucoup) à le faire fonctionner.

Je suis à peu près sûr qu'il y a beaucoup de code qui pourrait faire référence à des éléments connexes en tant que fichiers susceptibles d'échouer, mais c'est le genre de choses que je veux dire quand je dis que je veux un seul fichier exec et pourquoi ce genre de la solution doit être effectuée dans le CoreCLR et non en externe (comme dans l'exemple zip).

appeler quelque chose comme MemoryModule

Les fichiers binaires chargés à l'aide de MemoryModule ne peuvent pas être diagnostiqués (par exemple, aucun des débogueurs, profileurs, etc. ne fonctionnera dessus), et MemoryModule ignore toutes les mesures de sécurité intégrées au système d'exploitation (par exemple, les antivirus, etc.). Ce n'est pas quelque chose que nous pourrions jamais proposer en tant que solution prise en charge.

Je vais supposer que ce n'est pas aussi simple que cela.

À droite, de nouvelles API seraient nécessaires (à la fois gérées et non gérées) pour prendre en charge l'exécution à partir d'un ensemble de fichiers unique non étendu. Les programmes et bibliothèques existants ne "fonctionneraient pas simplement".

Serait-il raisonnable de demander que l'interface d'analyse anti-malware soit
implémenté par les ingénieurs Windows sur MemoryModule comme il l'a été récemment pour
tous les assemblys .net, y compris ceux chargés à partir de mem ?

https://twitter.com/WDSecurity/status/1047380732031762432?s=19

EDIT: Hmm MemoryModule ressemblait à quelque chose d'intégré au système d'exploitation pour charger des modules natifs, mais apparemment ce n'est pas le cas, c'est probablement une raison suffisante pour ignorer ma suggestion ci-dessus

Le mercredi 5 décembre 2018, 01h46, Jan Kotas [email protected] a écrit :

appeler quelque chose comme MemoryModule

Les binaires chargés à l'aide de MemoryModule ne peuvent pas être diagnostiqués (par exemple, aucun des
les débogueurs habituels, les profileurs, etc.) fonctionneront dessus, et MemoryModule
ignore toutes les mesures de sécurité intégrées du système d'exploitation (par exemple, les antivirus, etc.). Ce n'est pas
quelque chose que nous pourrions jamais expédier en tant que solution prise en charge.

Je vais supposer que ce n'est pas aussi simple que cela.

À droite, de nouvelles API seraient nécessaires (à la fois gérées et non gérées) pour
prend en charge l'exécution à partir d'un ensemble de fichiers unique non étendu. L'existant
les programmes et les bibliothèques ne "fonctionneraient pas simplement".


Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/dotnet/coreclr/issues/20287#issuecomment-444314969 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AEBfudvVHxpbeKa-L_vTQjbnNZZsn6Meks5u1xdlgaJpZM4XK-X_
.

Merci pour tous les commentaires.
Nous publierons sous peu un plan mis à jour pour prendre en charge la distribution de fichiers uniques.

@NinoFloris voir dotnet/coreclr#21370

Je me rends compte que je suis en retard pour cette discussion, donc mes excuses si cela ne vous aide pas.

Pour réitérer ce que @mikedn disait, il peut être déroutant d'avoir toutes ces solutions parallèles, et cela soulève la question de savoir où se concentrera MS à l'avenir. Le fait que le brillant travail effectué sur CoreRT soit toujours qualifié d'expérimental sans feuille de route officielle et avec des fonctionnalités similaires mises en œuvre dans CoreCLR (CPAOT, désormais publication de fichier unique) rend difficile la prise de décisions commerciales basées sur la technologie. Je ne voudrais plus me tromper de cheval (Silverlight...).

Pourquoi ne pas s'en tenir au brillant environnement d'exécution de CoreRT et concentrer le travail sur l'intégration d'un JIT (et l'expansion du travail d'interpréteur jusqu'à ce qu'il soit prêt) dans CoreRT pour ceux qui veulent des capacités de framework complètes tout en ayant un code natif construit pour eux ? Ne serait-il pas possible, dans le cas de vouloir des capacités JIT, de conserver les métadonnées et JIT à l'intérieur d'un exécutable CoreRT compilé en mode natif ?
Ne serait-ce pas le meilleur des mondes ? Par exemple. vous auriez les plus petits exécutables, le temps de démarrage le plus rapide, les limitations du code AOT dans CoreRT pourraient être étendues en mettant en place un JIT et en conservant les métadonnées et le code IL pour ceux qui souhaitent conserver toutes les fonctionnalités du framework.
À l'OMI, l'accent devrait être mis sur la "meilleure solution possible" plutôt que sur une fonctionnalité à court terme qui pourrait détourner l'attention des objectifs à long terme.

Peut-être que je me trompe, mais je pense que la publication d'un seul fichier dans le cadre de CoreCLR détournerait encore plus les clients de CoreRT, ce qui, dans de nombreux cas, serait une solution potentiellement meilleure pour eux. Par exemple. si cela est marqué comme "maintenant vous pouvez publier votre code .NET en un seul fichier" mais qu'il crée des fichiers énormes, souffrira des performances de démarrage, etc., alors je peux voir les gens commencer à se plaindre de ce "runtime .NET gonflé" encore une fois . Alors que .NET a déjà une solution brillante pour exactement cela dans CoreRT, tout en manquant du support officiel / de l'engagement officiel du produit pour aller jusqu'au bout.

Peut-être que ma préoccupation est principalement que j'aimerais voir moins de produits parallèles (en citant à nouveau @mikedn) et davantage d'accent sur l'engagement profond, l'extension et le soutien de ceux qui sont ici (y compris le partage des feuilles de route).

produits moins parallèles

Nous n'avons qu'un seul produit : .NET Core. CoreRT n'est pas un produit séparé et ne le sera jamais. Il s'agit d'ajouter des options à ce seul produit. Voici quelques exemples d'options que nous avons aujourd'hui : poste de travail GC et serveur GC ; publication d'applications autonomes par rapport à la publication d'applications dépendantes du framework.

@jkotas Je comprends et je suis tout à fait d'accord que l'ajout d'options est généralement génial. Si vous remplacez mon utilisation du mot « produits » par « options/solutions », même si je maintiens ma préoccupation de ne pas savoir pleinement si l'engagement de notre produit envers CoreRT en tant qu'option/solution à l'intérieur du produit global .NET Core est quelque chose que nous peut parier en toute sécurité sur être soutenu dans de nombreuses années à venir. Imaginez ce que ce serait si les API effectuaient des changements de rupture imprévisibles au fil du temps et étaient soudainement obsolètes sans que vous sachiez si vous pouvez ou non faire confiance à une API pour y rester. Pour une entité non MS, les outils/options qui font partie du produit ont la même sensation. Nous dépendons de plusieurs fonctionnalités de CoreRT que nous ne serions pas en mesure de faire (du moins actuellement) avec CoreCLR (l'une d'entre elles est la capacité de protéger nos exécutables avec PACE et de supprimer de nombreuses métadonnées, IL, etc., liaison statique facile, compréhension plus facile de la plate-forme sous-jacente, perspective de construire l'obfuscation directement dans le compilateur, etc.). Fondamentalement, j'ai l'impression que votre travail, celui de Michal et d'autres sur CoreRT devrait être priorisé car il IMO est l'une des meilleures choses qui se soit produite dans l'écosystème .NET depuis sa conception. Chaque fois qu'il est question d'un nouvel outil/option qui pourrait alors être considéré en interne comme étant en concurrence avec CoreRT au lieu de l'option CoreRT à compléter et à étendre, cela me semble être une mauvaise allocation des ressources. Désolé, je ne voulais pas faire traîner la discussion, je voulais juste m'assurer que vous compreniez à quel point le travail de CoreRT est apprécié et que certains d'entre nous ici pensent que cela devrait être l'avenir de la plate-forme.
Je m'abstiendrai de polluer davantage cette discussion. En souhaitant tout le meilleur pour les équipes et en attendant avec impatience tout ce que vous proposerez, je suis sûr que ce sera génial.

@christianscheuer Vos commentaires sur ce problème et sur d'autres problèmes liés à CoreRT ont été très précieux. Vous ne polluez pas du tout cette discussion.

on parle d'un nouvel outil/option qui pourrait ensuite être considéré en interne comme en concurrence avec CoreRT

Au sein de l'équipe de base, nous avons des discussions sur un certain nombre d'options différentes, ambitieuses ou plus folles. Je ne considère pas le "unzip to disk" comme un concurrent important avec CoreRT full AOT. Chacun cible un segment différent d'utilisateurs/d'applications .NET.

Notre équipe de gestion de produits, qui compile les données de nombreux canaux différents (y compris les problèmes de github ou les conversations en face à face avec les clients), a suggéré que le meilleur rapport qualité-prix est une solution comme celle proposée ici. Nous validons toujours que nous avons toutes les données sur ce droit et qu'il aura le résultat souhaité.

Je ne peux pas vous promettre quand la technologie CoreRT sera livrée dans le cadre du produit .NET Core pris en charge à ce stade. Je sais qu'il a des atouts uniques et je suis sûr que nous allons proposer une solution prise en charge comme celle-ci pour le segment des utilisateurs .NET importants qui en bénéficieront éventuellement.

La distribution de fichier unique a du sens si :

  • Cela n'a pas d'impact sur le temps de démarrage (sinon, seules les plus petites applications pourront l'utiliser)
  • Il agit comme un VFS (Virtual File System) Vous permet d'accéder aux assemblages et aux ressources comme s'ils provenaient du disque, du dossier de l'application).
  • N'affecte pas la "patchabilité" de l'application. IE : Microsoft devrait être en mesure de corriger les assemblages critiques même s'ils sont intégrés en fournissant des remplacements ailleurs, au niveau du système.

Les assemblys en tant que ressources intégrées, extraites et copiées dans un dossier temporaire ne sont pas une solution nécessaire de Microsoft. Il peut être facilement mis en œuvre par tout client qui en a besoin.

Une "véritable" solution de fichier unique est nécessaire et apporterait beaucoup de valeur.

@jkotas vos commentaires sonnent juste pour moi. J'aurais du mal à convaincre les développeurs .NET de mon entreprise (LOB/backoffice/intégrations) de passer à CoreRT car ce serait un saut trop important pour eux (surtout compte tenu du label Experimental), mais ils peuvent voir la valeur dans un solution relativement simple (à utiliser) pour Core comme ce fil en parle. Merci

@ popcatalin81 En fait, je serais fortement en désaccord avec vos points ici.

Le temps de démarrage n'est pas significatif pour de nombreuses applications. Je me ferai un plaisir d'échanger une augmentation de 50 % à 100 % du temps de démarrage de tout service de longue durée dans le but de réduire la complexité opérationnelle de son déploiement.

Même si nous ajoutons 30 secondes au temps de démarrage d'un service, cela n'a pas vraiment de sens sur le long terme pour les services.
Pour les applications destinées aux utilisateurs, ce sera probablement un tueur, mais jusqu'à la sortie de la version 3.0, pratiquement toutes les applications CoreCLR sont soit des consoles, soit des services.

Non pas que CoreCLR dispose déjà d'un mode dans lequel vous pouvez regrouper le framework avec votre application (déploiement autonome).
Dans notre cas (RavenDB), nous _appuyons_ sur cela à plusieurs fins. Premièrement, la possibilité de choisir notre propre framework, quel que soit ce que nos utilisateurs utilisent. C'est un avantage _majeur_ pour nous, car cela signifie que nous n'avons pas besoin d'utiliser le framework installé globalement et que nous ne sommes donc pas liés à ce que l'administrateur a décidé d'être le framework (nous avions l'habitude de tenir compte du fait que nous serions exécutés sur .NET 4.0 parfois, même des années après la sortie de 4.5, par exemple, et c'était pénible).
Un autre aspect important est que nous pouvons exécuter avec _notre_ fork du framework. Ceci est très utile si nous rencontrons des choses que nous devons changer.

Dans ce cadre, nous nous approprions les cycles de patch et ne voulons pas que quelqu'un d'autre s'en mêle.

Je ne me soucie pas de VFS, mais je ne pense pas que cela soit nécessaire. Et je suis parfaitement d'accord pour devoir passer par une API dédiée / sauter à travers quelques cerceaux pour accéder aux assemblages/dlls/ressources natives qui sont regroupés de cette manière.

J'ai été pointé vers ce problème par @briacht pendant deux jours, donc je suis VRAIMENT en retard dans la discussion.
Je veux juste ajouter mes 2 cents !

D'abord mes réponses aux questions de @morganbr :

  1. Application Windows, mixant WPF et WinForms.
  2. Actuellement non
  3. Oui, en utilisant Assembly.Load dans différentes variantes
  4. Oui
  5. Cela dépend s'il s'agit d'une pénalité qui est à chaque démarrage. Oui si c'est quelques millisecondes, mais 5 secondes : non. S'il s'agit d'une seule fois, 5 secondes ne posent aucun problème.
  6. 50 Mo, c'est déjà assez volumineux par rapport à <2 Mo... mais si cela signifie que le runtime dotnet est inclus... OK. Peut-être que je peux fournir un téléchargement avec et sans.
  7. Le temps de publication n'a pas d'importance directe, mais il ne devrait pas déranger le fournisseur de CI en utilisant beaucoup de CPU pendant une longue période.
  8. OUI!

L'application dont j'en parle Greenshot, la version actuelle vise toujours .NET Framework 2.0 (oui vraiment) mais fonctionne sans problème sur la dernière version (bonne rétrocompatibilité) ! Le téléchargement, y compris le programme d'installation mais sans le .NET Framework, est d'environ 1,7 Mo. Le répertoire à partir duquel cela est démarré contient 1 .exe et 4 .dlls, il y a aussi 11 add-ons dans un sous-répertoire.

Je lisais les commentaires précédents, et beaucoup d'entre eux semblent vouloir quelque chose avec des fonctionnalités pour lesquelles j'utiliserais un installateur. Cela a un certain sens, car il n'existe actuellement aucune solution indépendante de la plate-forme.

Je discutais du sujet actuel avec certaines personnes de Microsoft en août, mon objectif principal était de tout lier pour réduire la taille et la complexité de l'application à déployer et également réduire le chargement de l'assemblage qui prend BEAUCOUP de temps au démarrage de ma candidature.

Avec la prochaine version de Greenshot, qui cible .NET Framework 4.7.1 et dotnet core 3.0 côte à côte, le téléchargement résultant pour dotnet core 3.0 compte actuellement environ 103 dll (!!!), un exe et 15 add-ons . La taille totale est d'environ 37 Mo et le plus gros fichier est MahApps.Metro.IconPacks.dll (12 Mo !!) qui contient la plupart des icônes que nous utilisons, ce qui représente probablement environ 4 % du fichier. La même chose avec beaucoup d'autres dll, je suppose qu'en général 50% de l'utilisation du code, c'est beaucoup !

Si l'utilisateur ne veut pas installer l'application, il suffit de télécharger un .zip et de trouver l'exécutable parmi environ 118 fichiers... pas vraiment une expérience agréable ! La taille est d'environ 35 Mo (17 x) plus grande, alors où est l'avantage pour l'utilisateur ?

Dans les mois qui ont précédé la création de dotnet core 3.0, j'utilisais Fody.Costura pour faire à peu près ce qui était décrit ici. Emballage pendant la construction et déballage au démarrage ! Il a même fait un seul exécutable sans extraire les fichiers possible en piratant un mais. Mais cela a également causé beaucoup de problèmes, donc ce n'est pas ma solution préférée.

J'espère une solution plus ou moins standard dont je peux dire : ça marche ™
Il est peut-être judicieux de définir une structure de dossiers standard, afin que nous puissions placer l'exécutable, le fichier readme, les fichiers de licence, etc. à la racine et avoir différents répertoires "connus" pour différents fichiers (dotnet core, dépendances, etc.). Cela pourrait faciliter le travail des outils et offrir des fonctionnalités où chacun peut décider de ce qu'il veut utiliser et de ce qu'il ne veut pas. Parfois, même le simple fait d'exécuter zip sur le répertoire résout certains problèmes.

Avoir une solution similaire à Fody.Costury est définitivement que je pourrais parfois utiliser pour simplifier le déploiement de Greenshot, mais cela ne réduit pas directement la taille et le temps de chargement. J'espère donc qu'il y aura du temps passé ici aussi!

@ayende S'il vous plaît, permettez-moi également d'être en désaccord avec vous :)

Bien qu'il s'agisse de vrais services, les applications Web et, en général, les applications de longue durée basées sur un serveur ne sont pas affectées par un coût de démarrage ponctuel, en même temps, ces applications ne sont pas celles qui bénéficient le plus du modèle de distribution de fichier unique. ( Raven est une exception, pas la norme ;) )

À mon avis, la distribution de fichiers uniques est principalement destinée aux applications et aux utilitaires destinés aux utilisateurs. Les utilisateurs qui téléchargeront, copieront, exécuteront de telles applications. Et dans un avenir proche, lorsque.Net Core 3.0 offrira un support pour les bibliothèques d'interface utilisateur, ce modèle de distribution deviendra assez courant. Cependant, je dois souligner que ce modèle ne conviendra à aucune application. Les principales applications utiliseront toujours un programme d'installation.

Maintenant, la question est, ce modèle d'assemblages intégrés copiés dans des dossiers temporaires, fonctionnera-t-il bien s'il devient très populaire ?

À mon avis, voici quelques problèmes potentiels pour le modèle actuel :

  • Des dizaines d'applications créent des milliers de fichiers temporaires avec des assemblages dupliqués. Il est possible de créer un gâchis ici. (Inaperçu par les utilisateurs, mais toujours un gâchis)
  • Pas de compression, pas de lien. Cela peut créer un inconvénient pour les petites applications utilitaires par rapport à FDD ou à la compression d'événements.
  • Cela pourrait en fait entraver les déploiements de serveurs au lieu de les rendre plus faciles, la raison étant : la configuration post-déploiement avec des remplacements de jetons. (Où allez-vous pour trouver le dossier temporaire pour écraser les fichiers de configuration ? Donnez-vous au service un accès en écriture à son propre dossier pour y créer le fichier de configuration ? C'est une sécurité non-non)

Je ne suis pas ici pour dire que ce modèle n'est pas optimal pour toutes sortes d'applications. Je l'ai implémenté avec succès et je l'ai utilisé moi-même dans le passé pour full.Net Framework, et c'est un bon choix pour certaines applications.

Je pense juste que l'implémentation optimale est la version où un éditeur de liens fusionne tous les assemblages en un seul fichier.

@ popcatalin81 Un monde avec un seul point de vue est un monde pauvre. Et je ne suis pas assez arrogant pour penser que mon modèle de déploiement est le seul qui existe.

Le cas que j'ai en tête est le scénario de téléchargement et de double-clic.
Pour le moment, nous devons décompresser et cliquer sur un script shell à exécuter, car aller dans un répertoire contenant des centaines de fichiers et trouver le bon est une corvée.

À propos de la configuration dans les fichiers temporaires. Je serais tout à fait contre. Les fichiers de configuration sont d'autres éléments visibles par l'utilisateur qui doivent résider juste à côté du fichier réel utilisé, et non cachés quelque part.
Nous avons déjà vu à quel point c'était mauvais avec les fichiers IsolatedStorage lorsque les utilisateurs en avaient besoin.

Dans les versions précédentes de RavenDB, nous avons fusionné beaucoup de choses pour avoir une disposition de répertoire plus simple et réduire le nombre de fichiers visibles, et cela a eu un impact sérieux sur la facilité d'utilisation de notre logiciel.

Cette fonctionnalité utilisera-t-elle ILMerge ? Si non, pourquoi pas ? Je voudrais me renseigner s'il y a un piège.

Je n'aime pas l'approche "pack and extract" proposée, en particulier la partie où l'on extrairait des fichiers sur le disque. C'est simple, mais il y a trop de problèmes. Tout devrait fonctionner "en mémoire" sans extraire sur le disque.

Je pense que cela devrait être quelque chose comme le compilateur natif corert ou Costura.Fody .

Facultativement, il devrait également tenter de réduire la taille binaire (supprimer les références inutilisées, IL mort).

Dans les mois qui ont précédé la création de dotnet core 3.0, j'utilisais Fody.Costura pour faire à peu près ce qui était décrit ici. Emballage pendant la construction et déballage au démarrage !

notez que costura ne "déballe pas sur le disque" (par défaut). il extrait (en mémoire) les assemblys embarqués des ressources et les charge via des octets

Merci pour le contexte @SimonCropp , nous explorons les deux options de décompression sur disque et de chargement à partir d'un flux. Couvrir le chargement d'un flux pour IL pur peut être possible dans notre première itération.

@jeffschwMSFT btw l'ensemble de fonctionnalités de fusion transparente d'assemblages (et de secouage d'arbre en option) est quelque chose que j'aimerais voir en tant que citoyen de première classe. costura est l'un de mes projets les plus populaires, mais aussi celui qui prend beaucoup de temps à soutenir. donc si / quand MS propose une alternative (même en version bêta), faites-le moi savoir et je passerai un peu de temps à l'examiner et à ajouter "il existe une alternative MS" au fichier readme costura et à la description du nuget

bien que peu probable, si vous avez besoin que je publie l'un des codes de costura sous une licence diff, faites-le moi savoir.

Merci @SimonCropp alors que nous commençons à intégrer le mono/illicker dans la chaîne d'outils .NET Core, nous accepterons votre offre de révision.

notez que costura ne "déballe pas sur le disque" (par défaut). il extrait (en mémoire) les assemblys embarqués des ressources et les charge via des octets

Mieux encore, je pense qu'il se charge à la demande à l'aide de l'événement AppDomain.AssemblyResolve , de sorte que le démarrage ne devrait pas être trop impacté car il ne chargera que les assemblages (en mémoire) chaque fois que nécessaire.

En retard à la conversation ici. Toutes mes excuses si cela a déjà été couvert.

Pouvons-nous supposer que l'artefact ici sera déterministe ? Par conséquent, la même construction produira toujours le même binaire ? Octet pour octet. Être capable de distribuer un binaire avec une somme de contrôle canonique serait également utile.

@morganbr Il y a beaucoup de lecture nécessaire ici. Serait-il possible d'enregistrer les décisions prises jusqu'à présent ?

@edblackburn, nous élaborons une conception mise à jour basée sur les commentaires. @swaroop-sridhar dirige la conception maintenant.

Cette fonctionnalité utilisera-t-elle ILMerge ? Si non, pourquoi pas ? Je voudrais me renseigner s'il y a un piège.

@simplejackcoder ILMerge combine l'IL de plusieurs assemblages en un seul, mais dans le processus, perd l'identité d'origine des assemblages fusionnés. Ainsi, des choses comme l'utilisation de la réflexion basée sur les noms d'assembly d'origine échoueront.

Le but de cet effort n'est pas de fusionner des assemblys, mais de les regrouper tout en conservant l'identité de l'assembly. De plus, nous devons empaqueter non seulement les assemblages, mais également les fichiers binaires natifs, les fichiers de configuration, éventuellement le runtime et toutes les autres dépendances requises par l'application.

Fusionner IL est une fonctionnalité utile pour les applications qui peuvent s'y adapter - c'est juste une fonctionnalité différente de ce problème.

Une revue de conception est publiée sur https://github.com/dotnet/designs/pull/52
Continuons désormais la discussion sur le PR.

J'ai quelques questions pour les personnes qui souhaitent utiliser le fichier unique. Vos réponses nous aideront à affiner nos options :

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)
  2. Votre application inclut-elle du code C++/natif (non-.NET) ?
  3. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?
  4. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?
  5. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?
  6. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?
  7. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?
  8. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?
  1. Notre cas d'utilisation dotnet/coreclr#1 est de loin les applications de console qui sont des utilitaires. Nous aimerions faire une publication pour Windows ou Linux et spécifier --single-file pour obtenir un exécutable. Pour Windows, nous nous attendrions à ce que cela se termine par .exe , pour Linux, ce serait un binaire exécutable.
  2. Pas généralement, mais cela pourrait via un package NuGet à notre insu
  3. Pas au départ, mais ce serait une excellente fonctionnalité future
  4. Oui
  5. Oui
  6. Tout ce qui fonctionne
  7. Oui, s'il optimise la taille résultante de l'exécutable. Idéalement, peut être un drapeau pour définir le niveau d'optimisation en utilisant --optimizing-level=5
  8. Oui, jusqu'à un certain point

Merci @BlitzkriegSoftware.
Je pense que la conception proposée ici couvre votre cas d'utilisation. S'il vous plaît jeter un oeil à la conception - nous apprécions vos commentaires.

J'ai quelques questions pour les personnes qui souhaitent utiliser le fichier unique. Vos réponses nous aideront à affiner nos options :

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)
  2. Votre application inclut-elle du code C++/natif (non-.NET) ?
  3. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?
  4. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?
  5. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?
  6. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?
  7. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?
  8. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?
  1. Application WPF .Core 3.0
  2. Peut-être dans un paquet de pépites
  3. Non
  4. Oui
  5. Oui pour 200-500ms max
  6. Pas important dès qu'il n'est pas 2 ou 3 fois plus grand que la taille du dossier de publication d'origine
  7. C'est pour la production donc pas vraiment important
  8. Oui mais avoir la possibilité de ne pas le faire peut être utile si le travail concerne une bibliothèque tierce

Les commentaires que vous avez reçus concernaient en grande partie le développement avant 2019, qui consiste généralement en des services Web, des applications de console et d'autres services lancés en arrière-plan. Mais maintenant, avec .net core 3.0, nous avons besoin de solutions pour les applications WPF et UI. Le .Net Framework 4.8 ne prendra pas en charge le .Net Standard 2.1 et nous avons besoin d'une solution pour remplacer ILMerge que nous utilisions jusqu'à présent pour les applications WPF car nous devons mettre à niveau nos applications du .net framework (dead framework) vers le .net core.

Un package auto-extractible n'est clairement pas une bonne solution comme expliqué dans d'autres commentaires précédents pour ce type de programmes.

  1. Principalement des applications CLI. Les petits services Windows et l'application WPF occasionnelle sont également intéressants. Pour les trucs Web, la distribution de fichiers uniques semble fondamentalement hors de propos. Pour cette raison, le reste est principalement orienté Windows ; notre intérêt pour Linux .NET Core concerne le Web.
  2. Parfois. Quand c'est le cas, c'est presque toujours pour les bibliothèques de compression. Si les trucs indigènes n'étaient pas emballés, ce ne serait pas la fin du monde. Une bonne solution pour les éléments purement gérés nécessitant le déploiement d'une dépendance native en tant que DLL distincte aurait toujours de la valeur.
  3. Non, pas dans les cas où nous nous soucions du fichier unique.
  4. Oui.
  5. 200 ms est à peu près la limite avant que les choses ne deviennent ennuyeuses pour qu'une CLI démarre. > 1 seconde et nous nous en tiendrons presque certainement à .NET Framework (ILMerge + ngen) ou regarderons d'autres langages qui compilent en un binaire natif avec tout runtime nécessaire lié de manière statique. Dans de nombreux cas, nous parlons de choses qui a été implémenté en C # parce qu'une application C # fusionnée et ngen-ed démarre en fait assez rapidement. Certaines de ces choses sont, du point de vue de la complexité, raisonnables à implémenter dans un langage de script, mais celles-ci ont tendance à avoir des coûts de démarrage importants, surtout si vous devez intégrer un tas de modules.
  6. Dépend. Plus de 10 Mo pour hello world seraient difficiles à vendre. Les énormes exécutables ont également tendance à avoir des coûts de démarrage non négligeables. Même si le système d'exploitation est théoriquement capable de démarrer l'exécution sans tout lire, du moins sous Windows, il y a presque toujours quelque chose qui veut d'abord obtenir un hachage à des fins de sécurité. En parlant de cela, ce déballage d'un tas de fichiers binaires pour temporiser va rendre les AV (Defender absolument inclus) fous, en termes d'utilisation des ressources, scannant frénétiquement si rien d'autre.
  7. Sûr. Je serais heureux d'ajouter une minute ou plus à une version de version si cela signifiait obtenir quelque chose d'une taille raisonnable et démarrer l'exécution rapidement.
  8. Absolument.

En relisant la proposition, elle ne traite d'aucun scénario que nous avons et que nous ne l'utiliserions pas. Il y a peut-être quelqu'un pour qui cela résout un problème, mais ce n'est pas nous.

Il semble qu'il y ait beaucoup de choses pertinentes pour des scénarios comme le nôtre en cours d'élaboration qui ne se sont tout simplement pas réunies dans une chaîne d'outils réellement utilisable/susceptible de continuer à fonctionner. C'est peut-être juste de l'ignorance de ma part, mais j'essaie de faire attention et ce n'est pas clair pour moi. Entre ILLink, Microsoft.Packaging.Tools.Trimming, CoreRT, .NET Native et tout ce qui se passe dans ce problème, il semble qu'il devrait y avoir un moyen d'obtenir un seul arbre secoué, un démarrage rapide (peut-être AoT ?), binaire de taille raisonnable hors de .NET Core (et non pour UWP).

  1. La distribution de fichiers uniques serait très utile pour les applications https://github.com/AvaloniaUI/Avalonia (Windows, Linux, MacOS) et WPF (Windows). Avoir un seul exe facilite les mises à jour automatiques par exemple, et en général, il est plus pratique d'avoir un seul fichier par rapport à une centaine de dll.
  2. Oui (dans le sens où il fait référence à des bibliothèques natives pré-construites telles que sqlite et skia)
  3. Non
  4. Oui
  5. 200ms est probablement bien. Avoir un temps de démarrage de 5 secondes pour une application graphique n'est pas bien.
  6. N'a pas vraiment d'importance
  7. Ça n'a pas vraiment d'importance. Nous pourrions créer un fichier unique uniquement pour les scénarios de production.
  8. Oui

S'il vous plaît, n'allez pas avec l'approche pack & extract. Nous pouvions déjà y parvenir en utilisant des outils d'archivage.

S'il vous plaît, n'allez pas avec l'approche pack & extract. Nous pouvions déjà y parvenir en utilisant des outils d'archivage.

Je ne peux pas être plus d'accord. Il existe déjà plusieurs outils disponibles qui le font.

Merci pour les commentaires @Safirion , @mattpwhite , @x2bool , @thegreatco.
À partir de ceux-ci, je vois une gamme de scénarios d'utilisation (applications console, WPF, applications GUI, etc.), mais les exigences générales semblent similaires :

  • Concentrez-vous sur le temps d'exécution/démarrage plutôt que sur le temps de construction.
  • Possibilité de reconstruire des applications pour d'autres versions/correctifs
  • Possibilité d'exécuter directement à partir du bundle (en particulier pour les composants entièrement gérés).

Je pense que ce sont les exigences auxquelles nous avons essayé de répondre dans le document de conception .

S'il vous plaît, n'allez pas avec l'approche pack & extract

Oui, comme expliqué dans ce document de mise en scène, l'objectif est de minimiser progressivement la dépendance à l'extraction de fichiers.

En relisant la proposition, elle ne traite d'aucun scénario que nous avons et que nous ne l'utiliserions pas.

@mattpwhite , voulait clarifier si vous pensez que cette solution ne fonctionne pas pour vous sur la base de :

  • L'approche basée sur l'auto-extraction proposée précédemment dans cet élément de travail, ou
  • La conception notée dans ce document
    Je crois que le dernier document tente de répondre au scénario que vous avez détaillé. Merci.

Il semble qu'il y ait beaucoup de choses pertinentes pour des scénarios comme le nôtre en cours d'élaboration qui ne se sont tout simplement pas réunies dans une chaîne d'outils réellement utilisable/susceptible de continuer à fonctionner.

@mattpwhite , des travaux sont en cours pour intégrer ILLink (tree-shaking), crossgen (génération de code natif prêt à l'emploi) et les aspects de regroupement de fichiers uniques dans msbuild/dotnet CLI de manière simplifiée pour .net core 3. Une fois cela est fait, l'utilisation de ces outils peut être accomplie facilement (ex: définir certaines propriétés msbuild).

Tous ces outils viennent avec des compromis. Par exemple, crossgen génère du code natif à l'avance, facilitant ainsi le démarrage, mais tend à augmenter la taille des binaires. En utilisant l'option de fichier unique, les applications peuvent être publiées dans un fichier unique, mais cela peut ralentir le démarrage, car les binaires natifs sont répandus sur le disque, etc.

@swaroop-sridhar, merci d'avoir pris le temps de répondre.

voulait clarifier si vous pensez que cette solution ne fonctionne pas pour votre basé sur

Il semblait que l'extraction était toujours dans l'image pour tout ce qui était autonome, et le statut de crossgen (ou toute autre chose à réduire dans le temps JIT au lancement) n'était pas clair pour moi. La lecture du document de mise en scène auquel la conception actuelle est liée semblait donner l'impression que ce qui rendrait cela plus intéressant pour nous était plus avancé. Compte tenu de cela, je pensais que nous continuerions à utiliser le .NET Framework pour ces niches pendant un certain temps encore. J'ai peut-être mal compris.

Tous ces outils viennent avec des compromis. Par exemple, crossgen génère du code natif à l'avance, facilitant ainsi le démarrage, mais tend à augmenter la taille des binaires.

Oui, compris que certaines d'entre elles sont des épées à double tranchant. Avec la façon dont le JIT a traditionnellement fonctionné, ngen a toujours été une victoire pour les applications CLI/GUI. Il est possible qu'une combinaison de compilation à plusieurs niveaux et le fait que le chargement du runtime lui-même ne soit pas nécessairement amorti par de nombreux autres processus .NET Framework s'exécutant sur le même boîtier rendent cela moins clair sur Core.

@swaroop-sridhar la grande préoccupation que j'ai avec la proposition actuellement acceptée est cette étape

Les 216 fichiers restants seront extraits sur le disque au démarrage.

Mis à part le fait que "Hello World" semble nécessiter 216 fichiers pour s'exécuter, les extraire sur le disque à un endroit rend difficile la suppression d'une simple application de ligne de commande. Lorsque les utilisateurs suppriment un outil qui ne provient pas d'un programme d'installation, ils ne s'attendent pas à devoir rechercher d'autres fichiers pour le supprimer complètement.

À mon humble avis, nous devrions viser une expérience de publication similaire à celle de golang. Bien qu'il faudrait crossgen pour correspondre pleinement à l'expérience golang (et on pourrait dire qu'une correspondance 1: 1 n'est pas une _bonne_ chose, car nous perdons le JIT et la compilation à plusieurs niveaux), un une bonne portion peut être obtenue sans elle. J'ai utilisé de nombreux outils au fil des ans pour obtenir une expérience similaire, et le plus efficace était les ressources intégrées avec un crochet sur le chargeur d'assemblage (ILMerge était capricieux et Costura.Fody n'existait pas encore). Ce qui est décrit dans la proposition ne reproduit même pas entièrement cette fonctionnalité. .NET Core a un avenir très prometteur, mais son utilisation pour développer des outils de ligne de commande est limitée tant que nous devons transporter des centaines de dépendances ou les recracher quelque part sur le disque avec du code d'amorçage à la main.

Mon cas d'utilisation dotnet/coreclr#1 est les utilitaires de ligne de commande, un fichier, aucune extraction serait ma préférence. Mais je soulignerais que donner un choix dans le cadre des commutateurs de commande pour tout-en-un contre tout-en-un-auto-extractible. Dans le cas de l'auto-extraction, il doit inclure un undo qui nettoie les fichiers décompressés. Dans le premier cas, la suppression de l'utilitaire signifie la suppression d'un fichier qui le rend apte à résider dans un dossier d'utilitaires généraux, tandis que, comme dans le 2ème cas, l'installation doit avoir son propre dossier afin de faciliter le nettoyage et d'éviter scénarios où la désinstallation supprime les fichiers partagés. Juste quelques pensées. Comme je l'ai dit, l'utilitaire de fichier unique (aucune installation nécessaire) est mon principal cas d'utilisation, car je crée fréquemment des utilitaires pour des projets (en tant que forgeron d'outils). Mais je peux voir un cas d'utilisation pour les deux scénarios. Mais ils sont différents .

J'ai quelques questions pour les personnes qui souhaitent utiliser le fichier unique. Vos réponses nous aideront à affiner nos options :

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)
  2. Votre application inclut-elle du code C++/natif (non-.NET) ?
  3. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?
  4. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?
  5. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?
  6. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?
  7. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?
  8. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?
  1. CLI (Windows, Linux, MacOS), WPF et WinForms.
  2. Parfois.
  3. Oui, plusieurs fois et je pense que le scénario selon lequel un plugin peut réutiliser une bibliothèque partagée à partir de l'application principale devrait être abordé !
  4. Oui.
  5. 200-500ms c'est bien !
  6. Pour une simple application CLI sans beaucoup de dépendances, 10 Mo suffisent (compressés) !
  7. Oui définitivement ! Le temps de construction (en particulier pour les versions de version !) n'a pas d'importance ! La taille de compression et/ou le passage à la publication d'un seul fichier devrait être facultatif !
  8. Oui, par exemple CoreRT !

À mon humble avis, nous devrions viser une expérience de publication similaire à celle de golang.

@thegreatco : Oui, la compilation complète en code natif est une bonne option pour créer des applications à fichier unique. Des langages tels que GO sont construits avec une compilation anticipée (AOT) comme modèle principal, ce qui s'accompagne de certaines limitations sur les fonctionnalités de langage dynamique obtenues via la compilation JIT.

CoreRT est la solution .Net Core pour les applications compilées AOT. Cependant, jusqu'à ce que CoreRT soit disponible, nous essayons de réaliser des applications à fichier unique par d'autres moyens dans ce problème.

Mis à part le fait que "Hello World" semble nécessiter 216 fichiers pour fonctionner,

Il existe quelques options disponibles pour réduire le nombre de fichiers requis pour HelloWorld"

  • Créez une application dépendante du framework, qui n'a besoin que de 3 à 4 fichiers
  • Si nous devons créer des applications autonomes, utilisez ILLinker pour réduire le nombre de dépendances de fichiers

les extraire sur le disque à un endroit rend difficile la suppression d'une simple application en ligne de commande.

  • Au fur et à mesure que le développement de la fonctionnalité de fichier unique progresse , le nombre de fichiers déversés sur le disque diminuera et sera idéalement nul pour la plupart des applications. Mais dans les premières étapes, plusieurs fichiers (ceux contenant du code natif) devront être renversés.
  • L'emplacement des fichiers déversés sur le disque est toujours déterministe et configurable. Ainsi, les fichiers renversés peuvent être nettoyés avec un script simple. Mais je suis d'accord que ce n'est pas l'idéal.

Merci pour la clarification @mattpwhite.

Oui, jusqu'aux étapes ultérieures du développement des fonctionnalités, les applications autonomes verront les fichiers extraits sur le disque. Vous pourrez peut-être utiliser certaines des techniques que j'ai écrites dans le commentaire ci-dessus pour améliorer la situation de vos applications.

Merci pour votre réponse @BlitzkriegSoftware.

Mais je soulignerais que donner le choix dans le cadre des commutateurs de commande pour tout-en-un ou tout-en-un auto-extractible

Le fait qu'une application publiée en tant que fichier unique nécessite une extraction dépend du contenu de l'application (par exemple : si elle contient des fichiers natifs). La conception du bundler fournit certaines configurations pour décider si tous les fichiers doivent être extraits. Nous pouvons ajouter une propriété pour indiquer que l'application ne doit pas utiliser l'extraction de fichiers au moment de l'exécution.

<propertygroup>
    <SingleFileExtract> Never | Always | AsNeeded </SingleFileExtract>
</propertygroup>

La compréhension ici est la suivante : lors de la compilation de SingleFileExtract=Never, si l'application contient des fichiers qui ne peuvent être gérés que par extraction (binaires natifs), la publication dans un fichier unique échouera.

Dans le cas de l'auto-extraction, il doit inclure une annulation qui nettoie les fichiers décompressés.

Semble raisonnable. L'emplacement exact de l'extraction (le cas échéant) est déterministe et configurable. Ainsi, nous pouvons avoir un script pour supprimer une application et toutes ses dépendances extraites.

Merci pour votre réponse @DoCode. Votre scénario est intéressant dans la mesure où il utilise des plugins.
Si les plugins eux-mêmes ont des dépendances (qui ne sont pas partagées avec l'application principale), auriez-vous besoin/préféreriez-vous également publier le plugin en tant que fichier unique (avec des dépendances intégrées) ? Merci.

Oui @swaroop-sridhar, c'est le but. Nous pensons que dans ce cas, le plugin devrait intégrer ses dépendances. Seules les dépendances partagées auraient dû rester en dehors de l'application principale à fichier unique.

Aujourd'hui, @madskristensen a partagé une bonne clarification avec Visual Studio et le populaire package Newtonsoft.Json NuGet.

Nous les mêmes situations dans une situation similaire parfois!

Merci @DoCode. Nous prévoyons d'adresser la fonctionnalité des plugins à fichier unique, une fois que les applications à fichier unique sont implémentées et stables. La doc de conception parle des plugins ici .

Merci pour l'engagement continu sur cette fonctionnalité @swaroop-sridhar, c'est très apprécié. Avoir une commande d'annulation sera particulièrement utile pour les étapes d'origine.

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)
    -- Utilitaires de ligne de commande (applications console)
  2. Votre application inclut-elle du code C++/natif (non-.NET) ?
    -- Non
  3. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?
    -- Pas habituellement
  4. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?
    -- Oui
  5. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?
    -- < 1 seconde serait ma préférence
  6. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?
    -- La taille n'est pas importante
  7. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?
    -- 30 secondes
  8. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?
    -- Sûr s'il peut être scripté ou configuré

1 - Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)

  • Jeux
  • Outils de ligne de commande

2 - Votre application inclut-elle du code C++/natif (non .NET) ?

Oui

3 - Votre application chargerait-elle des plugins ou d'autres dll externes que vous n'aviez pas inclus à l'origine dans la construction de votre application ?

Oui, mais avec des symboles déjà connus, je ne compte pas sur la réflexion car c'est lent

4 - Êtes-vous prêt à reconstruire et redistribuer votre application pour intégrer des correctifs de sécurité ?

Oui

5 - L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?

Non, c'est déjà un peu lent

6 - Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?

Dépend du projet, mais pour un simple outil de ligne de commande, je ne m'attends pas à ce qu'il soit supérieur à un chiffre mbs

7 - Accepteriez-vous un temps de build plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?

Tant que cela n'a pas d'impact sur le temps de développement/d'itération, je suis d'accord avec un temps de construction de version plus long
Mais n'oubliez pas que les applications .net core sont déjà construites plus longtemps que les applications .net framework traditionnelles

Cette tendance à un logiciel plus lent chaque année n'est PAS acceptable, nous avons un meilleur matériel, aucune raison pour cette lenteur

8 - Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?

OUI!

J'espère vraiment que la compilation AOT avec CoreRT fonctionnera un jour afin que nous puissions avoir des applications compilées nativement comme golang et rust et d'autres langages compilés AOT. De la même manière que Unity3D le fait avec IL2CPP.

@morganbr Voici quelques commentaires de moi et des gens avec qui je travaille. J'utilise beaucoup de langages, mais principalement C#, Go et Python.

Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)

Programmes ASP.NET Core et Console, principalement sous Linux, potentiellement certaines charges de travail Windows, selon que ML.NET répond à nos besoins.

Votre application inclut-elle du code C++/natif (non-.NET) ?

Peu probable à ce stade.

Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?

Ça dépend. Actuellement, nous pouvons extraire toutes nos dépendances sous forme de packages, mais je pourrais voir une situation où nous payons pour une bibliothèque commerciale, ce qui peut signifier l'utilisation de DLL externes.

Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?

Absolument. C'est une priorité absolue pour nous.

L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?

Je dirais que moins de 10 secondes me conviennent parfaitement. Le temps de démarrage n'a généralement pas d'importance tant qu'il est idempotent et prévisible - c'est-à-dire que les bibliothèques sont chargées dans le même ordre, les variables sont initialisées dans le même ordre, etc.

Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?

Plus c'est petit, mieux c'est, principalement à des fins de distribution. La distribution peut être des binaires téléchargés par l'utilisateur, des images de conteneur avec le binaire, etc.

Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ?

Bien sûr, tant que c'est plus rapide que C/C++ et Java, ça devrait être agréable.

Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?

30 à 90 secondes seraient probablement idéales, mais tout ce qui est inférieur à 3 minutes est probablement agréable. Plus de 3 minutes pour les petits/moyens projets (1k-500k LOC) serait un peu trop. 5 minutes pour les très grands projets (1M LOC) pourraient être acceptables.

Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?

Ça dépend. Si le travail supplémentaire consiste à ajouter du code passe-partout qui peut être modélisé, c'est probablement bien. Si ce n'est pas clair, pas un travail simple, potentiellement pas.

Merci pour la réponse @mxplusb , @dark2201 , @RUSshy , @BlitzkriegSoftware

Je pense que la conception actuelle répond le mieux possible à vos scénarios en l'absence d'une compilation AOT pure. Si vous avez des inquiétudes concernant le design, n'hésitez pas à le signaler.

En ce qui concerne le temps de démarrage et le temps de compilation inférieurs :
Les applications dépendantes du framework auront un temps de démarrage considérablement plus court (au moins dans les premières étapes de la mise en place de la fonctionnalité). Le temps de compilation est également plus court (car moins de fichiers doivent être intégrés).
Je vous reviendrai avec les mesures du temps de démarrage, du débit de compilation et de la taille des fichiers dès que la première itération du développement des fonctionnalités sera terminée.

@swaroop-sridhar Quel est le calendrier pour cela ?

@ayende La première itération est en cours de développement actif, je pense que nous aurons les résultats dans quelques semaines.

@swaroop-sridhar

Je pense que la conception actuelle répond le mieux possible à vos scénarios en l'absence d'une compilation AOT pure. Si vous avez des inquiétudes concernant le design, n'hésitez pas à le signaler.

Exécutez : HelloWorld.exe

L'application groupée et les fichiers de configuration sont traités directement à partir du bundle.
Les 216 fichiers restants seront extraits sur le disque au démarrage.

Que se passe-t-il si j'ai besoin d'exécuter à partir de fs en lecture seule, c'est courant pour l'IoT, ou si l'exe s'exécute dans un conteneur ro ? pourquoi n'y a-t-il pas également la possibilité de l'exécuter directement à partir de l'exe?

@etherealjoy L'exemple présenté dans cette section est la sortie attendue pour HelloWorld autonome à partir de l'étape 2 du développement de cette fonctionnalité (comme mentionné dans cette section ). À ce stade, les seules applications pouvant s'exécuter directement à partir de l'EXE sont les applications entièrement gérées dépendantes du framework.

Si nous sommes à l'étape 4 ou à l' étape 5 , l'application autonome ci-dessus peut s'exécuter directement à partir du bundle.

Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)

Fondamentalement tout ce qui précède. Utilitaires console, WPF, asp.net, jeux

Votre application inclut-elle du code C++/natif (non-.NET) ?

Oui. SQLite est un bon exemple.

Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?

Probablement pas.

Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?

Oui.

L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?

net.core est déjà un peu trop lent. Mais une augmentation de quelques secondes est acceptable. 5 secondes - certainement pas.

Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?

Peu importe de nos jours

Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?

Jusqu'à 5 minutes se sent est acceptable. Les versions de 15 à 20 minutes pour UWP rendent tout le monde fou.

Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?

Sûr.

Merci @mjr27

L'implémentation de l' étape 1 est maintenant terminée et est disponible à partir de la version 3.0.100-preview5-011568 .

Les applications peuvent être publiées dans un seul fichier en définissant la propriété PublishSingleFile sur true comme expliqué ici .

Dans cette version, tous les fichiers intégrés sont extraits sur le disque lors de la première exécution et réutilisés lors des exécutions suivantes, comme expliqué ici .

Débit de compilation
Il n'y a pas de différence significative dans le temps, que les fichiers soient écrits dans le répertoire de publication en tant que fichiers individuels ou en tant que fichier unique.

Taille du fichier et démarrage
Le tableau suivant montre les performances de quelques applications créées en tant que fichier unique.

  • Console : Une application hello world. Le temps indiqué est le temps d'exécution de l'application, mesuré par des tics d'horloge.
  • Application WPF : application msix-catalog . Le temps indiqué est le temps de démarrage à l'écran initial, mesuré via un chronomètre.
  • Fw : versions dépendantes du framework
  • Autonome : constructions autonomes.
    Toutes les exécutions ont été chronométrées lorsque les vérifications antivirus sont désactivées afin de minimiser l'impact des facteurs externes.

Mesure | Micrologiciel console | Console autonome | Logiciel WPF | WPF Auto
-- | -- | -- | -- | --
Taille du fichier (Mo) | 0,32 | 66,5 | 20.69 | 118,9
Fonctionnement normal (sec) | 0,123 | 0,127 | 3.32 | 3.24
Première exécution d'un seul exe (sec) | 0,127 | 0,565 | 3.67 | 4.14
Exécutions suivantes d'un seul exe (sec) | 0,124 | 0,128 | 3.30 | 3.29

Je continuerai à mettre à jour les chiffres au fur et à mesure que la mise en œuvre progresse dans les étapes de développement suivantes.

Excellente nouvelle. Merci

Est-ce que toutes les étapes mentionnées dans la documentation de mise en scène seront terminées pour 3.0 RTM ? Ou faudra-t-il attendre la post 3.0 pour qu'elles soient implémentées ?

Comme mentionné ici , .net core 3.0 devrait implémenter l' étape 2 de sorte que les applications msil pures dépendantes du framework puissent s'exécuter directement à partir du bundle. Les étapes restantes seront prises en compte pour les versions ultérieures.

Comme mentionné ici , .net core 3.0 devrait implémenter l' étape 2 de sorte que les applications msil pures dépendantes du framework puissent s'exécuter directement à partir du bundle. Les étapes restantes seront prises en compte pour les versions ultérieures.

:( J'espérais qu'il pourrait arriver sur RTM.

@cup Je pensais que tu pouvais le faire avec dotnet publish -o out /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 . Je viens de tester en créant une application console vanille et en exécutant cette commande. Cela a fonctionné avec succès.

Vous pouvez aller encore plus loin en regroupant le fichier .pdb avec dotnet publish -o out /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 /p:IncludeSymbolsInSingleFile=true

Merci @seesharprun pour les notes détaillées. Oui @cup , la méthode recommandée pour la publication d'un seul fichier en ligne de commande consiste à définir la propriété PublishSingleFile à partir de la ligne de commande.

@etherealjoy les dépôts d'exécution coreclr seront principalement verrouillés avec le travail de fonctionnalité dans un mois environ. Je pense qu'il n'y a pas assez de temps pour toutes les étapes. J'espère que les étapes suivantes viendront dans la prochaine version.

Je l'ai fait fonctionner aujourd'hui, mais il semble que la modification du répertoire de base d'extraction ne fonctionne pas. Selon cette rubrique . Je devrais pouvoir ajouter un commutateur d'application dans runtimeconfig appelé ExtractBaseDir pour modifier l'emplacement vers lequel l'application est extraite.

J'ai un runtimeconfig.template.json qui ressemble à ceci

{
    "configProperties" : {
        "ExtractBaseDir": "C:\\"
    },
    "ExtractBaseDir": "C:\\"   
}

Le fichier app.runtimeconfig.json produit ressemble à ceci :

{
  "runtimeOptions": {
    "configProperties": {
      "ExtractBaseDir": "C:\\"
    },
    "ExtractBaseDir": "C:\\"
  }
}

Lors de l'exécution de l'exe produit, il extrait toujours le dossier tmp.

Je suppose que cette fonctionnalité n'est tout simplement pas prête dans Preview5, mais je voulais m'en assurer car il n'est pas clair où "ExtractBaseDir" est censé aller dans runtimeconfig.json et il n'y a pas d'exemples.

@igloo15 Merci d'avoir soulevé cette question.

Dans l'aperçu actuel, seule la variable d'environnement DOTNET_BUNDLE_EXTRACT_BASE_DIR est activée. En effet, à l' étape actuelle de la mise en œuvre , tous les fichiers, y compris runtimeconfig.json , sont extraits sur le disque avant d'être traités.

Je travaille sur l'ajout de la prise en charge de ExtractBaseDir dans le prochain aperçu.

Existe-t-il des conseils sur la façon de faire fonctionner cela avec les projets ASP.NET Core ? L'approche recommandée serait-elle d'utiliser la réflexion pour trouver d'où mes types de système se chargent et de définir mon IHostingEnvironment ContentRootPath et WebRootPath par rapport à ce répertoire ?

@keithwill Vous pouvez utiliser AppContext.BaseDirectory pour obtenir l'emplacement où app.dll et tous les autres fichiers sont extraits sur le disque. Donc, vous pouvez l'utiliser comme ContentRootPath .

@igloo15 : Je suis curieux de savoir si vous pouviez partager votre scénario par rapport à l'utilisation de cette option.

  • Essayez-vous de l'utiliser pour un scénario de débogage ou de déploiement en production ?
  • La variable d'environnement suffirait-elle dans ce cas, ou avez-vous besoin du paramètre runtimeconfig.json ?

Je suis également curieux d'entendre d'autres développeurs s'il existe des cas d'utilisation spécifiques pour ce paramètre.

@swaroop-sridhar

J'ai une situation assez étrange. Mon logiciel est stocké sur un partage réseau, puis le partage réseau est lié à une machine virtuelle Windows aléatoire et exécuté directement à partir du partage réseau. La machine virtuelle Windows qui est créée pour exécuter le logiciel à partir du partage réseau ne peut rien modifier ni changer. Les journaux, les fichiers de configuration, etc. doivent tous être créés sur le partage réseau.

Étrangement, cette configuration permet au système global de disposer plusieurs logiciels dans un dossier, puis de cloner cette structure de dossiers pour différentes configurations/versions. Ensuite, lorsqu'une version spécifique doit être exécutée, le logiciel de gestion fait tourner les vms et mappe les lecteurs sur les vms vers un partage réseau de version spécifique et exécute le logiciel.

1.) Il s'agit d'un scénario de déploiement de production
2.) Les variables d'environnement seraient difficiles car l'ordinateur exécutant le logiciel est constamment différent et détruit/refait

@cup Je ne suis vraiment pas d'accord que ce sujet concerne l'implémentation du document de conception et le document de conception indique spécifiquement que ExtractBaseDir devrait fonctionner pour cette fonctionnalité.

Si ce problème ne concerne pas la mise en œuvre de ce document de conception, alors de quoi s'agit-il ?

Merci pour l'explication @igloo15.

Je pose des questions sur l'option de configuration, car l'analyse des fichiers de configuration au début du code AppHost a un coût. Actuellement, AppHost n'est pas lié au code d'analyse des fichiers json (ils sont utilisés par hostfxr/hostpolicy à la place). L'ajout de cette fonctionnalité à l'heure actuelle rendrait l'AppHost un peu plus grand/complexe. Cependant, une fois que la mise en œuvre passe à d' autres étapes (où tous les codes d'hébergement et d'exécution sont liés), ce n'est plus un problème.

@ igloo15 , la documentation de conception en est une partie importante, mais le cœur de ce problème est la fonctionnalité elle-même. ExtractBaseDir est un paramètre facultatif et je préférerais que la fonctionnalité principale soit transmise à la version "actuelle" plutôt que de s'enliser avec des paramètres facultatifs.

@cup , j'ai posé la question ici, car j'ai attiré l'attention des développeurs intéressés par ce fil.
Bien que je ne pense pas que la question soit hors sujet, je comprends votre inquiétude concernant la longueur de ce fil. Je créerai un problème lié la prochaine fois. Merci.

@cup @swaroop-sridhar

Une ou deux choses que je dirais d'abord, c'est que cette fonctionnalité n'a d'importance que pour l'étape 1 du document d'étape. Toutes les autres étapes 2 à 5 concernent l'exécution des dll depuis l'intérieur du bundle et non l'extraction. Ainsi, un paramètre permettant de déterminer l'emplacement du répertoire de base de l'extrait n'est pas vraiment utile pour les étapes 2 à 5. Comme NetCore 3.0 a l'intention de développer l'étape 1, je m'attendrais à ce que cette fonctionnalité soit là puisque c'est la seule fois où elle serait utile.

Deuxièmement, comment différencions-nous cette méthode des autres méthodes comme dotnet-wrap. Pour moi, les principaux avantages de cette méthode sont que nous intégrons ce processus dans la chaîne de construction plus près du moment où le code est compilé. De plus, il s'agit d'une fonctionnalité adaptée à .NET et comprend donc les nuances des applications .NET Core telles que leurs configurations, leur processus de construction, etc. En tant que tel, j'espère que nous nous concentrerons sur les fonctionnalités qui différencient cet outil des autres outils qui sont pas spécifiquement adapté au cœur du réseau. Il s'agirait de fonctionnalités telles que la configuration de l'emplacement d'extraction que dotnet-wrap ne peut pas faire.

En ce qui concerne la manière dont il est implémenté, je ne suis pas sûr, mais je pense que plutôt que de lire ExtractBaseDir à partir de la configuration au moment de l'exécution, ne pourrions-nous pas intégrer cela dans l'exe du bundle au moment de la construction? Je n'ai pas vu le code qui fait fonctionner ce processus de bundle, mais dans mon esprit, il génère/construit un exe natif avec toutes les dll, etc. à l'intérieur. Ne pourrions-nous pas, lors de la génération/construction de l'exe, lire le fichier runtimeconfig des applications fournies, extraire le ExtractBaseDir et le définir en tant que propriété sur l'exe du bundle natif.

Ensuite, il ne lit pas une runtimeconfig intégrée au moment de l'exécution, mais utilise plutôt une propriété en interne pour déterminer l'emplacement d'extraction. Cela devrait potentiellement être beaucoup plus rapide.

@igloo15 : L'extraction du contenu du bundle sur le disque peut être utile pour certaines applications au-delà de l'étape 2.
Par exemple, si l'application contient des fichiers binaires natifs personnalisés dans le bundle, ils devront être extraits jusqu'à l'étape 5. L'application peut souhaiter regrouper des fichiers de contenu de type inconnu à extraire dans des fichiers au moment de l'exécution.

Je conviens que l'utilité de ce paramètre diminue à mesure que nous passons à d'autres étapes de développement. Cependant, une fois l'option ajoutée, nous devrons probablement la conserver dans toutes les versions ultérieures pour des raisons de compatibilité. Par conséquent, il doit être examiné attentivement maintenant.

Je suis d'accord que faire de l'emplacement d'extraction un paramètre de construction (ex: msbuild-property) plutôt qu'une option runtimeconfig est une implémentation plus facile et plus efficace. Merci.

Bonjour, j'ai quelques questions sur ce sujet :

Je souhaite utiliser la fonctionnalité de distribution de fichier unique pour empaqueter des applications .NET Framework 4.7.2 (par exemple) dans un seul exécutable. Est-ce l'intention de cette fonctionnalité ou est-elle uniquement destinée à prendre en charge les applications .NET Core ?

Ma deuxième question concerne la façon dont l'emballage est fait. Lorsque l'exécutable est créé, le runtime des frameworks cibles est-il intégré à l'exécutable ? Ou doit-il être pré-installé sur la machine cible qui exécutera l'application ?

@gaviriar Je ne pense pas qu'il prenne en charge les applications .NET Framework. Et oui, il peut regrouper le runtime .NET Core dans un exécutable (ce que l'on appelle la publication "autonome").

@ tomrus88 merci pour la réponse. C'est vraiment dommage pour les applications .NET Framework. Existe-t-il une méthode que vous recommanderiez qui pourrait être utilisée pour regrouper le runtime .NET Framework dans un exécutable ?

Je vois une liste d'outils dans la section de travail connexe du document. Y en a-t-il un en particulier qui pourrait être recommandé pour mon cas d'utilisation proposé ci-dessus ?

@gaviriar .NET Framework fait partie du système d'exploitation Windows. Il n'existe aucun moyen pris en charge de le regrouper dans un exécutable.

@gaviriar La nécessité de regrouper le runtime est l'une des principales raisons de passer à .NET Core.

@jnm2 et @jkotas merci pour la clarification, noob ici dans le monde .NET. Je suis d'accord, j'aimerais passer à .NET Core. Cependant, je suis confronté à un cas où je dois interagir avec une bibliothèque héritée qui cible .NET Framework. Dans un tel cas, je comprends que je ne peux pas basculer mon application vers .NET Core si j'ai besoin d'interagir avec cette bibliothèque. Ou existe-t-il une approche alternative telle que mon application est .NET Core mais peut toujours interagir avec la bibliothèque .NET Framework héritée ?

Cela dépend de la bibliothèque. De nombreuses bibliothèques qui ciblent .NET Framework fonctionnent également correctement sur .NET Core. Avez-vous essayé d'utiliser la bibliothèque dans .NET Core ? Si vous avez vérifié que cela ne fonctionne pas, vous ne pouvez pas changer tant que vous n'avez pas trouvé de solution.

Je l'ai effectivement essayé, mais cela ne fonctionne pas car nous parlons de bibliothèques spécifiques à Windows. Je suppose que je n'ai pas d'autre choix que de m'en tenir au ciblage de .NET Framework et de rater le plaisir de .NET Core comme vous le dites :/

@gaviriar Ceci est hors sujet, mais avez-vous essayé le package NuGet de compatibilité Windows, il fournit des API Windows pour .NET Core dans le but exact que vous décrivez Microsoft.Windows.Compatibility

@gaviriar : Quelques précisions supplémentaires :

Lorsque l'exécutable est créé, le runtime des frameworks cibles est-il intégré à l'exécutable ? Ou doit-il être pré-installé sur la machine cible qui exécutera l'application ?

Cela dépend de la construction. Les applications dépendantes du framework (le runtime est installé sur la cible) et autonomes (le runtime est fourni avec l'application) peuvent être publiées sous forme de fichier unique, mais uniquement les applications .net core 3.0.

Je vois une liste d'outils dans la section de travail connexe du document. Y en a-t-il un en particulier qui pourrait être recommandé pour mon cas d'utilisation proposé ci-dessus ?

Pour le framework .net, la meilleure solution que je puisse suggérer est que l'application gère elle-même l'extraction de fichiers. Par exemple : intégrez les dépendances en tant que ressources gérées dans le fichier binaire de l'application, puis extrayez explicitement les ressources au démarrage. Vous pouvez également utiliser la bibliothèque de bundles pour le regroupement et l'extraction (car la bibliothèque est construite netstandard), mais l'utilisation de ressources gérées est une meilleure solution.

@ igloo15 et @ swaroop-sridhar J'apprécie ces contributions étant donné qu'elles sont hors sujet. Bien que j'espère que quelqu'un d'autre trouvera cette discussion utile lors de la lecture un jour.

Je vais évaluer les options que vous avez partagées avec moi et vous faire savoir quelle est la meilleure approche pour mon cas d'utilisation.

Merci!

Mise à jour rapide !

J'ai testé cette simple application Hello World . Je peux créer avec succès un seul fichier exécutable. Cependant, comme vous pouvez le voir dans la configuration du projet, il est censé être autonome. Mais lorsque j'essaie d'exécuter cet exécutable sur une nouvelle installation de Windows 7 sans aucun runtime .NET core installé, je vois l'erreur suivante :

Failed to load the DLL from [C:\Users\vagrant\AppData\Local\Temp\.net\HelloWorld
\muasjfkf.kyn\hostfxr.dll], HRESULT: 0x80070057
The library hostfxr.dll was found, but loading it from C:\Users\vagrant\AppData\
Local\Temp\.net\HelloWorld\muasjfkf.kyn\hostfxr.dll failed
  - Installing .NET Core prerequisites might help resolve this problem.
     https://go.microsoft.com/fwlink/?linkid=798306

Ce que je peux voir, c'est que la construction de la publication de l'application en tant que dotnet publish /p:PublishSingleFile=true ou /p:PublishSingleFile=false ne modifie pas la taille de l'exécutable. Est-ce un comportement attendu ?

Étapes à suivre pour reproduire

  1. Publiez le projet pour générer le HelloWorld.exe

  2. Copiez l'exécutable sur une installation Windows 7 sans aucun runtime .NET Core installé

  3. Exécutez le HelloWorld.exe

@gaviriar J'ai essayé l'exemple que vous avez publié et cela a bien fonctionné pour moi.
C'est-à-dire qu'il a construit un seul exe autonome pour HelloWorld qui fonctionne correctement.

Ce que je peux voir, c'est que la construction de la publication de l'application en tant que publication dotnet /p:PublishSingleFile=true ou /p:PublishSingleFile=false ne modifie pas la taille de l'exécutable. Est-ce un comportement attendu ?

Ce n'est certainement pas prévu. L'application à fichier unique doit faire environ 70 Mo (pour la version de débogage indiquée sur votre page gitlab). Sinon, il s'agit d'un apphost normal, qui devrait échouer exactement comme vous l'avez noté ci-dessus. Publiez-vous à partir d'un répertoire propre ?

Une autre note à propos de votre fichier de projet - vous avez l'une des propriétés incorrectement écrite comme IncludeSymbolsInFile au lieu de IncludeSymbolsInSingleFile . Mais cela n'a aucun lien avec le problème que vous avez signalé.

@gaviriar quels sont vos identifiants d'exécution cibles. Si vous ne le définissez pas correctement, il ne regroupera pas le bon hostfxr.dll. Il est possible que hostfxr.dll nécessite un redistribuable vc++ spécifique qui n'existe pas sur votre machine Windows 7. Vous pouvez vérifier que la dll sur le chemin donné existe et si elle essaie de la charger dans l'outil de marcheur de dépendances pour voir si une dll dont elle dépend existe.

Fusion d'IL : des outils comme ILMerge combinent l'IL de plusieurs assemblages en un seul, mais perdent l'identité de l'assemblage au cours du processus. Ce n'est pas un objectif pour la fonction de fichier unique.

perdre l'identité de l'assembly

ce n'est pas un problème.
Je suis toujours contre l'utilisation de zip/unzip ou d'une autre solution groupée pour la fonction autonome Single exe.
car cela causera les prochains problèmes.
Comment réduire la taille du fichier exe unique ? ? ou pourquoi le fichier exe est tellement gros mais ce n'est qu'un bonjour le monde ! ?

Il y a toujours le problème, et doit être résolu, pourquoi ne pas faire une analyse approfondie.
En fait, dès le départ, il convient d'utiliser IL-Merge de manière similaire.

En fait, les gens ne sont pas vraiment obsédés par un seul EXE.
exe(1)+dll(1-2) également OK, mais pas 400 dll de montage.
ppl n'aimera pas amener le code à ne jamais être exécuté sur le disque du serveur et l'exécuter en prenant les mémoires du serveur.
les gens veulent juste réduire le coût du déploiement. (Disque, Mémoire, Bande passante etc...)

J'ai supprimé le jalon 3.0, afin que ce problème suive la mise en œuvre de la fonctionnalité de fichier unique à travers les étapes décrites dans ce document , ce qui dépasse le cadre de la version 3.0.

@sgf , je suis d'accord qu'il y a du travail nécessaire pour réduire la taille du fichier. Les opportunités de réduction de taille sont de deux formes, elles ne sont pas spécifiquement liées à un seul exe :
1) Réduisez la quantité de contenu à publier. Par exemple:
* Utilisez ILLinker comme des outils pour couper les binaires inutiles, les parties d'assemblages, etc.
Ce travail est suivi séparément par des problèmes tels que dotnet/coreclr#24092 et mono/linker#607
* Nous pouvons envisager d'autres mesures telles qu'avoir un mode "capacité réduite" où le JITting n'est pas pris en charge pour réduire le
2) Ajoutez une fonctionnalité de compression à la publication de fichiers uniques.

Les fonctionnalités ci-dessus peuvent fonctionner ensemble pour réduire la taille des applications à fichier unique (et non à fichier unique) :
Par exemple, pour l'application console HelloWorld,
Taille de publication normale = 67,4 Mo
Taille réduite = 27 Mo
Découpé, fichier unique, compressé (via prototype) = 12 Mo

@ swaroop-sridhar Existe-t-il un moyen d'obtenir le chemin de votre fichier exe unique dans votre application?
L'utilisation Assembly.GetExecutingAssembly().Location affichera le répertoire d'extraction dans \AppData\Local\Temp.net.

@ chris3713 La meilleure façon d'accéder à l'emplacement exe actuellement est de PInvoke-ing aux API natives. Par exemple : GetModuleFileNameW (Null, <buffer>, <len>)

@ chris3713 La meilleure façon d'accéder à l'emplacement exe actuellement est de PInvoke-ing aux API natives. Par exemple : GetModuleFileNameW (Null, <buffer>, <len>)

Merci, j'ai fini par utiliser Process.GetCurrentProcess().MainModule.FileName .

Fonctionne bien avec asp .net core worker/web api en tant que service Windows publié avec PublishSingleFile=true.

Lorsque j'enregistre le service et que je l'exécute via sc create testwk binPath="[...]/MyAspNetCoreWorker.exe" puis sc start testwk , j'ai ce message de réussite :

[...]\bin\publish\x64>sc start testwk

SERVICE_NAME: testwk
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 5060
        FLAGS              :

[...]\bin\publish\x64>sc stop testwk

SERVICE_NAME: testwk
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

J'ai hâte de voir l'étape 2 avec runing en bundle😀
Au fait, l'étape 2 sera-t-elle toujours prévue pour faire partie de .Net Core 3.0 ?

Merci pour votre travail, le service de publication dans .net core est maintenant très simple 👍

CoreRT : (2,5 Mo)

image

image

Pas de piratage zip , pas de coût caché , le moteur ne contient que ce qui est nécessaire et les fonctionnalités non utilisées sont désactivées à l'aide de csproj config (réflexion)

C'est ce dont dotnet a besoin, il concurrence GO et le surpasse même tant en terme de taille que de perf

Pour toute personne intéressée, consultez le dépôt:

https://github.com/dotnet/corert

Il existe des exemples pour MonoGame :

https://github.com/dotnet/corert/tree/master/samples/MonoGame

Aucune des solutions proposées ne peut atteindre ce résultat, CoreRT est vraiment le meilleur, MS commet une énorme erreur en ne se concentrant pas dessus

J'ai testé cette fonctionnalité sur macOS avec dotnet-sdk-3.0.100-preview8-013656-osx-x64.tar.gz . Si nous basculons la configuration, de Debug à Release ou vice-versa et que nous reconstruisons à nouveau, cela ajoute 10 Mo à la taille de l'exécutable. La recompilation avec l'ancienne configuration ne récupère pas cette augmentation de taille sauf si nous supprimons le répertoire bin .

mkdir /tmp/dotnet-preview8
curl -s https://download.visualstudio.microsoft.com/download/pr/a974d0a6-d03a-41c1-9dfd-f5884655fd33/cf9d659401cca08c3c55374b3cb8b629/dotnet-sdk-3.0.100-preview8-013656-osx-x64.tar.gz | tar -xvz -C /tmp/dotnet-preview8
export PATH=/tmp/dotnet-preview8:$PATH

dotnet new console -o /tmp/myApp
pushd /tmp/myApp

# publish with Debug
dotnet publish /p:PublishSingleFile=true,RuntimeIdentifier=osx-x64,Configuration=Debug -o bin/a/b/c/d

bin/a/b/c/d/myApp
# outputs: Hello World!

du -sh bin/a/b/c/d
# outputs  70M  bin/a/b/c/d

# publish with Release
dotnet publish /p:PublishSingleFile=true,RuntimeIdentifier=osx-x64,Configuration=Release -o bin/a/b/c/d

du -sh bin/a/b/c/d
# outputs:  80M bin/a/b/c/d

# publish with Debug again
dotnet publish /p:PublishSingleFile=true,RuntimeIdentifier=osx-x64,Configuration=Debug -o bin/a/b/c/d
# still outputs:  80M   bin/a/b/c/d

Même sans modifier la configuration de la construction, si nous invoquons Rebuild target ultérieurement ( /t:Rebuild ) après la construction initiale, la taille de la sortie augmente.

Merci @ am11 d'avoir jeté un coup d'œil. Publier en conservant les anciens binaires est un problème connu (cc @nguerrera).

Depuis l'aperçu 8 de .Net Core 3, je ne peux pas lancer mon application publiée à fichier unique.
Dans l'observateur d'événements j'ai cette erreur :

image

Je suis sur Windows Serveur 2019

Edit : Cette erreur s'est produite après la mise à jour de .Net Core SDK Preview 7 vers .Net Core SDK Preview 8. Après avoir redémarré le serveur, je peux relancer correctement mon application.

@Safirion, nous avons modifié le format interne sous-jacent autour de ces aperçus. Il est possible que vous ayez chevauché la sortie d'un aperçu et construit avec un autre. Il n'y a pas de pause entre l'Aperçu 8 et l'Aperçu 9.

Sous Linux, le chemin d'extraction par défaut semble être /var/tmp/.net . Sur AWS lambda, le chemin /var n'est pas accessible en écriture, donc la création de ce dossier échoue. Pour sortir de la boîte exécutable sans définir DOTNET_BUNDLE_EXTRACT_BASE_DIR, je propose de changer cela en /tmp/.net . Ou peut-être qu'il devrait y avoir plusieurs tentatives à des emplacements communs (/var/tmp, /tmp, même répertoire que le binaire, etc.)

@stevemk14ebr merci d'avoir signalé ce problème. Pouvez-vous déposer un nouveau problème pour suivre ce travail ? https://github.com/dotnet/core-setup

@jeffschwMSFT La même erreur a été renvoyée avec le passage de .Net Core P9 à RC1.

Description: A .NET Core application failed.
Application: Setup.exe
Path: C:\Users\Administrateur\Desktop\Setup.exe
Message: Failure processing application bundle.
Failed to determine location for extracting embedded files
A fatal error was encountered. Could not extract contents of the bundle

@Safirion merci d'avoir signalé ce problème. Pouvez-vous créer un problème séparé pour reproduire cela ? https://github.com/dotnet/core-setup
cc @swaroop-sridhar

@Safirion pouvez-vous s'il vous plaît envoyer des instructions de reproduction? Cet échec est-il déterministe ?
Veuillez signaler un problème dans le référentiel de configuration de base, comme @jeffschwMSFT l' a suggéré ci-dessus.

J'ai regardé cela et cela ne se produirait que si l'application s'exécutait dans un environnement où le répertoire temporaire n'est pas accessible. Par exemple si je fais ceci :

set "TMP=wrong_path"
myapp.exe

Il échoue avec

Failure processing application bundle.
Failed to determine location for extracting embedded files
A fatal error was encountered. Could not extract contents of the bundle

Notez que le bundle recherche le répertoire temporaire à l'aide de l'API GetTempPath win32. Qui utilise l'env. variable TMP , suivi de TEMP et ainsi de suite. Si le premier avec valeur contient un chemin non valide, il échouera comme ceci.

Vous pouvez résoudre ce problème en vous assurant que le chemin temporaire est correctement défini ou en définissant explicitement DOTNET_BUNDLE_EXTRACT_BASE_DIR sur un emplacement où vous souhaitez que l'extraction se produise.

@Safirion pouvez-vous s'il vous plaît envoyer des instructions de reproduction? Cet échec est-il déterministe ?
Veuillez signaler un problème dans le référentiel de configuration de base, comme @jeffschwMSFT l' a suggéré ci-dessus.

Je ne parviens pas à reproduire ce problème après la mise à jour de .Net Core vers RC1 et le redémarrage de mon serveur. (J'ai essayé de désinstaller RC1 et de réinstaller Preview 9 pour mettre à niveau à nouveau vers RC1 mais mon application se lance bien cette fois)

Cette erreur s'est produite lors du passage du SDK 3.0 P7 au SDK 3.0 P8 et du SDK 3.0 P9 au SDK 3.0 RC1.
Et dans les deux cas, un simple redémarrage du serveur règle le problème.

J'utilise un service Windows .Net Core (travailleur utilisant le dossier C:\Windows\Temp\.net pour extraire depuis son lancement par le système) et une application .Net Core WPF (lancement par le script de session de démarrage de l'utilisateur) lorsque j'ai mis à niveau vers RC1. Peut-être que cette erreur est causée par .Net core worker en cours d'exécution pendant l'installation de .Net Core SDK, je ne sais pas ...

Notez que j'installe le SDK et non le runtime car je dois déployer le runtime 3 .Core (asp.net core, desktop .net core et core) en même temps et https://dot.net ne nous donne pas un "Full Runtime installer" (je n'ai même pas trouvé le programme d'installation de Desktop Runtime, donc pas le choix) ...

Mise à jour : tant pis, j'ai trouvé la documentation .

Salut, merci pour votre travail acharné!

Comment les fichiers de configuration (App.config par exemple) sont-ils censés être distribués ? Je viens de créer une application console sur RHEL 7.6 avec la séquence de commandes exacte :

dotnet restore -r win-x64 --configfile Nuget.config
dotnet build Solution.sln --no-restore -c Release -r win-x64
dotnet publish --no-build --self-contained -c Release -r win-x64 /p:PublishSingleFile=true -o ./publish ./SomeDir/SomeProj.csproj

où SomeProj.csproj a <PublishTrimmed>true</PublishTrimmed> activé et a obtenu 2 fichiers comme résultat : SomeProj.exe et SomeProj.pdb , mais pas SomeProj.config

@catlion pour avoir le comportement par défaut pour les fichiers *.config, ils doivent être exclus du bundle. Par défaut, tous les fichiers non pdb sont inclus dans le bundle.
Ce qui suit exclura la configuration du fichier unique :

<ItemGroup>
    <Content Update="*.config">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </Content>
  </ItemGroup>

https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md#build-system-interface

@morganbr

Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)

Applications sans tête et WPF pour Windows

Votre application inclut-elle du code C++/natif (non-.NET) ?

Oui, nous P/Invoke à une variété de DLL natives, certains éléments tiers sur lesquels nous n'avons aucun contrôle, certains internes d'autres équipes.

Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?

Oui, mais nous utilisons CompilerServices pour les compiler à partir des sources.

Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?

Oui

L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?

Oui, notre application reste généralement ouverte pendant de longues périodes.

Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?

Oui, nous pouvons attendre plusieurs minutes.

Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?

Oui

Merci @john-cullen

Lier quelques PR à la branche single-exe pour une mise en œuvre prototype de l'exécution d'applications à fichier unique sans extraction ( étape 4 ).

https://github.com/dotnet/coreclr/pull/26197
https://github.com/dotnet/coreclr/pull/26504
https://github.com/dotnet/coreclr/pull/26697
https://github.com/dotnet/coreclr/pull/26904

Permettez-moi également de fournir quelques réponses pour @morganbr :) Je ne sais pas si vous les lisez encore :)

  1. Avec quel type d'application seriez-vous susceptible de l'utiliser ? (par exemple WPF sous Windows ? ASP.NET dans un conteneur Linux Docker ? Quelque chose d'autre ?)

Aventures textuelles (applications console) à exécuter sur différentes plates-formes (Linux, MacOS, Windows)

  1. Votre application inclut-elle du code C++/natif (non-.NET) ?

Non.

  1. Votre application chargerait-elle des plug-ins ou d'autres DLL externes que vous n'aviez pas inclus à l'origine dans la version de votre application ?

Pas actuellement, mais ce serait formidable à long terme de prendre en charge certains scénarios.

  1. Êtes-vous prêt à reconstruire et à redistribuer votre application pour intégrer des correctifs de sécurité ?

Oui.

  1. L'utiliseriez-vous si votre application démarrait 200 à 500 ms plus lentement ? Qu'en est-il de 5 secondes ?

Oui.
(Ce serait formidable de fournir une sortie de texte ou une boîte de message pour informer l'utilisateur que quelque chose se passe)

  1. Quelle est la plus grande taille que vous considérez comme acceptable pour votre application ? 5 Mo ? dix? 20 ? 50 ? 75 ? 100 ?

10-20 Mo.

  1. Accepteriez-vous un temps de construction plus long pour optimiser la taille et/ou le temps de démarrage ? Quelle est la durée la plus longue que vous accepteriez ? 15 secondes ? 30 secondes? 1 minute? 5 minutes?

1+ minutes c'est ok.

  1. Seriez-vous prêt à faire un travail supplémentaire si cela réduisait de moitié la taille de votre application ?

Peut-être.

Merci pour la réponse, @lenardg.

Ce problème suit la progression de la fonctionnalité de distribution de fichier unique .NET Core 3.0.
Voici le document de conception et le plan de mise en scène de la fonctionnalité.

C'est une fonctionnalité très utile pour faciliter le déploiement et réduire la taille.
Peu de réflexions sur l'amélioration de la conception, en particulier pour les déploiements d'entreprise où l'environnement est étroitement contrôlé via des stratégies de groupe.

  1. Conditionnellement, est-il possible de compresser lors de l'emballage du seul exécutable?
    c'est-à-dire ajouter Wrap comme logique, donc nous n'avons pas besoin d'intégration d'autres outils.
    Le compressé produira des exe encore plus petits.

  2. Lors du lancement de l'exe, il développe son contenu dans un dossier temporaire. Pour notre produit, sur certains sites d'utilisateurs, les machines clientes sont étroitement contrôlées et ne permettent pas le lancement d'exécutables à partir du dossier temporaire ou même des emplacements %userprofile%.

Est-il possible de spécifier/contrôler où extraire ou peut-être "extraire en place" dans un ".\extract" ou un tel sous-dossier ?
Cela permet la conformité aux stratégies de groupe ainsi que la possibilité d'utiliser la fonction exe unique.

  1. Avant d'emballer, est-il possible de signer le dossier, puis de choisir les fichiers à emballer ?
    Nous pouvons signer l'exe unique, mais les fichiers d'extraction ne sont pas signés et, par conséquent, à certains autres emplacements clients, ils ne permettent pas l'exécution, à moins que les fichiers binaires ne soient signés.

Je voulais juste vous faire savoir, j'ai vu le même problème que @Safirion aujourd'hui. J'ai une application dotnetcore 3.0 ciblant ubuntu et je suis allé l'exécuter sur mon serveur Synology. Il ne voulait pas extraire - échouait toujours avec une erreur "Une erreur fatale s'est produite. Impossible d'extraire le contenu du bundle". Reconstruit plusieurs fois, mais la même chose. Après avoir redémarré l'hôte, cela a bien fonctionné à nouveau.

Serait utile de comprendre s'il y a un verrou de fichier ou quelque chose ici, et s'il y a des moments sur la façon de le déboguer.

@RajeshAKumar dotnet/core-setup#7940

Je ne sais pas comment ce lien aide.
Il ne parle que de l'extraction temporaire, j'ai énuméré 3 points ci-dessus.

Et je vous ai donné la solution pour l'un d'entre eux. je n'ai aucune idée pour les 2 autres

Et je vous ai donné la solution pour l'un d'entre eux. je n'ai aucune idée pour les 2 autres

L'extrait temporaire ne fonctionne pas pour nous, ce n'est donc pas la solution. Ma demande était de pouvoir contrôler où il extrait ou peut être extrait en place dans un sous-dossier.
Les administrateurs informatiques de bon nombre de nos ordinateurs clients n'autorisent pas l'exécution d'exécutables à partir de dossiers temporaires ou à partir d'un profil utilisateur.
Veuillez relire le message https://github.com/dotnet/coreclr/issues/20287#issuecomment -542497711

@RajeshAKumar : Vous pouvez définir le DOTNET_BUNDLE_EXTRACT_BASE_DIR pour contrôler le chemin de base où l'hôte extrait le contenu du bundle.
Veuillez voir plus de détails ici : https://github.com/dotnet/designs/blob/master/accepted/single-file/extract.md#extraction -location

@RajeshAKumar : La compression du single-exe fourni est une fonctionnalité à l'étude pour .net 5 : https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md#compression

Pour l'instant, vous devrez utiliser d'autres utilitaires pour compresser l'exe unique généré.

@RajeshAKumar , concernant la signature, vous pouvez signer tous les fichiers/binaires qui sont publiés et regroupés dans le single-exe. Lorsque l'hôte extrait les composants intégrés sur le disque, les fichiers individuels seront eux-mêmes signés. Vous pouvez également signer le fichier unique construit lui-même, comme vous l'avez mentionné.

Est-ce que cela répond à vos exigences ?

@Webreaper Si vous pouvez reproduire le problème, pouvez-vous exécuter l'application avec COREHOST_TRACE activé (définissez la variable d'environnement COREHOST_TRACE sur 1 ) et partagez le journal généré ? Merci.

@swaroop-sridhar
C'est une fonctionnalité très intéressante. Avez-vous un lien indiquant quand les différentes étapes seront disponibles dans quelle version de dotnet ?

@RajeshAKumar : Vous pouvez définir le DOTNET_BUNDLE_EXTRACT_BASE_DIR pour contrôler le chemin de base où l'hôte extrait le contenu du bundle.
Veuillez voir plus de détails ici : https://github.com/dotnet/designs/blob/master/accepted/single-file/extract.md#extraction -location

Merci swaroop-sridhar

@RajeshAKumar , concernant la signature, vous pouvez signer tous les fichiers/binaires qui sont publiés et regroupés dans le single-exe. Lorsque l'hôte extrait les composants intégrés sur le disque, les fichiers individuels seront eux-mêmes signés. Vous pouvez également signer le fichier unique construit lui-même, comme vous l'avez mentionné.

Est-ce que cela répond à vos exigences ?

J'essaie de comprendre comment casser la "compilation" et publier des parties.
J'utilise actuellement la commande suivante, elle ne me donne donc pas la possibilité de signer.
Définir publipargs=-c Release /p:PublishSingleFile=True /p:PublishTrimmed=True /p:PublishReadyToRun=false
dotnet publier -r win-x64 -o bin\Output\Win64 %publishargs%

Étant donné que les compilations ci-dessus ainsi que les garnitures et les packages, vous ne savez pas comment les casser.
Idéalement pour utiliser votre démarche, je devrai compiler, puis signer puis enfin publier.

@Webreaper Si vous pouvez reproduire le problème, pouvez-vous exécuter l'application avec COREHOST_TRACE activé (définissez la variable d'environnement COREHOST_TRACE sur 1 ) et partagez le journal généré ? Merci.

Merci. Il a disparu maintenant parce que j'ai redémarré, mais il est utile de le noter si cela se reproduit !

@RajeshAKumar , vous devrez marquer la signature sur une cible qui s'exécute juste avant le regroupement.
Étant donné que vous utilisez PublishReadyToRun et PublishTrimmed , vous ne pouvez pas utiliser les cibles standard Afterbuild ou BeforePublish .

Vous pouvez ajouter une cible qui s'exécute juste avant BundlePublishDirectory et effectue la signature.

@swaroop-sridhar
C'est une fonctionnalité très intéressante. Avez-vous un lien indiquant quand les différentes étapes seront disponibles dans quelle version de dotnet ?

Merci @etherealjoy. Le travail pour les fichiers uniques exécutés directement à partir du bundle est en cours, ciblant la version .net 5 à ma meilleure compréhension.

@RajeshAKumar , vous devrez marquer la signature sur une cible qui s'exécute juste avant le regroupement.
Étant donné que vous utilisez PublishReadyToRun et PublishTrimmed , vous ne pouvez pas utiliser les cibles standard Afterbuild ou BeforePublish .

Vous pouvez ajouter une cible qui s'exécute juste avant BundlePublishDirectory et effectue la signature.

Merci.
Le lien que vous avez donné ressemble à des tâches MS Build.
Comment créer un gestionnaire pour "BundlePublishDirectory" ? Est-ce dans Studio/Project props/Build Events ou dois-je créer quelque chose à partir de zéro.

@RajeshAKumar dans ce cas, vous aurez besoin de quelque chose de plus précis que les événements pré-construction post-construction.
Donc, je pense que vous devriez éditer le fichier de projet et ajouter quelque chose comme :

<Target Name="Sign" BeforeTargets="BundlePublishDirectory">
    ... 
</Target>

Quel est le comportement attendu de la commande dotnet pack avec ceci ? Disons que nous avons un artefact à un seul exe poussé vers le référentiel nuget local. Si j'essaie de l'installer avec chocolatey, il essaie de restaurer tous les deps de nuget répertoriés dans le fichier de projet. Ce qui était attendu auparavant, mais je doute que ce comportement soit correct pour SFD.

Est-il possible d'ajouter une barre de progression ou un indicateur de chargement lors de l'extraction d'une application WPF autonome à fichier unique, cela peut prendre un certain temps sans que rien ne se passe.
Une application WPF autonome de base fait plus de 80 Mo et l'extraction peut prendre plus de 5 secondes. Ce n'est pas très convivial et j'ai reçu des plaintes de mes utilisateurs finaux.

Edit : Un moyen de nettoyer automatiquement l'ancienne version au lancement ?

@Safirion Je ne vois pas comment cela pourrait être à la portée de cette fonctionnalité. Si vous en avez besoin, vous seriez mieux servi en créant votre propre petite application qui affiche un écran de démarrage et lance la vraie application, puis que la vraie application arrête le programme splashscreen lorsqu'il démarre.

@ProfessionalNihilist Je pense que vous ne comprenez pas mon propos.
Une application WPF vide et autonome utilise 80 Mo de stockage sur disque lors de la compilation. Vous ne pouvez pas avoir une application WPF plus petite que 80mo sans la compiler en tant qu'application dépendante du framework 😉
Le problème est le temps d'extraction du framework inclus avant même que l'application ne puisse se lancer. Cela doit donc être fait par le .Net Core et c'est totalement lié à cette fonctionnalité.

Peut-être ajouter la possibilité d'avoir un png qui serait affiché pendant que l'application est décompressée ?

@Safirion @ayende le manque de "retour d'interface utilisateur" lors du démarrage est suivi ici : https://github.com/dotnet/core-setup/issues/7250

Quel est le comportement attendu de la commande dotnet pack avec ceci ? Disons que nous avons un artefact à un seul exe poussé vers le référentiel nuget local. Si j'essaie de l'installer avec chocolatey, il essaie de restaurer tous les deps de nuget répertoriés dans le fichier de projet. Ce qui était attendu auparavant, mais je doute que ce comportement soit correct pour SFD.

@catlion la propriété PublishSingleFile n'est prise en charge que par la commande dotnet publish . Donc, cela n'a aucun impact sur dotnet pack . Y a-t-il une motivation à utiliser à la fois le fichier unique et l'emballage ?

Edit : Un moyen de nettoyer automatiquement l'ancienne version au lancement ?

@Safirion dans la version actuelle, le nettoyage est manuel, l'hôte ne tente pas de supprimer les fichiers extraits, car ils pourraient être potentiellement réutilisés lors de futures exécutions.

Ok, je vais faire mon propre nettoyant 😉
Merci pour votre réponse.

@cup qui n'a rien de spécial à propos de mono, c'est juste une compilation standard, ajoutez maintenant une référence de nuget et cette solution n'est plus un fichier unique. Mono a mkbundle pour obtenir un fichier unique

@Suchiman êtes-vous sûr? Mon exemple ci-dessus produit un seul fichier de 3 Ko. Alors que la taille minimale de dotnet semble être de 27 Mo :

https://github.com/dotnet/coreclr/issues/24397#issuecomment -502217519

@cup oui

C:\Users\Robin> type .\Program.cs
using System;
class Program {
   static void Main() {
      Console.WriteLine("sunday monday");
   }
}
C:\Users\Robin> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe .\Program.cs
Microsoft (R) Visual C# Compiler version 4.8.3752.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240

C:\Users\Robin> .\Program.exe
sunday monday
C:\Users\Robin> dir .\Program.exe


    Verzeichnis: C:\Users\Robin


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       10.11.2019     18:36           3584 Program.exe

@Suchiman êtes-vous sûr? Mon exemple ci-dessus produit un seul fichier de 3 Ko. Alors que la taille minimale de dotnet semble être de 27 Mo :

#24397 (commentaire)

Votre fichier 3k ne fonctionne que parce que mono est déjà installé. L'intérêt de la distribution de fichiers uniques dotnetcore est que vous n'avez pas besoin de clr installé, c'est un exe unique autonome comprenant le runtime.

@Webreaper en fait, je crois qu'il n'a utilisé que mcs de mono pour compiler, car il n'a pas écrit mono sun-mon.exe , il a probablement fonctionné sur .NET Framework.

Mais .NET Core prend également en charge le scénario de préinstallation du runtime, c'est-à-dire le déploiement dépendant du framework. Ce n'est toujours pas un déploiement de fichier unique dans ce cas, car il existe quelques fichiers supplémentaires pour .NET Core tels que .deps.json et .runtimeconfig.json

@ chris3713 La meilleure façon d'accéder à l'emplacement exe actuellement est de PInvoke-ing aux API natives. Par exemple : GetModuleFileNameW (Null, <buffer>, <len>)

Il semble Environment.CurrentDirectory soit une meilleure solution, même si je n'ai pas encore essayé les deux approches sur autre chose que Windows.

EDIT : Non. Ce chemin est susceptible de changer à différents points d'entrée dans l'application. Pas bien.

Sur une note légèrement connexe, j'ai trouvé cette régression dans la publication d'un fichier unique des applications Blazor dans le dernier aperçu de VS pour Mac : https://github.com/aspnet/AspNetCore/issues/17079 - Je l'ai signalé sous AspNeCore/Blazor, mais il se peut que cela soit plus pertinent pour le groupe coreclr - pas sûr. Je vous laisse le soin de vous déplacer !

@Suchiman attention, ce compilateur a des problèmes:

https://github.com/dotnet/roslyn/issues/39856

@cup sauf qu'en utilisant le chemin de fichier que j'ai nommé, vous utilisez l'ancien compilateur C# 5 écrit en C++, ce n'est pas roslyn et ils fermeront probablement ce problème pour cette raison. Mais Roslyn peut faire la même chose, juste un chemin différent...

Sur une note légèrement connexe, j'ai trouvé cette régression dans la publication d'un fichier unique des applications Blazor dans le dernier aperçu de VS pour Mac : aspnet/AspNetCore#17079 - Je l'ai signalé sous AspNeCore/Blazor, mais il se peut que cela est plus pertinent pour le groupe coreclr - pas sûr. Je vous laisse le soin de vous déplacer !

@Webreaper Merci d'avoir signalé le problème, qui ressemble à un problème ASP.net concernant les actifs statiques. Donc, c'est le bon endroit pour le déposer.

* Déplacer le message d'un autre numéro vers ici.

@swaroop-sridhar ,

Les temps de démarrage des applications DotNet Core Single File WPF sont beaucoup plus lents que ceux de l'application WPF originale ILMerge-ed construite sur .net 4.7. Est-ce à prévoir ou cela va-t-il s'améliorer à l'avenir ?

Les builds proviennent de mon ImageOptimizer : https://github.com/devedse/DeveImageOptimizerWPF/releases

| Taper | Temps de premier démarrage estimé | Deuxième temps de démarrage estimé | Taille | Lien de téléchargement |
| -- | -- | -- | -- | -- |
| .NET 4.7.0 + ILMerge | ~3 s | ~1 s | 39.3mb | LIEN |
| dotnet publish -r win-x64 -c Release --self-contained=false /p:PublishSingleFile=true | ~10 s | ~3 s | 49mb | |
| dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true | ~19 s | ~2 s | 201 Mo | |
| dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true | ~15 s | ~3 s | 136 Mo | LIEN |
| dotnet publier -r win-x64 -c Release | ~2,5 s | ~1,5 s | 223kb pour exe (+400mb en dll) | |

@devedse , pour s'en assurer, le "deuxième démarrage" est-il la moyenne de plusieurs runs (autres que le premier) ?
Je suis curieux, mais je n'ai aucune explication sur la raison pour laquelle l'exécution /p:PublishSingleFile=true /p:PublishTrimmed=true devrait être plus lente que l'exécution de ` /p:PublishSingleFile=true .

Donc, avant d'enquêter, je veux m'assurer que les nombres dans le "deuxième démarrage" sont des nombres stables et que la différence de démarrage est reproductible,

De plus, ce problème concerne les plugins à fichier unique, pouvez-vous déplacer la discussion sur les performances vers un nouveau problème ou vers dotnet/coreclr#20287 ? Merci.

@swaroop-sridhar , en réponse à votre question sur le fait qu'il s'agit de la moyenne :
Il est un peu difficile pour moi de chronométrer très précisément cela, donc le chronométrage a été fait en comptant pendant le démarrage de l'application, puis en l'essayant plusieurs fois pour voir s'il y avait une différence significative dans le temps de démarrage. Si vous connaissez une meilleure méthode, vous pouvez facilement la reproduire en construisant ma solution : https://github.com/devedse/DeveImageOptimizerWPF

Ma principale question porte sur la raison pour laquelle le démarrage d'une application groupée (fichier unique) prend plus de temps par rapport à un fichier .exe dégroupé.

Je peux me tromper ici, mais cela a du sens pour moi car il y a une surcharge avec un seul fichier. Essentiellement, vous avez une application qui démarre une autre application. Alors que l'ILMerge démarre directement. ILMerge n'a fusionné que les DLL référencées dans l'exe, il n'a pas enveloppé le tout dans une autre couche, ce qui est actuellement fait avec PublishSingleFile.

@devedse Le fichier unique consiste essentiellement à extraire, vérifier les sommes de contrôle, etc. avant de démarrer l'exécution de dotnet.
Je suppose que c'est pourquoi cela a pris ce temps.
L'extrait est "caché" donc lors de la prochaine exécution, il n'y a pas de surcharge d'E/S.

@RajeshAKumar , hmm extrait vraiment la voie à suivre dans ce scénario ? Ne serait-il pas préférable de suivre la méthode ILMerge et de fusionner les DLL en un seul ensemble ?

Surtout pour les fichiers .exe plus volumineux, vous induisez également le coût de l'espace disque pour stocker tous les fichiers deux fois.

@devedse Nous attendons tous les prochaines étapes de cette fonctionnalité (Run from Bundle) mais pour l'instant, c'est la seule solution. 😉

https://github.com/dotnet/designs/blob/master/accepted/single-file/staging.md

c'est ce que vous obtenez pour l'utilisation de JIT sur le bureau, démarrage lent, on dirait que seul Apple l'a compris

(Répéter principalement ce qui a déjà été dit):
Le premier démarrage devrait être beaucoup plus lent - il extrait l'application sur le disque - donc beaucoup d'E/S. Le deuxième démarrage et les démarrages suivants doivent être presque identiques à la version non à fichier unique de l'application. Dans nos mesures internes, nous n'avons pas vu de différence.

Comment mesurer : nous avons utilisé le traçage (ETW sous Windows) - il y a des événements lorsque le processus démarre, puis il y a des événements d'exécution qui peuvent être utilisés pour cela - ce n'est pas vraiment facile cependant.

Comme mentionné par @Safirion, nous travaillons sur la prochaine amélioration pour le fichier unique qui devrait exécuter directement la plupart du code géré à partir du .exe (pas d'extraction sur le disque). Je ne peux pas encore promettre un train de sortie.

JIT : Tout le framework doit être précompilé avec Ready2Run (CoreFX, WPF), donc au démarrage, seul le code de l'application doit être JIT. Ce n'est pas parfait, mais cela devrait faire une grande différence. Compte tenu des temps de démarrage d'environ 1 à 2 secondes, je pense qu'il l'utilise déjà dans tous les tests.

Merci à tous, je n'étais pas au courant des prochaines étapes prévues. Cela le clarifie.

Le premier démarrage devrait être beaucoup plus lent - il extrait l'application sur le disque - donc beaucoup d'E/S.

Cela n'aurait jamais dû arriver, vous rendez l'expérience utilisateur horrible PAR CONCEPTION, choix horrible, c'est ainsi que vous faites détester aux utilisateurs la technologie que le développeur utilise pour eux

Comme mentionné par @Safirion, nous travaillons sur la prochaine amélioration pour le fichier unique qui devrait exécuter directement la plupart du code géré à partir du .exe (pas d'extraction sur le disque). Je ne peux pas encore promettre un train de sortie.

Pourquoi sortir ça officiellement maintenant si ça va changer bientôt ? doit être marqué comme aperçu/expérimental

à mon avis, c'est une perte de temps et de ressources, concentrez-vous sur la compilation AOT et le tree-shaking, mettez toutes vos ressources là-bas, arrêtez avec les hacks

@RUSshy Pourquoi tant de haine ? Si vous ne voulez pas le délai de démarrage lors du premier lancement, n'utilisez pas le déploiement de fichier unique.

Je trouve que le démarrage est nettement inférieur à 10 secondes, et comme ce n'est que la première fois que vous exécutez, ce n'est pas du tout un problème. Je déploie une application Web côté serveur, ce qui signifie que dans la plupart des cas, elle démarrera une fois, puis fonctionnera pendant des jours/semaines, de sorte que l'extraction initiale est négligeable dans le schéma des choses - donc je préférerais de loin cela comme un bouche-trou jusqu'à ce qu'il y ait une seule image compilée, car cela rend le déploiement beaucoup plus facile que de copier des centaines de DLL autour de l'endroit.

+1 dans mon cas, nous avons un docker de construction générant un seul exe et un docker séparé pour exécuter l'application (en utilisant une image de docker Alpine standard sans dotnet). Après l'étape de construction, nous chargeons à chaud une fois le conteneur d'exécution et docker-commit la couche. Par la suite, nous n'avons observé aucune régression des performances par rapport à un déploiement dépendant du framework. Une fois que le mécanisme de chargement de fichiers à partir d'un bundle est implémenté et expédié, nous supprimerons l'étape intermédiaire de chargement à chaud.

@vitek-karas, y a-t-il un problème de suivi de la fonction "Charger les ressources d'exécution à partir du bundle" ? intéressés à comprendre quel genre d'obstacles sont là. :)

@am11 Nous sommes en train de mettre en place le plan détaillé. Vous pouvez regarder le prototype qui a été réalisé sur https://github.com/dotnet/coreclr/tree/single-exe. L'implémentation réelle ne sera probablement pas trop différente (de toute évidence une meilleure factorisation et ainsi de suite, mais l'idée de base semble être bonne).

@Webreaper Pour les applications Web, ce n'est pas du tout un problème, mais peut-être parce que .Net Core 3 est recommandé pour le développement WPF/WinForm maintenant, et que le partage d'une application de bureau .exe perdu dans une centaine de .dll n'est pas une option alors je suis totalement comprendre la frustration liée à la première étape de cette fonctionnalité.
;)

Et aucun utilisateur n'attend 10 secondes (ou plus de 3 secondes) avant de re-cliquer sur un exe aujourd'hui. Le fait qu'il n'y ait pas d'indicateur de chargement est le deuxième gros problème de cette fonctionnalité. Malheureusement, il semble que l'indicateur de chargement ne fera pas partie de .Net Core 3.1, les utilisateurs devront donc être patients...

Les développeurs de bureau attendent vraiment l'étape 2, et je pense que cela fera partie de .Net 5 car en fait, le développement de bureau dans .Net Core est une très mauvaise expérience pour les utilisateurs finaux.

@RUSshy Pourquoi tant de haine ? Si vous ne voulez pas le délai de démarrage lors du premier lancement, n'utilisez pas le déploiement de fichier unique.

ce n'est pas de la haine, ce sont des commentaires constructifs et honnêtes, je me soucie de C # et de .net, j'utilise les deux tous les jours, je ne veux pas qu'il soit remplacé par GO ou autre chose

tout recemment:
https://old.reddit.com/r/golang/comments/e1xri3/choosing_go_at_american_express/
https://old.reddit.com/r/golang/comments/ds2z51/the_stripe_cli_is_now_available_and_its_written/

les commentaires négatifs sont aussi utiles que les commentaires positifs, mais si vous le prenez comme de la "haine", je ne peux pas vous aider

La communauté .net est une voie silencieuse, passive et biaisée, la perturbation est la seule voie à suivre

.NET est objectivement la meilleure plate-forme pour la plupart des applications de nos jours. J'aimerais que plus de gens s'en rendent compte.

Les histoires de guerre que j'entends sur d'autres plateformes telles que Java, Go, Rust, Node, ... sont franchement dérangeantes. Ces plateformes sont des tueurs de productivité.

à mon avis, c'est une perte de temps et de ressources, concentrez-vous sur la compilation AOT et le tree-shaking, mettez toutes vos ressources là-bas, arrêtez avec les hacks

Je suis d'accord. .Net a un excellent système de typage. Trop souvent, il est contourné en utilisant la réflexion. L'outillage doit se concentrer sur l'AOT mais aussi sur la minimisation de la réflexion. https://github.com/dotnet/corert/issues/7835#issuecomment -545087715 serait un très bon début. L'erreur d'un milliard de dollars des valeurs nulles est désormais atténuée ; la même chose doit être faite avec la réflexion avec un paramètre ou un marqueur pour le code sans réflexion (ou sinon le code compatible avec l'éditeur de liens ou corert).

Éliminer la réflexion serait génial. Tant de souffrances pourraient être évitées si la réflexion était bannie. Mon histoire d'horreur la plus récente a été de découvrir que je ne pouvais pas déplacer le code parce que le framework utilisé (Service Fabric SDK) a trouvé prudent de lier les octets sérialisés au nom d'assemblage de l'implémentation du sérialiseur sans possibilité de remplacement.

Tout progrès visant à décourager la réflexion serait un progrès.

Btw cherchait un moyen de fusionner des assemblages pour réduire la taille des bundles et les temps de chargement, permettre l'optimisation de l'ensemble du programme. Je suppose que ce problème n'est pas vraiment ciblé là-dessus.

Edit : Depuis ce post a recueilli quelques réactions juste pour clarifier. Je pense que la méta-programmation devrait avoir lieu au moment de la conception, où le code est la donnée, et c'est sous mon contrôle.

Types que j'aime utiliser pour appliquer des invariants auxquels je peux faire confiance. Les réflexions d'exécution brisent cette confiance.

Par conséquent, j'aimerais que la réflexion à l'exécution soit remplacée par la méta-programmation au moment de la conception. Là où il pourrait également être plus puissant en chevauchant des cas d'utilisation tels que des analyseurs, des correctifs rapides et une refactorisation.

Marquage des abonnés à cette zone : @swaroop-sridhar
Avertissez danmosemsft si vous souhaitez vous abonner.

La conception de fonctionnalités à fichier unique se trouve dans ce document : https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/design.md
Suivi de la progression des applications à fichier unique dans ce numéro : https://github.com/dotnet/runtime/issues/36590.
Merci à tous pour vos commentaires et suggestions dans ce numéro.

Cette page vous a été utile?
0 / 5 - 0 notes