Runtime: Unterstützung der Einzeldateiverteilung

Erstellt am 5. Okt. 2018  ·  225Kommentare  ·  Quelle: dotnet/runtime

Dieses Problem verfolgt den Fortschritt der .NET Core 3.0-Einzeldateiverteilungsfunktion.
Hier ist das Designdokument und der Bereitstellungsplan für das Feature.

area-Single-File

Hilfreichster Kommentar

Der erste Start wird voraussichtlich viel langsamer sein – er extrahiert die App auf die Festplatte – so viel E / A.

Das hätte nie passieren dürfen, Sie machen die Benutzererfahrung BY DESIGN schrecklich, schreckliche Wahl, so bringen Sie Benutzer dazu, die Technologie zu hassen, die der Entwickler für sie verwendet

Wie von @Safirion erwähnt, arbeiten wir an der nächsten Verbesserung für Einzeldateien, die den größten Teil des verwalteten Codes direkt aus der EXE-Datei ausführen sollten (kein Extrahieren auf die Festplatte). Kann aber noch keinen Release Train versprechen.

Warum das jetzt offiziell veröffentlichen, wenn sich das bald ändern wird? sollte als Vorschau/experimentell gekennzeichnet sein

Meiner Meinung nach ist dies Zeit- und Ressourcenverschwendung, konzentrieren Sie sich auf die AOT-Kompilierung und das Tree-Shaking, legen Sie alle Ihre Ressourcen dort ab, hören Sie mit Hacks auf

Alle 225 Kommentare

Aus Interesse, wie lässt sich diese Initiative mit CoreRT vergleichen? Sie scheinen ähnliche Bemühungen zu sein?

Bezieht es sich auf „ möglicherweise nativen Benutzercode “, dh es wird weiterhin ermöglicht, dass Code JIT-kompiliert wird, nicht nur AOT?

Außerdem gehe ich davon aus, dass die Laufzeitkomponenten (" Nativer Code (Laufzeit, Host, native Teile des Frameworks.. ") diejenigen aus dem CoreCLR-Repository sein werden?

Sie stellen großartige Fragen, aber da dies noch am Anfang des Designs steht, habe ich noch keine großartigen Antworten.

Aus Interesse, wie lässt sich diese Initiative mit CoreRT vergleichen? Sie scheinen ähnliche Bemühungen zu sein?

Es würde wahrscheinlich ähnliche Ergebnisse geben (eine einzelne Datei), aber das Design kann unterschiedliche Leistungsmerkmale oder Funktionen aufweisen, die funktionieren/nicht funktionieren. Ein möglicher Entwurf könnte beispielsweise darin bestehen, im Wesentlichen alle Dateien in einer eigenständigen .NET Core-Anwendung in einer einzigen Datei zu verketten. Das sind 10 MB und könnten langsamer starten, aber auf der anderen Seite würde es die vollen Fähigkeiten von CoreCLR ermöglichen, einschließlich Laden von Plugins, Reflection Emit und erweiterter Diagnose. CoreRT könnte als das andere Ende des Spektrums angesehen werden – es ist einstellige MB und hat eine sehr schnelle Startzeit, aber da es kein JIT hat, kann es keine Plugins laden oder Reflexionsemission verwenden und die Build-Zeit ist langsamer als die meisten . NET-Entwickler daran gewöhnt sind. Es hat derzeit einige andere Einschränkungen, die im Laufe der Zeit besser werden könnten, aber durch .NET Core 3.0 möglicherweise nicht besser werden (möglicherweise sind Anmerkungen zur Reflexion erforderlich, einige Interop-Szenarien fehlen, eingeschränkte Diagnose unter Linux). Irgendwo dazwischen gibt es auch Ideen. Wenn Leute Kompromisse eingehen möchten, die sie eingehen/vermeiden möchten, wären wir neugierig, davon zu hören.

Bezieht es sich auf „möglicherweise nativen Benutzercode“, dh, dass Code weiterhin JIT-kompiliert werden kann, nicht nur AOT?

Mit „nativem Benutzercode“ meinte ich, dass Ihre App möglicherweise nativen C++-Code enthält (entweder von Ihnen geschrieben oder eine Komponente eines Drittanbieters). Es könnte Einschränkungen geben, was wir mit diesem Code tun können – wenn er in eine .dll kompiliert ist, ist die einzige Möglichkeit, ihn auszuführen, außerhalb der Festplatte; Wenn es sich um eine .lib handelt, ist es möglicherweise möglich, sie einzubinden, aber das bringt andere Komplikationen mit sich.

Außerdem gehe ich davon aus, dass die Laufzeitkomponenten ("Nativer Code (Laufzeit, Host, native Teile des Frameworks ...") die aus dem CoreCLR-Repo sind?

Basierend auf allem oben Gesagten werden wir herausfinden, welche Repos beteiligt sind. "Native Teile des Frameworks" würden native CoreFX-Dateien wie ClrCompression und Unix PAL umfassen.

Eine einzelne Dateiverteilung auf diese Weise kann für eine einfache Bereitstellung von unschätzbarem Wert sein, selbst wenn sie eine etwas langsamere Startzeit hat. Ich hätte viel lieber die Fähigkeit, die volle Macht zu haben, als gezwungen zu sein, etwas davon aufzugeben.

Einige Szenarien, die uns interessieren. Wie würde das plattformübergreifend funktionieren?
Ich nehme an, wir haben eine separate "Datei" pro Plattform?

Wie könnte ich in Bezug auf nativen Code verschiedene native Komponenten basierend auf der Plattform auswählen?

Einige Szenarien, die uns interessieren. Wie würde das plattformübergreifend funktionieren?
Ich nehme an, wir haben eine separate "Datei" pro Plattform?
Wie könnte ich in Bezug auf nativen Code verschiedene native Komponenten basierend auf der Plattform auswählen?

@ayende , ich zitiere aus dem Kommentar von @morganbr :

Ein möglicher Entwurf könnte darin bestehen, im Wesentlichen alle Dateien in einer eigenständigen .NET Core-Anwendung in einer einzigen Datei zu verketten.

Die aktuelle plattformübergreifende Geschichte für eigenständige Anwendungen besteht darin, ein Bereitstellungspaket pro Plattform zu erstellen, auf die Sie abzielen möchten, da Sie die Anwendung mit der Laufzeit ausliefern, die plattformspezifisch ist.

@morganbr Ich weiß es zu schätzen, dass Sie sich die Zeit genommen haben, eine so detaillierte Antwort zu geben

Ich bin gespannt, wohin das Design geht, das ist eine wirklich interessante Initiative

Ich habe ein paar Fragen an Leute, die Single-File verwenden möchten. Ihre Antworten helfen uns, unsere Optionen einzugrenzen:

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)
  2. Enthält Ihre App (nicht-.NET) C++/nativen Code?
  3. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?
  4. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?
  5. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?
  6. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?
  7. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?
  8. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?
  1. Konsolen-/UI-App auf allen Plattformen.
  2. Vielleicht als Drittanbieter-Komponente.
  3. Möglicherweise ja.
  4. Ja, insbesondere wenn es sich um ein einfaches ClickOnce-ähnliches System handelt.
  5. Eine anfängliche Verlangsamung kann toleriert werden. Kann Punkt 3 dabei helfen?
  6. Abhängig vom Vermögen. Hello World sollte eine Größe in der Größenordnung von MB haben.
  7. Egal, ob es nur um die Produktion geht.
  8. Möchten Sie Reflection-Zeug auf die Whitelist setzen? Jawohl.

@morganbr , denkst du, dass diese Fragen besser einem breiteren Publikum gestellt werden sollten; dh breiter als Leute, die von diesem GitHub-Problem wissen?

Ein möglicher Entwurf könnte beispielsweise darin bestehen, im Wesentlichen alle Dateien in einer eigenständigen .NET Core-Anwendung in einer einzigen Datei zu verketten.

Mit Blick auf das Komprimieren; oder mit einem komprimierten Dateisystem in der Datei?

@tpetrina , danke! Punkt 3 deckt einige Designwinkel ab:

  1. Tree Shaking passt nicht gut zum Laden von Plugins, die der Tree Shaker nicht gesehen hat, da es Code eliminieren könnte, auf den sich das Plugin stützt.
  2. CoreRT bietet derzeit keine Möglichkeit, Plugins zu laden
    Bei Punkt 5 geht es eher darum, ob wir die Größe oder die Startzeit optimieren würden (und wie viel)
    Punkt 8, ja, ich habe hauptsächlich an Reflexionssachen gedacht

@TheBlueSky , wir haben auch andere Leute kontaktiert, aber es hilft, Input von den leidenschaftlichen Leuten in der GitHub-Community zu bekommen.

@benaadams , Komprimierung liegt auf dem Tisch, aber ich betrachte sie derzeit als orthogonal zum Gesamtdesign. Leichte Experimente deuten darauf hin, dass das Zippen eine Größenreduzierung von etwa 50 % auf Kosten von mehreren Sekunden Startzeit (und Bauzeit) erreichen kann. Für mich ist das ein Kompromiss, der so radikal ist, dass er, wenn wir ihn machen, optional sein sollte.

@morganbr mehrere Sekunden Startzeit bei Verwendung der Komprimierung? Ich finde das kaum zu glauben, wenn man bedenkt, dass UPX Dekompressionsgeschwindigkeiten von behauptet

~10 MB/s auf einem alten Pentium 133, ~200 MB/s auf einem Athlon XP 2000+.

@morganbr , für mich lauten die Antworten:

1) Dienst (im Grunde eine Konsolen-App, auf der Kestrel ausgeführt wird). Wird als Windows-Dienst / Linux-Daemon oder im Docker ausgeführt.
2) Ja
3) Ja, typischerweise verwaltete Assemblys mit AssemblyContext.LoadFrom . Diese werden vom Endbenutzer bereitgestellt.
4) Ja, das wird erwartet. Tatsächlich bündeln wir sowieso bereits das gesamte Framework, also keine Änderung in dieser Hinsicht.
5) Als Service kümmern wir uns nicht so sehr um die Startzeit. 5 Sekunden wären angemessen.
6) 75 MB ist wahrscheinlich die Grenze. Vieles hängt von der tatsächlichen komprimierten Größe ab, da alle Pakete komprimiert geliefert werden.
7) Für Release-Builds sind längere (noch viel längere) Build-Zeiten akzeptabel.
8) Ja, absolut. Größe ist nicht so wichtig, aber kleiner ist besser.

Etwas, das ich nicht erwähnt gesehen habe und das sehr wichtig ist, ist die Debuggbarkeit davon.
Ich hoffe, dass dies keine Stack-Traces verstümmelt, und wir möchten in der Lage sein, pdb -Dateien oder eine Art Debugging-Symbole einzufügen.

Berücksichtigen Sie bei der Komprimierung die Tatsache, dass der eigentliche Zustellmechanismus in fast allen Fällen bereits komprimiert ist.
Zum Beispiel Nuget-Pakete.
Benutzer sind auch ziemlich versiert darin, Dinge zu entpacken, also ist das kein großes Problem.
Ich denke, man kann seitlich komprimieren.

Danke, @ayende! Sie haben Recht, dass ich die Debuggbarkeit hätte nennen sollen. Ich denke, es gibt nur ein paar geringfügige Möglichkeiten, wie das Debuggen beeinträchtigt werden könnte:

  1. Es ist möglicherweise nicht möglich, „Bearbeiten und fortfahren“ für eine einzelne Datei zu verwenden (da eine Möglichkeit zum Neuaufbau und erneuten Laden der ursprünglichen Baugruppe erforderlich ist).
  2. Der Einzeldateibuild erzeugt möglicherweise eine PDB oder einige andere Dateien, die für das Debuggen erforderlich sind, zusätzlich zu denen, die mit Ihren Assemblys geliefert wurden.
  3. Wenn CoreRT verwendet wird, verfügt es möglicherweise über einige Debugging-Funktionen, die im Laufe der Zeit ausgefüllt werden (insbesondere unter Linux/Mac).

Wenn Sie "PDB-Dateien einschließen" sagen, möchten Sie diese _in_ der einzelnen Datei oder nur die Möglichkeit haben, sie zu generieren und an ihnen festzuhalten, falls Sie den Einzeldatei-Build debuggen müssen?

1) Für uns kein Thema. E&C ist hier nicht relevant, da dies wahrscheinlich nur für den tatsächlichen Einsatz und nicht für den täglichen Gebrauch verwendet wird.
2) Idealerweise haben wir eine einzige Datei für alles, einschließlich der PDBs, nicht eine Datei und eine Reihe von PDBs an der Seite. Es gibt bereits die eingebettete PDB-Option, wenn das funktionieren würde, wäre es großartig.
3) Wenn ich über Debuggen spreche, spreche ich mehr über die Produktionszeit als über das Live-Anhängen eines Debuggers. Genauer gesagt, Stack-Trace-Informationen einschließlich Datei- und Zeilennummern, die Möglichkeit, Symbole beim Lesen von Dumps aufzulösen usw.

  1. Hauptsächlich Dienste, aber einige UI
  2. Einige tun es, aber das wäre nicht dringend
  3. Jawohl
  4. Jawohl
  5. Ein paar Sekunden sind ok
  6. Ist uns egal. Summe der DLL-Größe ist in Ordnung
  7. Idealerweise nicht
  8. Größe steht für uns nicht im Vordergrund

Eine andere Frage an uns ist, ob Sie dies auch für einzelne Komponenten tun könnten (vielleicht sogar inszeniert)? ZB haben wir Bibliotheks-DLLs, die viele Abhängigkeiten verwenden. Wenn wir diese paketieren könnten, würde das eine Menge Ärger bei der Versionsverwaltung usw. ersparen. Wenn diese wiederum in eine Exe gepackt werden könnten, wäre das noch schöner?

  1. Dienste und einige UI.
  2. Nicht im Moment.
  3. Jawohl. Idealerweise Plugins, die aus einem Ordner geladen und zur Laufzeit neu geladen werden können.
  4. Jawohl
  5. Kein Problem, solange wir nicht 10-15+ pushen.
  6. Summe der DLL-Größe oder ähnliches.
  7. Jawohl. Für eine Produktions-Build-Zeit ist nicht wirklich ein Problem, solange Debug-/Test-Builds relativ schnell erstellt werden.
  8. Hängt davon ab, aber die Option wäre praktisch.
  1. Service und Benutzeroberfläche.
  2. Manchmal.
  3. Ja, normalerweise.
  4. Jawohl.
  5. Am besten weniger als 5 Sekunden.
  6. Die UI ist weniger als 5 Sekunden, Service spielt keine Rolle.
  7. Die Bauzeit ist nicht wichtig, und der Optimierungseffekt ist der wichtigste.
  8. Jawohl.

@tpetrina @ayende @bencyoung @Kosyne @expcat Sie haben Frage 3 mit Ja beantwortet („Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?“) – können Sie uns mehr über Ihre Verwendung erzählen Fall?

Das Hauptverkaufsargument einer Einzeldateiverteilung besteht darin, dass nur eine Datei verteilt werden muss. Wenn Ihre App Plugins in separaten Dateien enthält, welchen Wert würden Sie dann ohnehin aus einer einzelnen Dateidistribution ziehen, die mehrere Dateien enthält? Warum ist "app.exe+plugin1.dll+plugin2.dll" besser als "app.exe+coreclr.dll+clrjit.dll+...+plugin1.dll+plugin2.dll"?

app.exe + 300+ DLLs - was heute der aktuelle Stand ist, ist wirklich umständlich.
app.exe + 1-5 DLLs, die normalerweise vom Benutzer selbst definiert werden, ist viel einfacher.

In unserem Szenario lassen wir bestimmte Erweiterungen durch den Benutzer zu, sodass wir normalerweise nur ein einzelnes exe bereitstellen und der Benutzer bei Bedarf zusätzliche Funktionen hinzufügen kann.

Es ist nicht so sehr, dass wir das _planen_, aber wir wollen es _können_, wenn die Notwendigkeit entsteht.

@ayende Einverstanden, dasselbe mit uns.

Wenn wir dies auf DLL-Ebene tun könnten, könnten wir auch Abhängigkeiten in unsere Assemblys packen, damit sie nicht mit Client-Assemblys in Konflikt geraten. Das heißt, indem Sie eine Version von NewtonSoft.Json auswählen, definieren Sie sie derzeit für alle Programme, Plugins und Drittanbieter-Assemblys im selben Ordner, aber wenn Sie sie einbetten könnten, hätten Drittanbieter Flexibilität und erhöhen die Versionskompatibilität

Stimme @ayende zu.

Danke an alle für eure Antworten! Basierend auf der Anzahl der Leute, die entweder nativen Code verwenden oder Plugins laden müssen, denken wir, dass der kompatibelste Ansatz, den wir verwalten können, der richtige Ausgangspunkt ist. Dazu gehen wir von einem „Pack and Extract“-Ansatz aus.

Dabei handelt es sich um Tools, die im Wesentlichen alle Anwendungs- und .NET-Dateien als Ressourcen in eine ausführbare Extraktordatei einbetten. Wenn die ausführbare Datei ausgeführt wird, extrahiert sie alle diese Dateien in ein temporäres Verzeichnis und wird dann ausgeführt, als ob die App als Nicht-Einzeldatei-Anwendung veröffentlicht worden wäre. Es wird nicht mit Komprimierung beginnen, aber wir könnten es möglicherweise in Zukunft hinzufügen, wenn dies gerechtfertigt ist.

Das kniffligste Detail dieses Plans ist, wohin Dateien extrahiert werden sollen. Wir müssen mehrere Szenarien berücksichtigen:

  • Erster Start – die App muss nur irgendwo auf der Festplatte extrahiert werden
  • Nachfolgende Starts – um zu vermeiden, dass bei jedem Start die Kosten für die Extraktion (wahrscheinlich mehrere Sekunden) bezahlt werden, wäre es vorzuziehen, dass der Extraktionsort deterministisch ist und es dem zweiten Start ermöglicht wird, Dateien zu verwenden, die beim ersten Start extrahiert wurden.
  • Upgrade – Wenn eine neue Version der Anwendung gestartet wird, sollte sie die von einer alten Version extrahierten Dateien nicht verwenden. (Umgekehrt ist es auch so; Leute möchten vielleicht mehrere Versionen nebeneinander laufen lassen). Das legt nahe, dass der deterministische Pfad auf dem Inhalt der Anwendung basieren sollte.
  • Deinstallieren – Benutzer sollten in der Lage sein, die extrahierten Verzeichnisse zu finden, um sie bei Bedarf zu löschen.
  • Fehlertoleranz – Wenn ein erster Start fehlschlägt, nachdem der Inhalt teilweise extrahiert wurde, sollte ein zweiter Start die Extraktion wiederholen
  • Ausführung mit erhöhten Rechten – Prozesse, die als Administrator ausgeführt werden, sollten nur von Speicherorten ausgeführt werden, die vom Administrator beschreibbar sind, um zu verhindern, dass Prozesse mit niedriger Integrität sie manipulieren.
  • Ausführung ohne erhöhte Rechte – Prozesse, die ohne Administratorrechte ausgeführt werden, sollten von Speicherorten ausgeführt werden, die vom Benutzer beschreibbar sind

Ich denke, wir können all dies berücksichtigen, indem wir einen Pfad konstruieren, der Folgendes beinhaltet:

  1. Ein bekanntes Basisverzeichnis (z. B. %LOCALAPPDATA%\dotnetApps unter Windows und Benutzerprofilspeicherorte unter anderen Betriebssystemen)
  2. Ein separates Unterverzeichnis für erhöhte
  3. Anwendungsidentität (vielleicht nur der Exe-Name)
  4. Eine Versionskennung. Die Zahlenversion ist wahrscheinlich nützlich, aber unzureichend, da sie auch genaue Abhängigkeitsversionen enthalten muss. Eine Anleitung oder ein Hash pro Build könnte angemessen sein.

Zusammen könnte das etwa so aussehen: c:\users\username\AppData\Local\dotnetApps\elevated\MyCoolApp\1.0.0.0_abc123\MyCoolApp.dll
(Wo die App MyCoolApp heißt, ihre Versionsnummer 1.0.0.0 und ihr Hash/Guid abc123 ist und sie mit erhöhten Rechten gestartet wurde).

Es ist auch Arbeit erforderlich, um Dateien in den Extraktor einzubetten. Unter Windows können wir einfach native Ressourcen verwenden, aber Linux und Mac erfordern möglicherweise benutzerdefinierte Arbeit.

Schließlich sind möglicherweise auch Anpassungen im Host (um extrahierte Dateien zu finden) und Diagnosen (um den DAC oder andere Dateien zu finden) erforderlich.

CC @swaroop-sridhar @jeffschwMSFT @vitek-karas

Ich habe das Gefühl, dass dieses Heilmittel schlimmer ist als die Krankheit. Wenn wir uns mit externen Verzeichnissen (je nach Betriebssystem unterschiedlich), Aktualisierungen, Deinstallationen und dergleichen befassen müssen, widerspricht dies meinem Grund, diese Funktion überhaupt zu wünschen (alles einfach, portabel, in sich abgeschlossen und sauber zu halten).

Wenn es unbedingt so sein muss, würde ich für mein Projekt eine einzelne ausführbare Hauptdatei und die entpackten Dateien in einem Verzeichnis neben dieser ausführbaren Datei bevorzugen, oder möglicherweise die Möglichkeit, zu entscheiden, wohin dieses Verzeichnis gehört.

Das bin aber nur ich, ich bin neugierig, auch von anderen zu hören.

Ich muss hier zustimmen, dass die Verwendung eines anderen Verzeichnisses viele spannende Probleme haben kann - zB Sie platzieren eine Konfigurationsdatei neben der exe und diese exe wird nicht abgeholt, weil das "echte" Verzeichnis woanders liegt.
Speicherplatz könnte ein Problem sein, auch zufällige Dateisperren aufgrund von Zugriffsrichtlinien usw. pp.
Ich würde diese Funktion gerne verwenden, aber nicht, wenn sie eine Vielzahl von Fehlermodi hinzufügt, die vorher nicht erkannt werden können.

Vereinbart mit @Kosyne - Die vorgeschlagene ursprüngliche Lösung scheint einfach eine Art "Installer" zu automatisieren. Wenn dies die Grenze des Problems wäre, das wir mit einer einzelnen Führungskraft zu lösen versuchen, dann hätten wir diese Automatisierung meiner Meinung nach alle einfach selbst durchgeführt.

Das Hauptziel des Single-Exec-Vorschlags sollte es sein, eine ausführbare Datei auf einem nicht verwalteten System ausführen zu können. Wer weiß, ob es überhaupt Schreibzugriff auf ein beliebiges Ziel-"Installationsverzeichnis" hat? Es sollte sicherlich auch nach dem Start keine Artefakte von sich selbst hinterlassen (nicht standardmäßig).

Als kleine Modifikation des bestehenden Vorschlags, um das Obige zu erfüllen: Könnten wir nicht in den Speicher entpacken und von dort aus laufen?

Stimme den restlichen Kommentaren zu. Das Entpacken an einen anderen Ort ist etwas, das _bereits_ verfügbar ist.
Wir können einen selbstextrahierenden Reißverschluss haben, der die extrahierten Werte ziemlich einfach ausführt. Das beantwortet nicht viele der Bedenken, die hier beantwortet werden sollen, und ist nur ein anderer Name für die Installation.

Der Speicherort der Datei ist wichtig. In unserem Fall würde das zum Beispiel bedeuten:

  • Suchen der Konfigurationsdatei (die wir spontan generieren, wenn sie nicht vorhanden ist, und den Benutzer anpassen lassen)
  • Suchen / Erstellen von Datendateien, die normalerweise relativ zur Quell-Exe sind.
  • Die PID / der Name des Prozesses sollten übereinstimmen, um eine ordnungsgemäße Überwachung / Unterstützung zu gewährleisten.

Einer unserer Benutzer muss unsere Software von einer DVD ausführen, wie funktioniert das, auf einem System, das möglicherweise keine Festplatte hat, auf der es ausgeführt werden kann.

Ich stimme zu, dass es besser wäre, alles im Gedächtnis zu behalten. Und die Sorge um die Startzeit ist nicht so groß, ich würde es gut finden, dies für jeden Neustart zu bezahlen oder manuell einen Schritt zu tun, um dies bei Bedarf zu lindern.

Ein weiteres Problem hier ist die tatsächliche Größe. Wenn dies nur (effektiv) ein Installationsprogramm ist, bedeutet das, dass wir über Dateigrößen für eine vernünftige App in den Hunderten von MB sprechen, oder?

Es scheint, dass das Erstellen der vorgeschlagenen Lösung keine (vielen, wenn überhaupt) CLR-Änderungen erfordert. Benutzer können bereits eine solche Lösung erstellen. Es hat keinen Sinn, dies zu CoreCLR hinzuzufügen. Vor allem, da der Anwendungsfall dafür ziemlich eng und spezifisch ist.

@GSPP Das scheint im Grunde etwas zu sein, das ich heute mit 7z-Extra machen kann. Ich stimme zu, dass es in diesem Fall besser wäre, es überhaupt nicht zu haben.

Tut mir leid, dass ich zu spät zu dieser Party komme. Ich bin hierher gekommen, nachdem ich einem Link gefolgt bin, der in einem doppelten Ticket gepostet wurde, das ich verfolgt habe.
Nachdem ich die neuesten Kommentare hier gelesen habe, tut es mir leid zu sehen, dass Sie das Packen und Extrahieren in Betracht ziehen. Das scheint ein Overkill zu sein, warum nicht mit der Möglichkeit beginnen, SFAs für einfache Konsolen-Apps bereitzustellen? Es scheint mir möglich zu sein, eine rudimentäre Konsolen-App mit einigen Netzwerk-, IO- und einigen externen Abhängigkeiten (Nuget usw.) zu erstellen, die sich in einer einzigen Datei befinden.
Ich denke, was ich sagen will, ist, dass, anstatt die Anforderungen aller zu sammeln, die Anforderungen von niemandem zu sammeln und stattdessen klein mit einer ersten Iteration anzufangen, die für alle sinnvoll ist und schnell Ergebnisse liefert.

Das scheint im Grunde etwas zu sein, was ich heute mit 7z-Extra machen kann

Sie haben Recht, dass es heute eine Reihe von Lösungen gibt, die von der Programmierumgebung unabhängig sind, um dieses Problem anzugehen. Ein weiteres Beispiel von vielen: https://www.boxedapp.com/exe_bundle.html

Der Mehrwert hier wäre die Integration in das dotnet-Tooling, sodass auch nicht erfahrene Benutzer dies problemlos tun können. Erfahrene Benutzer können dies heute tun, indem sie vorhandene Tools zusammenfügen, wie Sie darauf hingewiesen haben.

Ich persönlich stimme Ihnen zu, dass es nicht klar ist, ob wir hier die richtige Wahl treffen. Darüber haben wir im Kernteam viel diskutiert.

Es wäre genauso gut, einen Praktikanten einzusetzen und ein globales Tool herauszubringen (das empfohlen, aber nicht unterstützt wird), und es kann auch ziemlich einfach zu installieren sein.

Tatsächlich sprechen wir über dotnet publish-single-file und das würde alles tun, was hinter den Kulissen erforderlich ist.

Ich sehe nichts, was vom Framework oder der Laufzeit tatsächlich benötigt wird, um dieses Szenario zu unterstützen, und indem Sie dies zu etwas machen, das explizit außerhalb des Frameworks liegt, werden Sie den Benutzern viel mehr Freiheit geben, wie Sie dies ändern können.
Keine "Notwendigkeit" für eine PR (mit all der damit verbundenen Zeremonie, Rückwärtskompaktierung, Sicherheit usw.), die Sie erhalten würden, wenn Sie eine Änderung am Framework vornehmen möchten.
Sie forken einfach ein gemeinsames Nebenprojekt und verwenden das.

Beachten Sie, dass ich, so sehr ich diese Funktion auch haben möchte, lieber nichts drin haben möchte (was bedeutet, dass es _immer_ drin sein wird), das genauso gut von außen gemacht werden kann.

Ich möchte eine übergeordnete Frage stellen: Was ist die Hauptmotivation für Kunden, die eine Einzeldateiverteilung wünschen?
Ist es in erster Linie:

  1. Verpackung? Wenn ja, unabhängig davon, ob es sich bei der Lösung um eine Inbox-Lösung oder ein Tool eines Drittanbieters handelt, welche Eigenschaften sind am wichtigsten?
    a) Anlaufzeit (über den ersten Lauf hinaus)
    b) Fähigkeit zur Ausführung in nicht beschreibbaren Umgebungen
    c) Keine Dateien nach dem Lauf zurücklassen
    d) Kein Installationsprogramm ausführen zu müssen
    2) Leistung?
    a) Geschwindigkeit (statisches Linken von nativem Code, Vermeidung mehrfacher Bibliotheksladevorgänge, modulübergreifende Optimierungen etc.)
    b) Codegröße (benötigt nur ein Zertifikat, Tree Shaking usw.)
    3) Irgendwelche anderen?

Ich bin ein bisschen besorgt, dass dieses Feature von einigen als nicht so wichtig gelesen wird oder zumindest kein gutes Ziel ist, um es hier in das Kernfeatureset aufzunehmen. Ich möchte nur wiederholen, dass ich denke, dass es für jede Anwendung, die als Dienst oder Untermodul einer größeren Anwendung fungiert, immens leistungsfähig wäre. Eines, bei dem Sie als Autor vielleicht nicht einmal der Entwickler sind. Ich möchte keine Abhängigkeitsanforderungen weitergeben müssen, die nur mit Installationen (automatisch oder anderweitig) oder Post-Execution-Artefakten auf der Festplatte gelöst werden können, die möglicherweise eine zusätzliche Sicherheitserhöhung durch den Benutzer usw. erfordern.
Im Moment ist .NET einfach keine gute Wahl für dieses Nischenproblem. Aber es könnte sein (und sollte IMO sein).

Die kompilierte ausführbare Datei muss:

  • Packen Sie alle relevanten Abhängigkeiten
  • Keine Ausführungsartefakte haben (keine Festplattenschreibvorgänge)

Re @swaroop-sridhar Ich wage zu behaupten, dass jede Anwendung ihre eigene einzigartige Reihenfolge der Leistungsanforderungen haben wird, und daher würde ich mir vorstellen, dass der beste Ansatz, nachdem wir uns mit der Kernlösung befasst haben, darin besteht, die niedrig hängenden Früchte zu pflücken und von dort aus weiterzumachen.

@swaroop-sridhar Für mich geht es um Verpackung und Benutzerfreundlichkeit für den Endbenutzer.
Sie müssen sich nicht mit der Installation von systemweiten Dingen befassen, klicken Sie einfach und führen Sie es aus.

Dies ist wichtig, da wir die Einbettung unserer Software zulassen und ein einzelnes Datei-Addon viel einfacher zu verwalten ist.

@strich Der Punkt zum Einbetten ist gut. Wir werden häufig als Komponente in einer Microservice-Architektur verwendet, und die Reduzierung des Bereitstellungsaufwands wird dies vereinfachen.

Das Problem ist nicht, was auch immer oder nicht, dies ist eine wichtige Funktion. Das Problem ist, was auch immer die vorgeschlagene Lösung (an dieser Stelle im Wesentlichen das Zippen von Dingen) sein muss, um _im Kern_ zu sein.
Sachen, die im Kern sind, haben einen viel höheren Standard für Änderungen. Es wäre besser, dies als externes Tool zu haben, da es einfacher zu ändern und zu erweitern ist.

Um ehrlich zu sein, würde ich viel lieber eine bessere Option insgesamt sehen. Beispielsweise ist es möglich, statt Dateien DLLs aus dem Speicher zu laden (erfordert etwas Arbeit, ist aber möglich).
Wenn das passiert, können Sie das _gesamte_ Ding rein aus dem Speicher ausführen, wobei das Entpacken in den reinen Speicher und ohne Festplattenzugriffe erfolgt.

Das sollte in den Kern gehen, da sehr wahrscheinlich Änderungen an der Laufzeit erforderlich sind, um dies zu ermöglichen.
Und das wäre an und für sich wertvoll. Und nichts, was wir derzeit tun können.

Ein gutes Beispiel ist also die Erfahrung von Go-Tools wie Consul von Hashicorp. Eine einzelne exe-Datei, die Sie auf einem beliebigen Computer ablegen und ausführen können. Keine Installationsprogramme, kein Kopieren von Ordnern, kein Suchen nach Konfigurationsdateien in Listen mit Hunderten von Dateien, nur eine wirklich nette Endbenutzererfahrung.

Für uns bin ich mir nicht sicher, ob der In-Memory-Ansatz funktionieren würde, da wir auch möchten, dass dies auch für Plugin-DLLs funktioniert (das Löschen eines Plugins wäre also auch eine einzelne Datei und nicht alle seine Abhängigkeiten), aber jeder Fortschritt würde dies tun gut sein. Wir haben uns Fody.Costura angesehen und das funktioniert gut für einige Sachen, aber wir hatten Probleme mit .NET Core dafür.

Ein gutes Beispiel ist also die Erfahrung von Go-Tools wie Consul von Hashicorp

Eh, für Tools wie consul wäre die ideale Lösung corrt, nicht diese selbstextrahierende Improvisation.

@mikedn Warum ist das so? Ich sehe nicht, was die AOT- oder JIT-Kompilierung mit der Bereitstellungsmethode zu tun hat?

Ich möchte mich den Worten von @strich anschließen , die Bereitstellung einzelner Dateien wäre ein Hauch frischer Luft für die Bereitstellung von Microservice-Architekturen sowie für jede Konsolen-App, die ein kleines Tool mit Befehlszeile ist – oder zumindest ihr Leben als solches beginnt Schalter.

Warum ist das? Ich sehe nicht, was die AOT- oder JIT-Kompilierung mit der Bereitstellungsmethode zu tun hat?

Weil es Ihnen genau das gibt, was Sie wollen – eine einzige Exe-Datei, die Sie auf jedem Computer ablegen und ausführen können (na ja, auf jedem Computer mit einem geeigneten Betriebssystem, es ist schließlich eine native Datei). Es neigt auch dazu, weniger Ressourcen zu verbrauchen, was für Agenten wie Consul eine gute Sache ist. Es ist so ziemlich das Äquivalent zu dem, was Go Ihnen bietet, mehr als eine Selbstextraktionslösung.

@mikedn denke ich, aber

1) Es existiert noch nicht wirklich in einer Produktionsform (soweit ich weiß)!
2) Wir verwenden viele dynamische Funktionen (IL-Generierung, beliebige Reflexion)
3) Wir wollen immer noch Plugins hinzufügen können (wieder ideal komprimiert)

Sehen Sie, da es in dieser Ausgabe darum ging, die Leute zu fragen, was sie wollen, geben wir nur unsere Meinung ab! Wir wollen nicht wirklich auf ein anderes Laufzeitmodell umsteigen müssen, nur um diesen Vorteil zu nutzen. Für mich sind sie orthogonale Anliegen

Ich sehe nicht, was die AOT- oder JIT-Kompilierung mit der Bereitstellungsmethode zu tun hat?

Ohne JIT ist es einfacher, Dinge wie die Debugging-Geschichte gut genug zu machen. Der JIT-Teil macht das Problem schwieriger, weshalb Sie ihn in Go nicht finden werden. Das ist Engineering, also setzen Sie entweder mehr Ingenieure auf das schwierigere Problem und leben mit der neuen Komplexität oder schränken es an anderer Stelle ein. Beim Selbstextrahierer geht es darum, den Umfang zu verringern, da die Anzahl der Ingenieure mit den erforderlichen Fähigkeiten begrenzt ist.

Leute mit Projekten, die eher Go-Projekten ähneln (keine JIT-Anforderungen), könnten mit CoreRT ziemlich zufrieden sein, wenn sie mit dem Label „experimentell“ darauf einverstanden sind. Heutzutage ist es ziemlich einfach, es zu versuchen . Es verwendet denselben Garbage Collector, Codegenerator, CoreFX und den größten Teil von CoreLib wie die vollständige CoreCLR und erzeugt kleine ausführbare Dateien (einstellige Megabytes), die in sich geschlossen sind.

Es existiert noch nicht wirklich in einer Produktionsform (soweit ich weiß)!

Ja, mein Kommentar richtete sich hauptsächlich an MS-Leute : grins:. Sie haben all diese parallelen, verwandten, laufenden Projekte/Ideen (corert, illinker) und jetzt fügen sie eine weitere hinzu, diese Selbstextraktionssache, die, wie viele bereits betont haben, ein bisschen wie ein „meh, das können wir tun wir selbst" so etwas. Und es hat auch Nachteile, wie das Extrahieren von Dateien in ein „verstecktes“ Verzeichnis.

Wir verwenden viele dynamische Funktionen (IL-Generierung, beliebige Reflexion)

Das ist etwas, worüber die Community als Ganzes vielleicht noch einmal nachdenken sollte. Sicher, es ist nützlich, dies tun zu können, aber es kollidiert mit anderen Wünschen wie der Bereitstellung einzelner Dateien. Sie können immer noch eine Einzeldateibereitstellung erhalten, aber das ist in der Regel mit Kosten verbunden – eine ziemlich große Datei. Wenn du damit einverstanden bist, dann ist das vollkommen in Ordnung. Aber meiner Erfahrung nach wird der Aspekt "Einzeldatei" umso weniger nützlich, je größer die Datei wird.

@MichalStrehovsky sicher, es gibt verschiedene Möglichkeiten. Für uns können wir jedoch nicht experimentell verwenden (zu überzeugen, dass es an der Zeit war, zu .NET Core zu wechseln, war schwer genug), und ich glaube nicht, dass das Extrahieren in einen temporären Ordner in unserem Fall auch funktionieren wird. Im schlimmsten Fall machen wir jedoch so weiter wie bisher und verwenden diese Funktion nicht.

Es ist etwas, das wir uns wünschen würden, wenn es so läuft, wie wir es uns wünschen :)

@mikedn Ich stimme zu. Mehrere parallele Lösungen sind noch verwirrender. Ich denke, unsere ideale Lösung wäre eine Art Super-ILLinker/Weaver-Ansatz, aber ich lasse das gerne spielen und sehe, wo wir landen.

Ich freue mich wirklich sehr über die Landung dieser Funktionalität, aber ehrlich gesagt bin ich ebenso wenig begeistert von dem ursprünglichen Vorschlag, den Sie bei @morganbr gepostet haben. Meine Antworten auf die Liste der von Ihnen gestellten Fragen ähneln denen, die andere gepostet haben (also denke ich, dass es einen gemeinsamen gewünschten Satz von Funktionen gibt), aber meiner Meinung nach ist die vorgeschlagene Lösung „Auf Festplatte entpacken“ überhaupt nicht das, was ich mir erhoffe umgesetzt und wie andere sagten, wäre fast schlimmer als die 'Krankheit'. @jkotas

Ich stimme @strich und @ayende zu
Die kompilierte ausführbare Datei muss:
Packen Sie alle relevanten Abhängigkeiten
Keine Ausführungsartefakte haben (keine Festplattenschreibvorgänge)

Das Laden von .dlls aus dem Speicher statt von der Festplatte ist möglicherweise nicht einfach, aber das ist die Art von Funktionen, die meiner Meinung nach das tiefgreifende Fachwissen von MSFT-Low-Level-Entwicklern wert wären (und dann in CoreClr genutzt werden) im Vergleich zum obigen Vorschlag, der einfach als implementiert werden könnte ein externes Tool (und hat es bereits, siehe https://github.com/dgiagio/warp). Wenn dies erreicht würde, frage ich mich, wie viel Zeitunterschied es zwischen dem ersten und den nachfolgenden Läufen geben würde? Als Inspiration/Beispiel denke ich, dass Linux 3.17+ memfd_create hat, das von dlopen verwendet werden kann.

Zu einem anderen Thema frage ich mich, ob die Anforderung zur Unterstützung von Plugins den Designvorschlag überindiziert? Würde es sich lohnen, diese Funktionalität zu aktivieren, sodass nur die Personen, die diese Funktion benötigen, die potenziellen Strafen tragen (fehlendes Baumschütteln usw.) und alle anderen (bedeutende Mehrheit?) eine reduzierte bereitstellbare Größe, Leistungsvorteile (?)

Wenn ich @swaroop-sridhar @MichalStrehovsky zurücktrete , sehe ich zwei breite Anwendungsfälle, die möglicherweise so unterschiedliche Ziele/Wünsche haben, dass es schwierig wird, alle mit einer Lösung unterzubringen:

  • CLI-Tools wollen idealerweise jedes Mal schnell laufen, klein verteilbar; vielleicht besser geeignet für CoreRT?
  • Microservice kann wahrscheinlich eine längere Erstausführung (idealerweise <1 s) und eine größere Verteilung tolerieren, im Austausch für umfangreichere Funktionen wie JIT und dynamische Codefunktionen.

Ich hoffe, dieser Braindump macht Sinn, ich versuche nicht, ein Idiot zu sein, sondern nur Feedback zu geben, weil ich mich sehr für dieses Thema interessiere. Vielen Dank für all Ihre harte Arbeit und das Einholen von Community-Beiträgen! :)

Über Plugins.
Im Grunde möchte ich nur, dass _nicht_ bei Assembly.LoadFrom - oder LoadLibrary -Anrufen blockiert wird.
Ich brauche nichts weiter und kann den Rest alleine erledigen.

@ayende Kannst du bitte etwas genauer erklären, was du damit meinst, "bei LoadFrom und so blockiert zu werden"?

Einige der Vorschläge dafür enthielten beispielsweise CoreRT, was bedeutete, dass wir (wahrscheinlich) nicht in der Lage wären, einfach eine verwaltete DLL zu laden.
Aber solange ich einen Pfad zu einer verwalteten DLL angeben und eine Assembly abrufen oder LoadLibrary für eine native DLL aufrufen kann, bin ich damit einverstanden, dass dies der Plugin-Mechanismus ist.

Ich sage dies, um klarzustellen, dass Plugin-Szenarien nicht etwas sind, das _überlegt_ werden sollte, sondern eher etwas, das nicht _blockiert_ werden sollte.

Ich habe einige Zeit damit verbracht, mich in den Code einzuarbeiten, und auf den ersten Blick scheint es so, als ob es _möglich_ sein sollte (ich spreche nur von Windows, um die Dinge zu vereinfachen):

  • Packen Sie die gesamte CoreCLR in eine Exec (sagen wir, sie ist als eingebettete Ressource oder so ähnlich).
  • Zählen Sie die nativen DLLs auf, rufen Sie so etwas wie MemoryModule (https://github.com/fancycode/MemoryModule) auf, um sie in den Arbeitsspeicher zu laden
  • Rufen Sie die Laufzeit auf und laden Sie eine Assembly aus dem Speicher.

Ich gehe mal davon aus, dass das _nicht_ so einfach ist. Beispielsweise bietet ICLRRuntimeHost2::ExecuteAssembly keine Möglichkeit, ihm einen Puffer zu geben, sondern nur eine Datei auf der Festplatte.
Das macht es zum ersten (von denen ich sicher bin, dass es viele geben wird) Showstopper, um es tatsächlich zum Laufen zu bringen.

Ich bin mir ziemlich sicher, dass es eine Menge Code gibt, der sich auf verwandte Dinge als Dateien bezieht, die möglicherweise fehlschlagen, aber das ist die Art von Dingen, die ich meine, wenn ich sage, dass ich eine einzelne Datei ausführen möchte und warum so etwas Die Lösung muss in der CoreCLR und nicht extern erfolgen (wie im Zip-Beispiel).

Rufen Sie so etwas wie MemoryModule auf

Die mit MemoryModule geladenen Binärdateien sind nicht diagnostizierbar (z. B. funktioniert keiner der regulären Debugger, Profiler usw. mit ihnen), und MemoryModule überspringt alle integrierten Sicherheitsmaßnahmen des Betriebssystems (z. B. Antiviren usw.). Es ist nicht etwas, das wir jemals als unterstützte Lösung ausliefern könnten.

Ich gehe davon aus, dass dies nicht so einfach ist.

Richtig, es wären neue APIs erforderlich (sowohl verwaltete als auch nicht verwaltete), um die Ausführung aus einem nicht erweiterten Einzeldateipaket zu unterstützen. Die vorhandenen Programme und Bibliotheken würden nicht "einfach funktionieren".

Könnte es eine vernünftige Frage sein, ob die Anti-Malware-Scan-Schnittstelle vorhanden ist
von Windows-Ingenieuren auf MemoryModule implementiert, wie es kürzlich für war
alle .net-Assemblys, einschließlich der aus mem geladenen?

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

BEARBEITEN: Hmm MemoryModule klang wie etwas, das zum Laden nativer Module in das Betriebssystem integriert ist, aber anscheinend ist es das nicht, das ist wahrscheinlich Grund genug, meinen obigen Vorschlag zu ignorieren

Am Mi, 5. Dez. 2018, 01:46 schrieb Jan Kotas [email protected] :

Rufen Sie so etwas wie MemoryModule auf

Die mit MemoryModule geladenen Binärdateien sind nicht diagnostizierbar (z. B. keine von
die regulären Debugger, Profiler usw.) werden an ihnen arbeiten, und MemoryModule
überspringt alle eingebauten Sicherheitsmaßnahmen des Betriebssystems (z. B. Virenschutz usw.). Es ist nicht
etwas, das wir jemals als unterstützte Lösung liefern könnten.

Ich gehe davon aus, dass dies nicht so einfach ist.

Richtig, es wären neue APIs erforderlich (sowohl verwaltete als auch nicht verwaltete).
Unterstützung der Ausführung aus einem nicht erweiterten Einzeldateipaket. Die bestehende
Programme und Bibliotheken würden nicht "einfach funktionieren".


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/dotnet/coreclr/issues/20287#issuecomment-444314969 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AEBfudvVHxpbeKa-L_vTQjbnNZZsn6Meks5u1xdlgaJpZM4XK-X_
.

Danke für alle Rückmeldungen.
Wir werden in Kürze einen aktualisierten Plan zur Unterstützung der Einzeldateiverteilung veröffentlichen.

@NinoFloris siehe dotnet/coreclr#21370

Mir ist klar, dass ich zu spät zu dieser Diskussion komme, also entschuldige ich mich, wenn das nicht hilft.

Um zu wiederholen, was @mikedn gesagt hat: Es kann verwirrend sein, all diese parallelen Lösungen zu haben, und es stellt sich die Frage, wo der Schwerpunkt von MS in Zukunft liegen wird. Die Tatsache, dass die brillante Arbeit an CoreRT immer noch als experimentell bezeichnet wird, ohne dass eine offizielle Roadmap vorliegt und ähnliche Funktionen in CoreCLR (CPAOT, jetzt Einzeldateiveröffentlichung) implementiert sind, macht es schwierig, Geschäftsentscheidungen auf der Grundlage der Technologie zu treffen. Ich würde nicht wieder das falsche Pferd wählen wollen (Silverlight...).

Warum nicht bei der brillanten Laufzeit in CoreRT bleiben und die Arbeit auf die Integration eines JIT (und die Erweiterung der Interpreterarbeit, bis diese fertig ist) in CoreRT für diejenigen konzentrieren, die volle Framework-Funktionen wünschen, während sie dennoch nativen Code für sie erstellen? Wäre es nicht möglich, im Falle des Wunsches nach JIT-Fähigkeiten die Metadaten und JIT in einer nativ kompilierten ausführbaren CoreRT-Datei zu behalten?
Wäre das nicht die beste aller Welten? Z.B. Sie hätten die kleinsten ausführbaren Dateien, die schnellste Startzeit, die Einschränkungen des AOT-Codes in CoreRT könnten erweitert werden, indem ein JIT vorhanden ist und die Metadaten und der IL-Code für diejenigen beibehalten werden, die die volle Framework-Funktionalität beibehalten möchten.
Meiner Meinung nach sollte der Fokus auf der „bestmöglichen“ Lösung liegen und nicht auf kurzfristiger Funktionalität, die von langfristigen Zielen ablenken könnte.

Vielleicht irre ich mich, aber ich denke, dass die Veröffentlichung einer einzelnen Datei als Teil von CoreCLR Kunden noch weiter von CoreRT ablenken würde, was in vielen Fällen eine potenziell bessere Lösung für sie wäre. Z.B. Wenn dies als "Jetzt können Sie Ihren .NET-Code als einzelne Datei veröffentlichen" gebrandmarkt wird, aber riesige Dateien erstellt, die Startleistung leidet usw., dann kann ich sehen, dass sich die Leute wieder über diese "aufgeblähte .NET-Laufzeitumgebung" beschweren . Während .NET mit CoreRT eigentlich bereits eine brillante Lösung für genau das hat, fehlt es an offizieller Unterstützung / offizieller Produktzusage, um den ganzen Weg zu gehen.

Vielleicht ist meine Sorge hauptsächlich, dass ich weniger parallele Produkte sehen möchte (wiederum @mikedn zitierend) und mehr Wert darauf legen würde, die hier vorhandenen Produkte zu engagieren, zu erweitern und zu unterstützen (einschließlich des Teilens von Roadmaps).

weniger Parallelprodukte

Wir haben nur ein Produkt: .NET Core. CoreRT ist kein separates Produkt und wird es auch nie. Hier geht es um das Hinzufügen von Optionen zu diesem einen Produkt. Hier sind einige Beispiele für Optionen, die wir heute haben: Workstation GC und Server GC; Eigenständige App-Veröffentlichung vs. Framework-abhängige App-Veröffentlichung.

@jkotas Ich verstehe, und ich stimme voll und ganz zu, dass das Hinzufügen von Optionen normalerweise großartig ist. Wenn Sie meine Verwendung des Wortes „Produkte“ durch „Optionen/Lösungen“ ersetzen, bleibe ich dennoch bei meiner Sorge, nicht vollständig zu wissen, ob das Engagement unseres Produkts für CoreRT als Option/Lösung innerhalb des .NET Core-Gesamtprodukts etwas ist, was wir tun können sicher darauf setzen, noch viele Jahre unterstützt zu werden. Stellen Sie sich vor, wie es wäre, wenn APIs im Laufe der Zeit unvorhersehbare Breaking Changes vornehmen und plötzlich veraltet sein würden, ohne dass Sie wissen, ob Sie darauf vertrauen können, dass eine API dort bleibt. Für eine Nicht-MS-Einheit fühlen sich die Tools/Optionen, die Teil des Produkts sind, genauso an. Wir sind auf mehrere Fähigkeiten von CoreRT angewiesen, die wir (zumindest derzeit) mit CoreCLR nicht ausführen könnten (eine davon ist die Fähigkeit, unsere ausführbaren Dateien mit PACE zu schützen und viele, viele Metadaten, IL usw. einfaches statisches Linken, einfacheres Verständnis der zugrunde liegenden Plattform, Aussicht, Verschleierung direkt in den Compiler einzubauen usw.). Grundsätzlich bin ich der Meinung, dass Ihre und die Arbeit von Michal und anderen an CoreRT einfach höher priorisiert werden sollte, da es meiner Meinung nach eines der besten Dinge ist, die im .NET-Ökosystem seit seiner ersten Entwicklung passiert sind. Jedes Mal, wenn von einem neuen Tool/einer neuen Option die Rede ist, die dann intern als Konkurrenz zu CoreRT betrachtet werden könnte, anstatt die CoreRT-Option zu vervollständigen und zu erweitern, fühlt sich das für mich wie eine falsche Ressourcenallokation an. Entschuldigung, ich wollte die Diskussion nicht in die Länge ziehen, ich wollte nur sicherstellen, dass Sie verstehen, wie sehr die Arbeit von CoreRT geschätzt wird und dass einige von uns hier draußen glauben, dass dies die Zukunft der Plattform sein sollte.
Ich werde davon absehen, diese Diskussion weiter zu verschmutzen. Ich wünsche den Teams alles Gute und freue mich auf alles, was Sie sich einfallen lassen. Ich bin sicher, es wird großartig.

@christianscheuer Ihr Feedback zu diesem Problem und zu anderen von CoreRT veröffentlichten Problemen war sehr wertvoll. Sie verschmutzen diese Diskussion überhaupt nicht.

die Rede ist von einem neuen Tool/Option, das dann intern als Konkurrenz zu CoreRT angesehen werden könnte

Im Kernteam führen wir Gespräche über verschiedene, ehrgeizigere oder verrücktere Optionen. Ich halte das „unzip to disk“ nicht für einen signifikanten Konkurrenten mit CoreRT full AOT. Jede richtet sich an ein anderes Segment von .NET-Benutzern/Apps.

Unser Produktmanagementteam, das Daten aus vielen verschiedenen Kanälen (einschließlich Github-Problemen oder persönlichen Kundengesprächen) zusammenstellt, schlug vor, dass das größte Preis-Leistungs-Verhältnis eine Lösung wie die hier vorgeschlagene ist. Wir validieren noch, dass wir alle Daten zu diesem Recht haben und dass es das gewünschte Ergebnis haben wird.

Ich kann Ihnen zu diesem Zeitpunkt nicht versprechen, wann die CoreRT-Technologie als Teil des unterstützten .NET Core-Produkts ausgeliefert wird. Ich weiß, dass es einzigartige Stärken hat, und ich bin sicher, dass wir eine unterstützte Lösung wie diese für das Segment wichtiger .NET-Benutzer ausliefern werden, die schließlich davon profitieren werden.

Die Einzeldateiverteilung ist sinnvoll, wenn:

  • Es wirkt sich nicht auf die Startzeit aus (sonst können es nur die kleinsten Anwendungen verwenden)
  • Es fungiert als VFS (Virtual File System) und ermöglicht Ihnen den Zugriff auf Assemblys und Ressourcen, als wären sie von der Festplatte oder aus dem Anwendungsordner).
  • Hat keinen Einfluss auf die "Patchbarkeit" der App. IE: Microsoft sollte in der Lage sein, kritische Baugruppen zu patchen, selbst wenn sie eingebettet sind, indem an anderer Stelle auf Systemebene Außerkraftsetzungen bereitgestellt werden.

Assemblys als eingebettete Ressourcen, die extrahiert und in einen temporären Ordner kopiert werden, sind keine erforderliche Lösung von Microsoft. Es kann von jedem Kunden, der es benötigt, einfach implementiert werden.

Eine "echte" Einzeldateilösung ist erforderlich und würde viel Wert bieten.

@jkotas deine Kommentare klingen mir wahr. Es würde mir schwer fallen, die .NET-Entwickler meines Unternehmens (LOB/Backoffice/Integrationen) davon zu überzeugen, auf CoreRT umzusteigen, da dies ein zu großer Sprung für sie wäre (insbesondere angesichts des experimentellen Labels), aber sie sehen den Wert in a relativ einfache (zu verwendende) Lösung für Core, wie sie in diesem Thread diskutiert wird. Danke

@ popcatalin81 Ich würde Ihren Punkten hier eigentlich stark widersprechen.

Die Startzeit ist für viele Anwendungen nicht aussagekräftig. Ich tausche gerne eine 50- bis 100-prozentige Verlängerung der Startzeit eines lang laufenden Dienstes ein, um die betriebliche Komplexität seiner Bereitstellung zu reduzieren.

Selbst wenn wir die Startzeit eines Dienstes um 30 Sekunden verlängern, ist das für Dienste auf Dauer nicht wirklich aussagekräftig.
Für benutzerorientierte Anwendungen wird das wahrscheinlich ein Killer sein, aber bis 3.0 herauskommt, sind so ziemlich alle CoreCLR-Apps entweder Konsolen oder Dienste.

Nicht, dass CoreCLR bereits über einen Modus verfügt, in dem Sie das Framework mit Ihrer Anwendung bündeln können (eigenständige Bereitstellung).
In unserem Fall (RavenDB) _verlassen_ wir uns aus mehreren Gründen darauf. Erstens die Möglichkeit, unser eigenes Framework zu wählen, unabhängig davon, was unsere Benutzer verwenden. Dies ist ein _großer_ Vorteil für uns, da es bedeutet, dass wir das global installierte Framework nicht verwenden müssen und somit nicht an das Framework gebunden sind, das der Administrator für das Framework festgelegt hat (wir haben früher berücksichtigt, dass wir darauf laufen würden .NET 4.0 manchmal, sogar Jahre nachdem 4.5 herauskam, zum Beispiel, und das war ein Schmerz).
Ein weiterer wichtiger Aspekt ist, dass wir mit _unserem eigenen_ Fork des Frameworks laufen können. Dies ist sehr nützlich, wenn wir auf Dinge stoßen, die wir ändern müssen.

Als Teil davon übernehmen wir die Verantwortung für die Patchzyklen und möchten nicht, dass sich jemand anderes damit herumschlägt.

VFS stört mich nicht, aber ich glaube nicht, dass dies erforderlich wäre. Und es ist vollkommen in Ordnung, dass ich eine dedizierte API durchlaufen / durch einige Reifen springen muss, um zu den Assemblys/nativen DLLs/Ressourcen zu gelangen, die auf diese Weise gebündelt sind.

Ich wurde zwei Tage lang von @briacht auf dieses Problem hingewiesen, also bin ich WIRKLICH spät in der Diskussion.
Ich möchte nur meine 2 Cent hinzufügen!

Zuerst meine Antworten auf die Fragen von @morganbr :

  1. Windows-App, WPF und WinForms mischen.
  2. Zurzeit nicht
  3. Ja, mit Assembly.Load in verschiedenen Varianten
  4. Jawohl
  5. Es kommt darauf an, ob dies eine Strafe ist, die bei jedem Start anfällt. Ja, wenn es ein paar Millisekunden sind, aber 5 Sekunden: nein. Wenn es einmalig ist, sind 5 Sekunden kein Problem.
  6. 50 MB sind schon ziemlich groß im Vergleich zu <2 MB ... aber wenn dies bedeuten würde, dass die dotnet-Laufzeit enthalten ist ... OK. Vielleicht kann ich einen Download mit und ohne bereitstellen.
  7. Die Veröffentlichungszeit spielt keine direkte Rolle, aber sie sollte den CI-Anbieter nicht verärgern, indem sie über einen langen Zeitraum viel CPU beansprucht.
  8. JAWOHL!

Die Anwendung, von der ich spreche Greenshot, die aktuell veröffentlichte Version zielt ziemlich immer noch auf .NET Framework 2.0 ab (ja wirklich), funktioniert aber ohne Probleme auf der neuesten Version (gute Abwärtskompatibilität)! Der Download, einschließlich Installer, aber ohne .NET Framework, ist etwa 1,7 MB groß. Das Verzeichnis, aus dem dieser gestartet wird, enthält 1 .exe und 4 .dlls, außerdem gibt es 11 Add-Ons in einem Unterverzeichnis.

Ich habe mir die vorherigen Kommentare durchgelesen, und viele von ihnen klingen so, als ob Sie etwas mit Funktionen wollen, für die ich ein Installationsprogramm verwenden würde. Dies ist in gewisser Weise sinnvoll, da es derzeit keine plattformunabhängige Lösung gibt.

Ich habe das aktuelle Thema bereits im August mit einigen Leuten bei Microsoft diskutiert, mein Hauptaugenmerk lag darauf, alles miteinander zu verknüpfen, um die Größe und Komplexität der Anwendung für die Bereitstellung zu reduzieren und auch das Laden der Assembly zu reduzieren, das während des Starts viel Zeit in Anspruch nimmt meiner Bewerbung.

Mit der nächsten Version von Greenshot, die auf .NET Framework 4.7.1 und dotnet Core 3.0 nebeneinander abzielt, enthält der resultierende Download für dotnet Core 3.0 derzeit etwa 103 DLLs (!!!), eine exe und 15 Add-Ons . Die Gesamtgröße beträgt etwa 37 MB und die größte Datei ist MahApps.Metro.IconPacks.dll (12 MB!!), die die meisten der von uns verwendeten Symbole enthält, was wahrscheinlich etwa 4 % der Datei ausmacht. Dasselbe gilt für viele andere DLLs, ich würde davon ausgehen, dass im Allgemeinen 50% der Codenutzung viel sind!

Wenn der Benutzer die Anwendung nicht installieren möchte, laden Sie einfach eine .zip-Datei herunter und finden Sie die ausführbare Datei zwischen etwa 118 Dateien ... nicht wirklich eine schöne Erfahrung! Die Größe ist etwa 35 MB (17x) größer, wo ist also der Nutzen für den Benutzer?

In den Monaten, bevor es dotnet core 3.0 gab, habe ich Fody.Costura verwendet, um so ziemlich das zu tun, was hier beschrieben wurde. Packen während des Bauens und Auspacken beim Start! Es machte sogar eine einzelne ausführbare Datei möglich, ohne die Dateien zu extrahieren, indem man a but hackte. Aber es hat auch ziemlich viele Probleme verursacht, also ist das nicht meine bevorzugte Lösung.

Ich hoffe auf eine mehr oder weniger Standardlösung, von der ich sagen kann: es funktioniert einfach ™
Vielleicht ist es sinnvoll, eine Standardordnerstruktur zu definieren, damit wir die ausführbare Datei, die Readme-Datei, die Lizenzdateien usw. im Stammverzeichnis ablegen und verschiedene "bekannte" Verzeichnisse für verschiedene Dateien haben können (Dotnet-Kern, Abhängigkeiten usw.). Dies erleichtert möglicherweise die Arbeit mit Tools und bietet Funktionen, bei denen jeder entscheiden kann, was er verwenden möchte und was nicht. Manchmal löst sogar das Ausführen von zip auf dem Verzeichnis einige Probleme.

Eine Lösung ähnlich wie Fody.Costury zu haben, ist definitiv irgendwann, die ich mir vorstellen könnte, um die Bereitstellung von Greenshot zu vereinfachen, aber es reduziert nicht direkt die Größe und Ladezeit. Ich hoffe also, dass auch hier einige Zeit verbracht wird!

@ayende Bitte erlauben Sie mir, Ihnen auch zu widersprechen :)

Während es sich um echte Dienste handelt, sind Webanwendungen und im Allgemeinen serverbasierte langlaufende Anwendungen nicht von einmaligen Startkosten betroffen, aber gleichzeitig sind diese Anwendungen nicht diejenigen, die die meisten Vorteile aus dem Einzeldateiverteilungsmodell ziehen. ( Raven ist eine Ausnahme, nicht die Norm ;) )

Meiner Ansicht nach ist die Einzeldateiverteilung in erster Linie auf Anwendungen und Dienstprogramme ausgerichtet, die sich an Benutzer richten. Benutzer, die solche Anwendungen herunterladen, kopieren und ausführen. Und in naher Zukunft, wenn.Net Core 3.0 Unterstützung für UI-Bibliotheken bieten wird, wird dieses Verteilungsmodell weit verbreitet sein. Allerdings muss ich betonen, dass dieses Modell für keine Apps geeignet sein wird. Wichtige Apps verwenden weiterhin ein Installationsprogramm.

Nun stellt sich die Frage, ob dieses Modell eingebetteter Assemblys, die in temporäre Ordner kopiert werden, gut funktioniert, wenn es sehr beliebt wird?

Aus meiner Sicht sind dies einige potenzielle Probleme für das aktuelle Modell:

  • Dutzende von Apps erstellen Tausende von temporären Dateien mit duplizierten Baugruppen. Hier kann Chaos entstehen. (Unbemerkt von Benutzern, aber immer noch ein Durcheinander)
  • Keine Komprimierung, kein Linker. Dies kann für kleine Utility-Apps im Vergleich zu FDD oder Ereigniskomprimierung einen Nachteil darstellen.
  • Es könnte die Bereitstellung von Servern tatsächlich behindern, anstatt sie zu vereinfachen. Der Grund dafür ist: Konfiguration nach der Bereitstellung mit Token-Ersetzungen. (Wo finden Sie den temporären Ordner, um Konfigurationsdateien zu überschreiben? Geben Sie dem Dienst Schreibzugriff auf seinen eigenen Ordner, um dort die Konfigurationsdatei zu erstellen? Das ist ein Sicherheits-Nein-Nein)

Ich bin nicht hier, um zu sagen, dass dieses Modell für alle Arten von Apps suboptimal ist. Ich habe es erfolgreich implementiert und in der Vergangenheit selbst für full.Net Framework verwendet, und es passt gut zu bestimmten Apps.

Ich denke nur, dass die optimale Implementierung die Version ist, bei der ein Linker alle Assemblys in einer einzigen Datei zusammenführt.

@popcatalin81 Eine Welt mit einem einzigen Standpunkt ist arm. Und ich bin nicht arrogant genug zu glauben, dass mein Bereitstellungsmodell das einzige ist, das es gibt.

Der Fall, an den ich denke, ist das Download- und Doppelklick-Szenario.
Im Moment müssen wir ein Shell-Skript entpacken und darauf klicken, um es auszuführen, da es mühsam ist, in ein Verzeichnis mit Hunderten von Dateien zu gehen und die richtige zu finden.

Über die Konfiguration in temporären Dateien. Ich wäre sehr dagegen. Konfigurationsdateien sind andere für den Benutzer sichtbare Dinge, die direkt neben der tatsächlich verwendeten Datei liegen _müssen_ und nicht irgendwo versteckt sind.
Wir haben bereits gesehen, wie schlimm das bei IsolatedStorage -Dateien war, wenn Benutzer sie brauchten.

In früheren Versionen von RavenDB haben wir viele Dinge zusammengeführt, um ein einfacheres Verzeichnis-Layout zu haben und die Anzahl der sichtbaren Dateien zu reduzieren, und das hatte einen ernsthaften Einfluss darauf, wie benutzerfreundlich unsere Software war.

Wird diese Funktion ILMerge verwenden? Wenn nein, warum nicht? Ich würde mich gerne weiterbilden, wenn es einen Fallstrick gibt.

Ich mag den vorgeschlagenen Ansatz "Packen und Extrahieren" nicht, insbesondere den Teil, in dem Dateien auf der Festplatte extrahiert werden. Es ist einfach, hat aber zu viele Probleme. Es sollte alles "im Speicher" funktionieren, ohne auf die Festplatte zu extrahieren.

Ich denke, es sollte so etwas wie corrt nativer Compiler oder Costura.Fody sein .

Optional sollte es auch versuchen, die Binärgröße zu reduzieren (unbenutzte Referenzen entfernen, tote IL).

betreffend

In den Monaten, bevor es dotnet core 3.0 gab, habe ich Fody.Costura verwendet, um so ziemlich das zu tun, was hier beschrieben wurde. Packen während des Bauens und Auspacken beim Start!

Beachten Sie, dass costura (standardmäßig) nicht "auf die Festplatte entpackt". Es extrahiert (im Speicher) die eingebetteten Assemblys aus Ressourcen und lädt sie über Bytes

Danke für den Kontext @SimonCropp , wir untersuchen beide Optionen zum Entpacken auf die Festplatte und zum Laden aus einem Stream. Die Abdeckung des Ladens aus einem Stream für reine IL könnte in unserer ersten Iteration möglich sein.

@jeffschwMSFT Übrigens, die Funktionen zum nahtlosen Zusammenführen von Assemblys (und optionalem Tree Shaking) sind etwas, das ich als erstklassiger Bürger gerne sehen würde. costura ist eines meiner beliebtesten Projekte, aber auch eines, dessen Unterstützung viel Zeit in Anspruch nimmt. Wenn also MS eine Alternative herausbringt (sogar als Beta), lassen Sie es mich wissen und ich werde einige Zeit damit verbringen, sie zu überprüfen und etwas "es gibt eine MS-Alternative" zur Costura-Readme- und Nuget-Beschreibung hinzuzufügen

Obwohl es unwahrscheinlich ist, lassen Sie es mich einfach wissen, wenn Sie einen Code in Costura unter einer Diff-Lizenz veröffentlichen müssen.

Vielen Dank an @SimonCropp , während wir beginnen, den Mono/Ilinker in die .NET Core-Toolkette zu integrieren, werden wir Ihr Angebot zur Überprüfung annehmen.

Beachten Sie, dass costura (standardmäßig) nicht "auf die Festplatte entpackt". Es extrahiert (im Speicher) die eingebetteten Assemblys aus Ressourcen und lädt sie über Bytes

Noch besser, ich glaube, es wird bei Bedarf mit dem AppDomain.AssemblyResolve -Ereignis geladen, sodass der Start nicht zu sehr beeinträchtigt werden sollte, da es nur bei Bedarf Assemblys (in den Speicher) lädt.

Zu spät zum Gespräch hier. Entschuldigung, falls dies bereits behandelt wurde.

Können wir davon ausgehen, dass das Artefakt hier deterministisch ist? Daher erzeugt der gleiche Build immer die gleiche Binärdatei? Byte für Byte. Es wäre auch hilfreich, eine Binärdatei mit einer kanonischen, begleitenden Prüfsumme verteilen zu können.

@morganbr Hier muss viel gelesen werden. Wäre es möglich, die bisher getroffenen Entscheidungen zu protokollieren?

@edblackburn Wir stellen ein aktualisiertes Design basierend auf dem Feedback zusammen. @swaroop-sridhar treibt jetzt das Design voran.

Wird diese Funktion ILMerge verwenden? Wenn nein, warum nicht? Ich würde mich gerne weiterbilden, wenn es einen Fallstrick gibt.

@simplejackcoder ILMerge kombiniert die IL aus vielen Assemblys zu einer, verliert dabei aber die ursprüngliche Identität der zusammengeführten Assemblys. Daher werden Dinge wie die Verwendung von Reflektion basierend auf ursprünglichen Assemblynamen fehlschlagen.

Das Ziel dieser Bemühungen besteht nicht darin, Assemblys zusammenzuführen, sondern sie unter Beibehaltung der Assemblyidentität zusammenzupacken. Darüber hinaus müssen wir nicht nur die Assemblys packen, sondern auch native Binärdateien, Konfigurationsdateien, möglicherweise die Laufzeit und alle anderen Abhängigkeiten, die von der App benötigt werden.

Das Zusammenführen von IL ist eine nützliche Funktion für Apps, die sich daran anpassen können – es ist nur eine andere Funktion als dieses Problem.

Eine Designüberprüfung wird unter https://github.com/dotnet/designs/pull/52 veröffentlicht
Lassen Sie uns die Diskussion über die PR von nun an fortsetzen.

Ich habe ein paar Fragen an Leute, die Single-File verwenden möchten. Ihre Antworten helfen uns, unsere Optionen einzugrenzen:

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)
  2. Enthält Ihre App (nicht-.NET) C++/nativen Code?
  3. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?
  4. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?
  5. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?
  6. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?
  7. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?
  8. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?
  1. Unser dotnet/coreclr#1-Anwendungsfall sind bei weitem Konsolen-Apps, die Dienstprogramme sind. Wir möchten eine Veröffentlichung für Windows oder Linux durchführen und --single-file angeben, um eine ausführbare Datei zu erhalten. Für Windows würden wir erwarten, dass dies auf .exe endet, für Linux wäre es eine ausführbare Binärdatei.
  2. Normalerweise nicht, aber es könnte über ein uns unbekanntes NuGet-Paket passieren
  3. Zunächst nicht, aber das wäre ein großartiges zukünftiges Feature
  4. Jawohl
  5. Jawohl
  6. Was auch immer funktioniert
  7. Ja, wenn es die resultierende Größe der ausführbaren Datei optimiert. Idealerweise kann es ein Flag sein, um die Optimierungsstufe mit --optimizing-level=5
  8. Ja, bis zu einem gewissen Punkt

Danke @BlitzkriegSoftware.
Ich denke, das hier vorgeschlagene Design deckt Ihren Anwendungsfall ab. Bitte werfen Sie einen Blick auf das Design – wir freuen uns über Ihr Feedback.

Ich habe ein paar Fragen an Leute, die Single-File verwenden möchten. Ihre Antworten helfen uns, unsere Optionen einzugrenzen:

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)
  2. Enthält Ihre App (nicht-.NET) C++/nativen Code?
  3. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?
  4. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?
  5. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?
  6. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?
  7. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?
  8. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?
  1. WPF .Core 3.0-App
  2. Vielleicht in einem Nuget-Paket
  3. Nein
  4. Jawohl
  5. Ja für max. 200-500ms
  6. Nicht wichtig, solange es nicht 2 oder 3 Mal größer ist als die ursprüngliche Größe des Veröffentlichungsordners
  7. Es ist für die Produktion also nicht wirklich wichtig
  8. Ja, aber die Möglichkeit, dies nicht zu tun, kann nützlich sein, wenn die Arbeit eine Bibliothek eines Drittanbieters betrifft

Das Feedback, das Sie erhalten haben, bezog sich hauptsächlich auf die Entwicklung vor 2019, bei der es sich normalerweise um Webservices, Konsolenanwendungen und andere im Hintergrund gestartete Dienste handelt. Aber jetzt mit .net Core 3.0 brauchen wir Lösungen für WPF- und UI-Apps. Das .Net Framework 4.8 wird den .Net Standard 2.1 nicht unterstützen und wir brauchen eine Lösung, um ILMerge zu ersetzen, das wir bisher für WPF-Anwendungen verwendet haben, da wir unsere Apps von .net Framework (totes Framework) auf .net Core aktualisieren müssen.

Ein selbstextrahierendes Paket ist eindeutig keine gute Lösung, wie in anderen Kommentaren zuvor für diese Art von Programmen erklärt wurde.

  1. Meistens CLI-Apps. Interessant sind auch kleine Windows-Dienste und die gelegentliche WPF-App. Für Web-Zeug scheint die Verteilung einzelner Dateien im Grunde irrelevant zu sein. Aus diesem Grund ist der Rest meist Windows-orientiert; Unser Interesse an Linux .NET Core gilt dem Web-Zeug.
  2. Manchmal. Wenn dies der Fall ist, handelt es sich fast immer um Komprimierungsbibliotheken. Wenn das einheimische Zeug nicht eingepackt würde, wäre es nicht das Ende der Welt. Eine gute Lösung für rein verwaltete Dinge, die die Bereitstellung einer nativen Abhängigkeit als separate DLL erfordern, wäre immer noch wertvoll.
  3. Nein, nicht in Fällen, in denen uns eine einzelne Datei wichtig ist.
  4. Jawohl.
  5. 200 ms ist ungefähr die Grenze, bevor die Dinge für den Start einer CLI ärgerlich werden. > 1 Sekunde und wir würden uns mit ziemlicher Sicherheit an .NET Framework (ILMerge + ngen) halten oder uns andere Sprachen ansehen, die zu einer nativen Binärdatei kompiliert werden, in die die erforderliche Laufzeit statisch eingebunden ist. In vielen Fällen sprechen wir über solche Dinge wurde in C# implementiert, weil eine ilmerged, ngen-ed C#-App eigentlich ziemlich schnell startet. Einiges davon ist von der Komplexität her vernünftig in einer Skriptsprache zu implementieren, aber diese neigen dazu, erhebliche Startkosten zu verursachen, insbesondere wenn Sie eine Reihe von Modulen einbinden müssen.
  6. Kommt darauf an. Über 10 MB für "Hello World" wären schwer zu verkaufen. Riesige auch ausführbare Dateien haben in der Regel nicht unerhebliche Startkosten. Selbst wenn das Betriebssystem theoretisch in der Lage ist, die Ausführung zu starten, ohne das Ganze zu lesen, zumindest unter Windows, gibt es fast immer etwas , das zuerst einen Hash für Sicherheitszwecke erhalten möchte. Apropos, dieses Auspacken von Binärdateien in temporäre Dateien wird AV (Defender absolut eingeschlossen) verrückt machen, wenn es um die Ressourcennutzung geht, die hektisch scannt, wenn nichts anderes.
  7. Sicher. Ich würde gerne eine Minute oder mehr zu einem Release-Build hinzufügen, wenn es bedeutet, etwas zu bekommen, das eine vernünftige Größe hat und schnell mit der Ausführung beginnt.
  8. Bestimmt.

Beim Lesen des Vorschlags wird kein Szenario angesprochen, das wir haben und das wir nicht verwenden würden. Es könnte jemanden geben, für den es ein Problem löst, aber wir sind es nicht.

Es scheint, als gäbe es viele relevante Dinge für Szenarien wie unseres, an denen gearbeitet wird, die einfach nicht zu einer Toolchain zusammengekommen sind, die tatsächlich verwendbar ist/wahrscheinlich weiterhin funktioniert. Vielleicht ist das nur Unwissenheit meinerseits, aber ich versuche aufzupassen und es ist mir nicht klar. Zwischen ILLink, Microsoft.Packaging.Tools.Trimming, CoreRT, .NET Native und was auch immer in dieser Ausgabe passiert, scheint es, als ob es einen Weg geben sollte, eine einzelne baumerschütterte, schnell startende (möglicherweise AoT?) Binärdatei mit angemessener Größe zu erhalten aus .NET Core (und nicht für UWP).

  1. Die Einzeldateiverteilung wäre für https://github.com/AvaloniaUI/Avalonia (Windows, Linux, MacOS) und WPF (Windows) Apps sehr nützlich. Eine einzelne exe macht zum Beispiel automatische Updates einfach, und im Allgemeinen ist es praktischer, eine einzelne Datei zu haben, verglichen mit hunderten von DLLs.
  2. Ja (in dem Sinne, dass es auf vorgefertigte native Bibliotheken wie sqlite und skia verweist)
  3. Nein
  4. Jawohl
  5. 200 ms sind wahrscheinlich in Ordnung. Eine Startzeit von 5 Sekunden für eine GUI-App ist nicht in Ordnung.
  6. Ist eigentlich egal
  7. Ist eigentlich egal. Wir könnten eine einzelne Datei nur für Produktionsszenarien erstellen.
  8. Jawohl

Bitte gehen Sie nicht mit Pack & Extract-Ansatz vor. Dies konnten wir bereits durch den Einsatz von Archiv-Tools erreichen.

Bitte gehen Sie nicht mit Pack & Extract-Ansatz vor. Dies konnten wir bereits durch den Einsatz von Archiv-Tools erreichen.

Ich kann nicht mehr zustimmen. Es gibt bereits mehrere Tools, die dies tun.

Danke für das Feedback @Safirion , @mattpwhite , @x2bool , @thegreatco.
Von diesen sehe ich eine Reihe von Nutzungsszenarien (Konsolen-Apps, WPF, GUI-Apps usw.), aber die Gesamtanforderungen scheinen ähnlich zu sein:

  • Konzentrieren Sie sich eher auf die Ausführungs-/Startzeit als auf die Build-Zeit.
  • Möglichkeit, Apps für weitere Versionen/Patches neu zu erstellen
  • Möglichkeit zur Ausführung direkt aus dem Bundle (insbesondere für rein verwaltete Komponenten).

Ich glaube, das sind die Anforderungen, die wir versucht haben, im Designdokument anzusprechen.

Bitte gehen Sie nicht mit Pack & Extract-Ansatz vor

Ja, wie in diesem Staging -Dokument erläutert, besteht das Ziel darin, die Abhängigkeit von der Dateiextraktion schrittweise zu minimieren.

Beim Lesen des Vorschlags wird kein Szenario angesprochen, das wir haben und das wir nicht verwenden würden.

@mattpwhite wollte klarstellen, ob diese Lösung Ihrer Meinung nach für Sie nicht funktioniert, basierend auf:

  • Der zuvor in diesem Arbeitspunkt vorgeschlagene auf Selbstextraktion basierende Ansatz, oder
  • Das in diesem Dokument erwähnte Design
    Ich glaube, das spätere Dokument versucht, das von Ihnen beschriebene Szenario anzugehen. Danke.

Es scheint, als gäbe es viele relevante Dinge für Szenarien wie unseres, an denen gearbeitet wird, die einfach nicht zu einer Toolchain zusammengekommen sind, die tatsächlich verwendbar ist/wahrscheinlich weiterhin funktioniert.

@mattpwhite , es wird laufend daran gearbeitet, ILLink (Tree-Shaking), Crossgen (Generieren von betriebsbereitem nativen Code) und Single-File-Bundling-Aspekte auf optimierte Weise für .net Core 3 in die msbuild/dotnet-CLI zu integrieren. Einmal Wenn dies erledigt ist, kann die Verwendung dieser Tools problemlos durchgeführt werden (z. B. das Festlegen bestimmter msbuild-Eigenschaften).

Alle diese Tools haben Kompromisse. Beispielsweise generiert Crossgen im Voraus nativen Code und hilft so beim Start, neigt jedoch dazu, die Größe der Binärdateien zu erhöhen. Mit der Einzeldateioption können Apps in einer Einzeldatei veröffentlicht werden, aber dies kann den Start verlangsamen, da native Binärdateien auf die Festplatte übertragen werden usw.

@swaroop-sridhar, danke, dass du dir die Zeit genommen hast zu antworten.

wollte klären, ob Sie denken, dass diese Lösung für Ihre Basis nicht funktioniert

Es schien, als wäre die Extraktion für alles, was in sich geschlossen ist, immer noch im Bilde, und der Status von Crossgen (oder irgendetwas anderem, das in der JIT-Zeit beim Start reduziert werden sollte) war mir nicht klar. Das Lesen des Staging-Dokuments, dass die aktuellen Designlinks darauf aussahen, als würden die Dinge, die dies für uns interessanter machen würden, weiter draußen liegen. In Anbetracht dessen dachte ich, dass wir noch einige Zeit damit beschäftigt sein würden, das .NET Framework für diese Nischen zu verwenden. Ich habe es vielleicht falsch verstanden.

Alle diese Tools haben Kompromisse. Beispielsweise generiert Crossgen im Voraus nativen Code und hilft so beim Start, neigt jedoch dazu, die Größe der Binärdateien zu erhöhen.

Ja, verstanden, dass einige davon zweischneidige Schwerter sind. Mit der traditionellen Arbeitsweise des JIT war ngen schon immer ein Gewinn für CLI/GUI-Apps. Es ist möglich, dass eine Kombination aus abgestufter Kompilierung und der Tatsache, dass das Laden der Laufzeit selbst nicht unbedingt durch viele andere .NET Framework-Prozesse, die auf derselben Box ausgeführt werden, amortisiert wird, dies für Core weniger klar macht.

@swaroop-sridhar Die große Sorge, die ich mit dem derzeit akzeptierten Vorschlag habe, ist dieser Schritt

Die verbleibenden 216 Dateien werden beim Start auf die Festplatte extrahiert.

Abgesehen von der Tatsache, dass „Hello World“ anscheinend 216 Dateien benötigt, um ausgeführt zu werden, erschwert das Extrahieren auf die Festplatte an einem beliebigen Ort das Entfernen einer einfachen Befehlszeilenanwendung. Wenn Leute ein Tool löschen, das nicht über ein Installationsprogramm kam, erwarten sie nicht, dass sie andere Dateien suchen müssen, um es vollständig zu entfernen.

IMHO sollten wir ein Veröffentlichungserlebnis anstreben, das dem von Golang ähnelt. Es müsste zwar crossgen vorhanden sein, um der Golang-Erfahrung vollständig zu entsprechen (und man könnte argumentieren, dass ein 1:1-Match keine _gute_ Sache ist, da wir bei der JIT- und Tiered-Compilation verlieren), a gute Portion kann ohne sie erreicht werden. Ich habe im Laufe der Jahre viele Tools verwendet, um eine ähnliche Erfahrung zu erzielen, und das effektivste waren eingebettete Ressourcen mit einem Haken am Assembly Loader (ILMerge war pingelig und Costura.Fody existierte noch nicht). Was in dem Vorschlag beschrieben wird, repliziert diese Funktionalität nicht einmal vollständig. .NET Core hat eine wirklich starke Zukunft, aber seine Verwendung für die Entwicklung von Befehlszeilentools ist begrenzt, solange wir Hunderte von Abhängigkeiten mitschleppen oder sie irgendwo auf der Festplatte mit handgewelltem Bootstrap-Code ausspucken müssen.

Mein dotnet/coreclr#1-Anwendungsfall sind Befehlszeilenprogramme, eine Datei, keine Extraktion wäre meine Präferenz. Aber ich möchte darauf hinweisen, dass die Auswahl als Teil der Befehlsschalter für All-in-One vs. All-in-One-Selbstextrahierung. Im selbstextrahierenden Fall sollte es ein undo enthalten, das die entpackten Dateien bereinigt. Im ersten Fall bedeutet das Entfernen des Dienstprogramms das Löschen einer Datei, die es geeignet macht, sich in einem Ordner mit allgemeinen Dienstprogrammen zu befinden, während im zweiten Fall die Installation einen eigenen Ordner haben sollte, um das Aufräumen zu erleichtern und zu vermeiden Szenarios, in denen die Deinstallation freigegebene Dateien entfernt. Nur einige Gedanken. Wie ich bereits sagte, ist das Dienstprogramm mit einer Datei (keine Installation erforderlich) mein primärer Anwendungsfall, da ich häufig Dienstprogramme für Projekte (als Werkzeugschmied) erstelle. Aber ich sehe einen Anwendungsfall für beide Szenarien. Aber sie sind anders .

Ich habe ein paar Fragen an Leute, die Single-File verwenden möchten. Ihre Antworten helfen uns, unsere Optionen einzugrenzen:

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)
  2. Enthält Ihre App (nicht-.NET) C++/nativen Code?
  3. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?
  4. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?
  5. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?
  6. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?
  7. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?
  8. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?
  1. CLI (Windows, Linux, MacOS), WPF und WinForms.
  2. Manchmal.
  3. Ja, oft und ich denke, das Szenario, dass ein Plugin eine gemeinsam genutzte Bibliothek aus der Hauptanwendung wiederverwenden kann, sollte angegangen werden!
  4. Jawohl.
  5. 200-500ms sind ok!
  6. Für eine einfache CLI-Anwendung ohne viele Abhängigkeiten reichen 10 MB (komprimiert)!
  7. Ja definitiv! Die Bauzeit (insbesondere für Release-Builds!) spielt keine Rolle! Die Komprimierungsgröße und/oder der Wechsel zur Veröffentlichung einer einzelnen Datei sollte optional sein!
  8. Ja zB CoreRT!

IMHO sollten wir ein Veröffentlichungserlebnis anstreben, das dem von Golang ähnelt.

@thegreatco : Ja, die vollständige Kompilierung in nativen Code ist eine gute Option zum Erstellen von Single-File-Apps. Sprachen wie GO werden mit AOT-Kompilierung (Ahead-of-Time) als primärem Modell erstellt – was mit gewissen Einschränkungen für dynamische Sprachfunktionen einhergeht, die durch JIT-Kompilierung erreicht werden.

CoreRT ist die .Net Core-Lösung für AOT-kompilierte Apps. Bis CoreRT jedoch verfügbar ist, versuchen wir in dieser Ausgabe, Single-File-Apps auf andere Weise zu erreichen.

Abgesehen von der Tatsache, dass "Hello World" anscheinend 216 Dateien benötigt, um ausgeführt zu werden,

Es stehen einige Optionen zur Verfügung, um die Anzahl der für HelloWorld erforderlichen Dateien zu reduzieren.

  • Erstellen Sie eine Framework-abhängige App, die nur 3-4 Dateien benötigt
  • Wenn wir eigenständige Apps erstellen müssen, verwenden Sie den ILLinker , um die Anzahl der Dateiabhängigkeiten zu reduzieren

Wenn Sie sie an einem bestimmten Ort auf die Festplatte extrahieren, wird das Entfernen einer einfachen Befehlszeilenanwendung schwierig.

  • Wenn die Entwicklung der Einzeldateifunktion in weitere Phasen übergeht , wird die Anzahl der auf die Festplatte übertragenen Dateien abnehmen und für die meisten Apps idealerweise null betragen. Aber in der Anfangsphase müssen mehrere Dateien (die nativen Code enthalten) verschüttet werden.
  • Der Speicherort von Dateien, die auf die Festplatte übertragen werden, ist immer deterministisch und konfigurierbar. So können die verschütteten Dateien mit einem einfachen Skript bereinigt werden. Aber ich stimme zu, dass dies nicht ideal ist.

Danke für die Klarstellung @mattpwhite.

Ja, bis zu späteren Phasen der Funktionsentwicklung sehen eigenständige Apps Dateien, die auf die Festplatte extrahiert wurden. Möglicherweise können Sie einige der Techniken verwenden, die ich im obigen Kommentar geschrieben habe, um die Situation für Ihre Apps zu verbessern.

Danke für deine Antwort @BlitzkriegSoftware.

Aber ich möchte darauf hinweisen, dass die Auswahl als Teil der Befehlsschalter für All-in-One vs. All-in-One-Selbstextrahierung

Ob eine als einzelne Datei veröffentlichte App extrahiert werden muss, hängt vom Inhalt der App ab (z. B. ob sie native Dateien enthält). Das Bundler-Design bietet einige Konfigurationen , um zu entscheiden, ob alle Dateien extrahiert werden sollen. Wir können eine Eigenschaft hinzufügen, die besagt, dass die App zur Laufzeit keine Extraktion in Dateien verwenden darf.

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

Das Verständnis hier ist: Beim Kompilieren von SingleFileExtract=Never, wenn die App Dateien enthält, die nur durch Extrahieren (native Binärdateien) verarbeitet werden können, schlägt das Veröffentlichen in eine einzelne Datei fehl.

Im selbstextrahierenden Fall sollte es ein Rückgängigmachen enthalten, das die entpackten Dateien bereinigt.

Klingt vernünftig. Der genaue Ort der Extraktion (falls vorhanden) ist deterministisch und konfigurierbar. Wir können also ein Skript haben, um eine App und alle ihre extrahierten Abhängigkeiten zu entfernen.

Danke für deine Antwort @DoCode. Ihr Szenario ist insofern interessant, als es Plugins verwendet.
Wenn die Plugins selbst einige Abhängigkeiten haben (die nicht mit der Haupt-App geteilt werden), würden Sie das Plugin auch als einzelne Datei veröffentlichen müssen/ziehen (mit eingebetteten Abhängigkeiten)? Danke.

Ja @swaroop-sridhar, das ist das Ziel. Wir denken, dass in diesem Fall das Plugin ihre Abhängigkeiten einbetten sollte. Nur die gemeinsam genutzten Abhängigkeiten sollten außerhalb der Haupt-App mit einer einzigen Datei geblieben sein.

Heute hat @madskristensen eine gute Erläuterung zu Visual Studio und dem beliebten NuGet-Paket Newtonsoft.Json gegeben.

Wir haben manchmal die gleichen Situationen in einer ähnlichen Situation!

Danke @DoCode. Wir planen, die Funktion von Single-File-Plugins zu adressieren, sobald Single-File-Apps implementiert und stabil sind. Das Design-Dokument spricht hier über Plugins.

Vielen Dank für das anhaltende Engagement für dieses Feature @swaroop-sridhar, es wird sehr geschätzt. Ein Befehl zum Rückgängigmachen ist besonders für die ursprünglichen Phasen großartig.

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)
    -- Befehlszeilenprogramme (Konsolen-Apps)
  2. Enthält Ihre App (nicht-.NET) C++/nativen Code?
    -- Nein
  3. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?
    -- Nicht gewöhnlich
  4. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?
    -- Jawohl
  5. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?
    - < 1 Sekunde wäre meine Präferenz
  6. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?
    - Größe ist nicht wichtig
  7. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?
    -- 30 Sekunden
  8. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?
    - Sicher, wenn es per Skript oder konfiguriert werden kann

1 - Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)

  • Spiele
  • Kommandozeilen-Tools

2 – Enthält Ihre App (nicht-.NET) C++/nativen Code?

Jawohl

3 – Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?

Ja, aber bei bereits bekannten Symbolen verlasse ich mich nicht auf Reflexion, da es langsam ist

4 – Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?

Jawohl

5 - Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?

Nein, es ist schon etwas langsam

6 - Was ist die größte Größe, die Sie für Ihre App als akzeptabel ansehen würden? 5 MB? 10? 20? 50? 75? 100?

Hängt vom Projekt ab, aber für ein einfaches Befehlszeilentool erwarte ich nicht, dass es größer als einstellige MB ist

7 – Würden Sie eine längere Release-Build-Zeit akzeptieren, um Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?

Solange es sich nicht auf die Entwicklungs-/Iterationszeit auswirkt, bin ich mit einer längeren Release-Build-Zeit einverstanden
Denken Sie jedoch daran, dass .net-Core-Apps bereits länger gebaut werden als herkömmliche .net-Framework-Apps

Diese Tendenz zu langsamerer Software jedes Jahr ist NICHT akzeptabel, wir haben bessere Hardware, kein Grund für diese Langsamkeit

8 - Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?

JAWOHL!

Ich hoffe wirklich, dass die AOT-Kompilierung mit CoreRT eines Tages funktioniert, damit wir Anwendungen wie Golang und Rust und andere AOT-kompilierte Langs nativ kompilieren können. Ähnlich wie Unity3D es mit IL2CPP macht.

@morganbr Hier sind einige Beiträge von mir und Leuten, mit denen ich arbeite. Ich verwende viele Sprachen, hauptsächlich aber C#, Go und Python.

Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)

ASP.NET Core- und Konsolenprogramme, hauptsächlich unter Linux, möglicherweise einige Windows-Workloads, je nachdem, ob ML.NET unsere Anforderungen erfüllt.

Enthält Ihre App (nicht-.NET) C++/nativen Code?

An dieser Stelle unwahrscheinlich.

Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?

Es hängt davon ab, ob. Derzeit können wir alle unsere Abhängigkeiten als Pakete abrufen, aber ich könnte mir eine Situation vorstellen, in der wir für eine kommerzielle Bibliothek bezahlen, was die Verwendung externer DLLs bedeuten kann.

Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?

Absolut. Dies hat für uns höchste Priorität.

Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?

Ich würde sagen, dass alles unter 10 Sekunden für mich mehr als in Ordnung ist. Die Startzeit spielt im Allgemeinen keine Rolle, solange sie idempotent und vorhersehbar ist - dh Bibliotheken werden in derselben Reihenfolge geladen, Variablen in derselben Reihenfolge initialisiert usw.

Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?

Kleiner ist besser, hauptsächlich für Verteilungszwecke. Die Verteilung könnte vom Benutzer heruntergeladene Binärdateien, Container-Images mit der Binärdatei usw. sein.

Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren?

Sicher, solange es schneller als C/C++ und Java ist, sollte es akzeptabel sein.

Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?

Wahrscheinlich wären 30-90 Sekunden ideal, aber alles unter 3 Minuten ist wahrscheinlich akzeptabel. Über 3 Minuten für kleine/mittlere Projekte (1k-500k LOC) wären etwas viel. 5 Minuten für sehr große Projekte (1M LOC) könnten akzeptabel sein.

Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?

Es hängt davon ab, ob. Wenn die zusätzliche Arbeit darin besteht, Boilerplate-Code hinzuzufügen, der als Vorlage erstellt werden kann, ist das wahrscheinlich in Ordnung. Wenn es unklar ist, keine einfache Arbeit, möglicherweise nicht.

Danke für die Antwort @mxplusb , @dark2201 , @RUSshy , @BlitzkriegSoftware

Ich glaube, dass das aktuelle Design Ihre Szenarien in Ermangelung einer reinen AOT-Kompilierung bestmöglich anspricht. Wenn Sie Bedenken bezüglich des Designs haben, können Sie diese gerne ansprechen.

In Bezug auf eine geringere Startzeit und Kompilierzeit:
Framework-abhängige Apps haben eine erheblich kürzere Startzeit (zumindest in den Anfangsstadien der Feature-Einführung). Auch die Kompilierzeit ist kürzer (weil weniger Dateien eingebettet werden müssen).
Sobald die erste Iteration der Feature-Entwicklung abgeschlossen ist, melde ich mich mit Messungen zur Startzeit, zum Kompilierungsdurchsatz und zur Dateigröße bei Ihnen.

@swaroop-sridhar Was ist der Zeitplan dafür?

@ayende Die erste Iteration befindet sich in aktiver Entwicklung, ich denke, wir werden die Ergebnisse in ein paar Wochen haben.

@swaroop-sridhar

Ich glaube, dass das aktuelle Design Ihre Szenarien in Ermangelung einer reinen AOT-Kompilierung bestmöglich anspricht. Wenn Sie Bedenken bezüglich des Designs haben, können Sie diese gerne ansprechen.

Ausführen: HelloWorld.exe

Die gebündelten App- und Konfigurationsdateien werden direkt aus dem Bündel verarbeitet.
Die verbleibenden 216 Dateien werden beim Start auf die Festplatte extrahiert.

Was ist, wenn ich von schreibgeschützten fs ausführen muss, was für IoT üblich ist, oder wenn die exe in einem ro-Container ausgeführt wird? Warum gibt es nicht auch die Möglichkeit, es direkt aus der exe auszuführen?

@etherealjoy Das in diesem Abschnitt gezeigte Beispiel ist die erwartete Ausgabe für eigenständiges HelloWorld ab Phase 2 der Entwicklung dieser Funktion (wie in diesem Abschnitt erwähnt). Zu diesem Zeitpunkt sind die einzigen Apps, die direkt von der EXE-Datei ausgeführt werden können, Framework-abhängige, rein verwaltete Apps.

Wenn wir uns in Stufe 4 oder Stufe 5 befinden, kann die obige eigenständige App direkt aus dem Paket ausgeführt werden.

Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)

Im Grunde alles oben. Konsolenprogramme, WPF, asp.net, Spiele

Enthält Ihre App (nicht-.NET) C++/nativen Code?

Jawohl. SQLite ist ein gutes Beispiel.

Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?

Wahrscheinlich nein.

Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?

Jawohl.

Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?

net.core ist schon etwas zu langsam. Aber eine Erhöhung um ein paar Sekunden ist akzeptabel. 5 Sekunden - definitiv nicht.

Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?

Heutzutage egal

Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?

Bis zu 5 Minuten fühlen sich akzeptabel an. 15- bis 20-minütige Release-Builds für UWP treiben alle in den Wahnsinn.

Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?

Sicher.

Danke @mjr27

Die Implementierung der Phase 1 ist jetzt abgeschlossen und ab 3.0.100-preview5-011568 verfügbar .

Apps können in einer einzigen Datei veröffentlicht werden, indem die Eigenschaft $#$ PublishSingleFile $#$ wie hier erklärt auf true gesetzt wird.

In dieser Version werden alle eingebetteten Dateien bei der ersten Ausführung auf die Festplatte extrahiert und in nachfolgenden Ausführungen wiederverwendet, wie hier erklärt .

Kompilierungsdurchsatz
Es gibt keinen wesentlichen Zeitunterschied, ob Dateien als einzelne Dateien oder als einzelne Datei in das Veröffentlichungsverzeichnis geschrieben werden.

Dateigröße und Start
Die folgende Tabelle zeigt die Leistung für einige Apps, die als Einzeldatei erstellt wurden.

  • Konsole: Eine Hallo-Welt-App. Die gemeldete Zeit ist die Zeit zum Ausführen der App, gemessen anhand von Uhr-Ticks.
  • WPF-App: msix-Katalog- App. Die angegebene Zeit ist die Zeit bis zum Start des Startbildschirms, gemessen mit der Stoppuhr.
  • Fw: Framework-abhängige Builds
  • Selbst: Eigenständige Builds.
    Alle Läufe wurden terminiert, wenn Antivirenprüfungen deaktiviert sind, um die Auswirkungen externer Faktoren zu minimieren.

Messung | Konsole Fw | Konsole selbst | WPF Fw | WPF-Selbst
-- | -- | -- | -- | --
Dateigröße (MB) | 0,32 | 66,5 | 20.69 | 118.9
Normaler Lauf (Sek.) | 0,123 | 0,127 | 3.32 | 3.24
Single-exe-Erstausführung (Sek.) | 0,127 | 0,565 | 3,67 | 4.14
Nachfolgende Einzelexe-Ausführungen (Sek.) | 0,124 | 0,128 | 3.30 | 3.29

Ich werde die Zahlen weiter aktualisieren, während die Implementierung in die nachfolgenden Entwicklungsstadien fortschreitet.

Hervorragende Nachrichten. Danke

Werden alle im Staging-Dokument erwähnten Phasen für 3.0 RTM abgeschlossen sein? Oder müssen wir nach 3.0 warten, bis sie implementiert sind?

Wie hier erwähnt, wird erwartet, dass .net Core 3.0 Phase 2 implementiert, sodass Framework-abhängige reine msil-Apps direkt aus dem Bundle ausgeführt werden können. Verbleibende Stufen werden für weitere Veröffentlichungen berücksichtigt.

Wie hier erwähnt, wird erwartet, dass .net Core 3.0 Phase 2 implementiert, sodass Framework-abhängige reine msil-Apps direkt aus dem Bundle ausgeführt werden können. Verbleibende Stufen werden für weitere Veröffentlichungen berücksichtigt.

:( hatte gehofft, es könnte es zu RTM schaffen.

@cup Ich dachte, du könntest es mit dotnet publish -o out /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 machen. Ich habe gerade getestet, indem ich eine Vanilla-Konsolen-App erstellt und diesen Befehl ausgeführt habe. Es hat erfolgreich funktioniert.

Sie können sogar noch weiter gehen, indem Sie die .pdb -Datei mit dotnet publish -o out /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 /p:IncludeSymbolsInSingleFile=true bündeln

Danke @seesharprun für die ausführlichen Hinweise. Ja @cup , die empfohlene Methode für die Veröffentlichung einzelner Dateien über die Befehlszeile besteht darin, die Eigenschaft PublishSingleFile über die Befehlszeile festzulegen.

@etherealjoy Die Coreclr-Laufzeit-Repos werden in etwa einem Monat größtenteils für Feature-Arbeiten gesperrt sein. Ich glaube nicht, dass die Zeit für alle Etappen ausreicht. Ich hoffe, dass die nächsten Stufen in der nächsten Version kommen werden.

Ich habe das heute zum Laufen gebracht, aber es scheint, dass das Ändern des Extraktionsbasisverzeichnisses nicht funktioniert. Laut diesem Abschnitt . Ich sollte in der Lage sein, einen Anwendungsschalter namens ExtractBaseDir in runtimeconfig hinzuzufügen, um den Speicherort zu ändern, an den die Anwendung extrahiert wird.

Ich habe eine runtimeconfig.template.json, die so aussieht

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

Die erzeugte app.runtimeconfig.json sieht so aus:

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

Beim Ausführen der produzierten EXE-Datei wird sie jedoch immer noch in den tmp-Ordner extrahiert.

Ich gehe davon aus, dass diese Funktion in Preview5 einfach nicht bereit ist, aber ich wollte sichergehen, dass nicht klar ist, wo "ExtractBaseDir" in runtimeconfig.json hingehört, und es keine Beispiele gibt.

@igloo15 Danke, dass du das angesprochen hast.

In der aktuellen Vorschau ist nur die Umgebungsvariable DOTNET_BUNDLE_EXTRACT_BASE_DIR aktiviert. Dies liegt daran, dass in der aktuellen Phase der Implementierung alle Dateien – einschließlich runtimeconfig.json – auf die Festplatte extrahiert werden, bevor sie verarbeitet werden.

Ich arbeite daran, in der nächsten Vorschau Unterstützung für ExtractBaseDir hinzuzufügen.

Gibt es eine Anleitung, wie dies mit ASP.NET Core-Projekten funktioniert? Wäre der empfohlene Ansatz, Reflektion zu verwenden, um herauszufinden, woher meine Systemtypen geladen werden, und meine IHostingEnvironment ContentRootPath und WebRootPath relativ zu diesem Verzeichnis festzulegen?

@keithwill Sie können AppContext.BaseDirectory verwenden, um den Speicherort abzurufen, an dem die app.dll und alle anderen Dateien auf die Festplatte extrahiert werden. Sie können dies also als ContentRootPath verwenden.

@igloo15 : Ich bin gespannt, ob Sie mitteilen könnten, wie Ihr Szenario für die Verwendung dieser Option aussieht.

  • Versuchen Sie, es für ein Debugging- oder Produktionsbereitstellungsszenario zu verwenden?
  • Würde die Umgebungsvariable in diesem Fall ausreichen oder benötigen Sie die Einstellung runtimeconfig.json ?

Ich bin auch neugierig, von anderen Entwicklern zu hören, ob es bestimmte Anwendungsfälle für diese Einstellung gibt.

@swaroop-sridhar

Ich habe eine ziemlich seltsame Situation. Meine Software wird auf einer Netzwerkfreigabe gespeichert und dann wird die Netzwerkfreigabe mit einer zufälligen Windows-VM verknüpft und direkt von der Netzwerkfreigabe ausgeführt. Auf der Windows-VM, die hochgefahren wird, um die Software von der Netzwerkfreigabe auszuführen, darf nichts modifiziert oder geändert werden. Protokolle, Konfigurationsdateien usw. müssen alle auf der Netzwerkfreigabe erstellt werden.

Seltsamerweise ermöglicht dieses Setup dem Gesamtsystem, mehrere Softwareteile in einem Ordner zu erstellen und diese Ordnerstruktur dann für verschiedene Konfigurationen/Versionen zu klonen. Wenn dann eine bestimmte Version ausgeführt werden muss, startet die Verwaltungssoftware VMs und ordnet Laufwerke auf den VMs der Netzwerkfreigabe einer bestimmten Version zu und führt die Software aus.

1.) Es handelt sich um ein Produktionsbereitstellungsszenario
2.) Umgebungsvariablen wären schwierig, da der Computer, auf dem die Software ausgeführt wird, ständig anders ist und zerstört / neu erstellt wird

@cup Ich stimme wirklich nicht zu, dass es in diesem Thema um die Implementierung des Designdokuments geht, und das Designdokument besagt ausdrücklich, dass ExtractBaseDir für diese Funktion funktionieren sollte.

Wenn es in dieser Ausgabe nicht um die Implementierung dieses Designdokuments geht, worum geht es dann in dieser Ausgabe?

Danke für die Erklärung @igloo15.

Ich frage nach der Konfigurationsoption, da das frühzeitige Parsen der Konfigurationsdateien im AppHost-Code mit Kosten verbunden ist. Derzeit ist der AppHost nicht mit dem Code zum Analysieren der JSON-Dateien verknüpft (sie werden stattdessen von hostfxr/hostpolicy verwendet). Das Hinzufügen dieser Funktion zum jetzigen Zeitpunkt würde den AppHost etwas größer/komplexer machen. Sobald die Implementierung jedoch in weitere Phasen übergeht (in denen der gesamte Hosting- und Laufzeitcode miteinander verknüpft sind), ist dies kein Problem mehr.

@igloo15 Das Design-Dokument ist ein wichtiger Teil davon, aber der Kern dieser Ausgabe ist das Feature selbst. ExtractBaseDir ist ein optionaler Parameter und ich würde lieber sehen, dass die Kernfunktion an die "aktuelle" Version übergeben wird, anstatt sich mit optionalen Parametern zu verzetteln.

@cup , ich habe die Frage hier gestellt, weil ich in diesem Thread die Aufmerksamkeit interessierter Entwickler bekommen habe.
Obwohl ich nicht denke, dass die Frage vom Thema abweicht, verstehe ich Ihre Besorgnis über die Länge dieses Threads. Beim nächsten Mal erstelle ich ein verlinktes Problem. Danke.

@cup @swaroop-sridhar

Ein paar Dinge, die ich zuerst sagen möchte, sind, dass diese Funktion nur für Stufe 1 des Stufendokuments von Bedeutung ist. In allen anderen Phasen 2 - 5 geht es darum, die DLLs aus dem Bundle heraus auszuführen und nicht zu extrahieren. Daher ist eine Einstellung zum Bestimmen des Speicherorts des Basisverzeichnisses für das Extrahieren für die Stufen 2-5 nicht wirklich nützlich. Da NetCore 3.0 beabsichtigt, Phase 1 zu entwickeln, würde ich erwarten, dass diese Funktion vorhanden ist, da dies das einzige Mal ist, dass sie nützlich wäre.

Zweitens, wie unterscheiden wir diese Methode von anderen Methoden wie dotnet-wrap. Für mich besteht der Hauptvorteil dieser Methode darin, dass wir diesen Prozess näher an der Kompilierung des Codes in die Build-Kette einbauen. Darüber hinaus ist dies eine Funktion, die auf .NET ausgerichtet ist und daher die Nuancen von .NET Core-Anwendungen wie deren Konfigurationen, Build-Prozesse usw. versteht. Daher hoffe ich, dass wir uns auf Funktionen konzentrieren, die dieses Tool von anderen Tools unterscheiden nicht speziell auf Netzkern ausgerichtet. Dies wären Funktionen wie die Konfiguration des Extraktionsorts, die dotnet-wrap nicht ausführen kann.

Ich bin mir nicht sicher, wie es implementiert ist, aber ich würde denken, dass wir das nicht zur Build-Zeit in die Bundle-Exe einbetten könnten, anstatt das ExtractBaseDir zur Laufzeit aus der Konfiguration zu lesen? Ich habe den Code, der diesen Bundle-Prozess zum Laufen bringt, nicht gesehen, aber meiner Meinung nach wird eine native Exe mit allen darin enthaltenen DLLs usw. generiert / erstellt. Konnten wir nicht während der Generierung/Erstellung der exe die gebündelte apps runtimeconfig-Datei lesen, ExtractBaseDir herausziehen und als Eigenschaft für die native Bundle-exe festlegen.

Dann liest es keine eingebettete Laufzeitkonfiguration zur Laufzeit, sondern nutzt stattdessen intern eine Eigenschaft, um den Extraktionsort zu bestimmen. Das sollte möglicherweise viel schneller sein.

@igloo15 : Das Extrahieren des Inhalts des Pakets auf die Festplatte kann für bestimmte Apps nach Stufe 2 nützlich sein.
Wenn die App beispielsweise benutzerdefinierte native Binärdateien im Bundle enthält, müssen sie bis Phase 5 extrahiert werden. Die App möchte möglicherweise Inhaltsdateien unbekannten Typs bündeln, die zur Laufzeit in Dateien extrahiert werden sollen.

Ich stimme zu, dass der Nutzen dieser Einstellung abnimmt, wenn wir zu weiteren Entwicklungsstufen übergehen. Sobald wir die Option jedoch hinzugefügt haben, müssen wir sie wahrscheinlich aus Kompatibilitätsgründen in allen nachfolgenden Versionen beibehalten. Daher bedarf es jetzt einer sorgfältigen Überlegung.

Ich stimme zu, dass es bei der Implementierung einfacher und effizienter ist, den Extraktionsort zu einer Build-Time-Einstellung (z. B. msbuild-property) und nicht zu einer runtimeconfig-Option zu machen. Danke.

Hallo zusammen, ich habe ein paar Fragen zu diesem Thema:

Ich möchte die Single-File-Distribution- Funktion zum Packen von .NET Framework 4.7.2-Anwendungen (z. B.) in eine einzige ausführbare Datei verwenden. Ist das die Absicht dieses Features oder soll es nur .NET Core-Anwendungen unterstützen?

Meine zweite Frage bezieht sich auf die Verpackung. Wenn die ausführbare Datei erstellt wird, würde die Ziel-Framework-Laufzeit in die ausführbare Datei gebündelt werden? Oder muss es auf dem Zielcomputer vorinstalliert sein, auf dem die Anwendung ausgeführt wird?

@gaviriar Ich glaube nicht, dass es .NET Framework-Anwendungen unterstützt. Und ja, es kann die .NET Core-Laufzeit in ausführbare Dateien bündeln (sogenannte „eigenständige“ Veröffentlichung).

@tomrus88 danke für die Antwort. Das ist eine echte Schande für .NET Framework-Anwendungen. Gibt es eine Methode, die Sie empfehlen würden, um die .NET Framework-Laufzeit in eine ausführbare Datei zu bündeln?

Ich sehe eine Liste von Tools im zugehörigen Arbeitsabschnitt des Dokuments. Gibt es spezielle, die für meinen oben vorgeschlagenen Anwendungsfall empfohlen werden könnten?

@gaviriar .NET Framework ist Teil des Windows-Betriebssystems. Es gibt keine unterstützte Möglichkeit, es in eine ausführbare Datei zu bündeln.

@gaviriar Die Notwendigkeit, die Laufzeit zu bündeln, ist einer der Hauptgründe für den Wechsel zu .NET Core.

@jnm2 und @jkotas danke für die Klarstellung, Noob hier in der .NET-Welt. Ich stimme zu, dass ich gerne zu .NET Core wechseln würde. Ich stehe jedoch vor einem Fall, in dem ich mit einer Legacy-Bibliothek interagieren muss, die auf .NET Framework abzielt. In einem solchen Fall kann ich nach meinem Verständnis meine App nicht auf .NET Core umstellen, wenn ich mit dieser Bibliothek interagieren muss. Oder gibt es einen alternativen Ansatz, bei dem meine App .NET Core ist, aber dennoch mit der älteren .NET Framework-Bibliothek interagieren kann?

Das hängt von der Bibliothek ab. Viele Bibliotheken, die auf .NET Framework abzielen, funktionieren auch gut auf .NET Core. Haben Sie versucht, die Bibliothek in .NET Core zu verwenden? Wenn Sie sich vergewissert haben, dass es nicht funktioniert, können Sie nicht wechseln, bis Sie eine Lösung dafür haben.

Ich habe es tatsächlich versucht, aber das funktioniert nicht, da wir über Bibliotheken sprechen, die Windows-spezifisch sind. Ich denke, ich habe keine andere Wahl, als bei .NET Framework zu bleiben und den .NET Core-Spaß zu verpassen, wie Sie sagen:/

@gaviriar Dies ist kein Thema, aber haben Sie das Windows-Kompatibilitäts-NuGet-Paket ausprobiert, das Windows-APIs für .NET Core für genau den Zweck bereitstellt, den Sie Microsoft.Windows.Compatibility beschreiben

@gaviriar : Noch ein paar Klarstellungen:

Wenn die ausführbare Datei erstellt wird, würde die Ziel-Framework-Laufzeit in die ausführbare Datei gebündelt werden? Oder muss es auf dem Zielcomputer vorinstalliert sein, auf dem die Anwendung ausgeführt wird?

Das hängt vom Aufbau ab. Sowohl Framework-abhängige (Laufzeit wird auf dem Ziel installiert) als auch eigenständige (Laufzeit wird mit der App gepackt) Apps können als einzelne Datei veröffentlicht werden – aber nur .net Core 3.0-Apps.

Ich sehe eine Liste von Tools im zugehörigen Arbeitsabschnitt des Dokuments. Gibt es spezielle, die für meinen oben vorgeschlagenen Anwendungsfall empfohlen werden könnten?

Für das .net-Framework ist die beste Lösung, die ich vorschlagen kann, dass die App die Dateiextraktion selbst übernimmt. Beispiel: Betten Sie die Abhängigkeiten als verwaltete Ressourcen in die App-Binärdatei ein und extrahieren Sie die Ressourcen dann explizit beim Start. Sie können auch die Bundle-Bibliothek zum Bündeln und Extrahieren verwenden (da die Bibliothek Netstandard erstellt wurde), aber die Verwendung verwalteter Ressourcen ist eine bessere Lösung.

@igloo15 und @swaroop-sridhar Ich schätze diese Beiträge, da sie nicht zum Thema gehören. Obwohl ich hoffe, dass jemand anderes diese Diskussion beim Lesen eines Tages nützlich findet.

Ich werde die Optionen, die Sie mir mitgeteilt haben, bewerten und Sie wissen lassen, was sich als der beste Ansatz für meinen Anwendungsfall herausstellt.

Danke!

Schnelles Update!

Ich habe diese einfache Hello World- Anwendung getestet. Ich kann erfolgreich eine einzelne ausführbare Datei erstellen. Wie Sie jedoch der Projektkonfiguration entnehmen können, ist es für sich selbst gedacht. Aber wenn ich versuche, diese ausführbare Datei auf einer neuen Windows 7-Installation ohne installierte .NET Core-Laufzeit auszuführen, wird der folgende Fehler angezeigt:

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

Was ich sehen kann, ist, dass das Erstellen der Veröffentlichung der App als dotnet publish /p:PublishSingleFile=true oder /p:PublishSingleFile=false die Größe der ausführbaren Datei nicht ändert. Ist das erwartetes Verhalten?

Schritte zum Reproduzieren

  1. Veröffentlichen Sie das Projekt, um die HelloWorld.exe zu generieren

  2. Kopieren Sie die ausführbare Datei in eine Windows 7-Installation ohne installierte .NET Core-Runtime

  3. Führen Sie die HelloWorld.exe

@gaviriar Ich habe das von Ihnen veröffentlichte Beispiel ausprobiert und es hat für mich gut funktioniert.
Das heißt, es hat eine eigenständige Single-Exe für HelloWorld erstellt, die OK läuft.

Was ich sehen kann, ist, dass das Erstellen der Veröffentlichung der App als dotnet publish /p:PublishSingleFile=true oder /p:PublishSingleFile=false die Größe der ausführbaren Datei nicht ändert. Ist das erwartetes Verhalten?

Das ist definitiv nicht zu erwarten. Die Einzeldatei-App sollte etwa 70 MB groß sein (für den auf Ihrer Gitlab-Seite angegebenen Debug-Build). Andernfalls handelt es sich um einen normalen Apphost, von dem erwartet wird, dass er genau so fehlschlägt, wie Sie oben festgestellt haben. Veröffentlichen Sie aus einem sauberen Verzeichnis?

Eine weitere Anmerkung zu Ihrer Projektdatei: Sie haben eine der Eigenschaften fälschlicherweise als IncludeSymbolsInFile anstelle von IncludeSymbolsInSingleFile geschrieben. Das hat aber nichts mit dem von Ihnen gemeldeten Problem zu tun.

@gaviriar was sind Ihre Ziellaufzeitkennungen. Wenn Sie es nicht richtig einstellen, wird die richtige hostfxr.dll nicht gebündelt. Es ist möglich, dass die hostfxr.dll eine bestimmte vc++ Redistributable benötigt, die auf Ihrem Windows 7-Computer nicht vorhanden ist. Sie können überprüfen, ob die DLL im angegebenen Pfad vorhanden ist, und versuchen, sie im Dependency Walker-Tool zu laden, um festzustellen, ob eine DLL existiert, von der sie abhängt.

Zusammenführen von IL: Tools wie ILMerge kombinieren die IL aus vielen Assemblys zu einer, verlieren dabei aber die Assemblyidentität. Dies ist kein Ziel für die Einzeldateifunktion.

Versammlungsidentität verlieren

das ist kein Problem.
Ich bin immer gegen die Verwendung von Zip / Unzip oder einer anderen Bundle-Lösung für die eigenständige Single-Exe-Funktion.
weil dies die nächsten Probleme verursachen wird.
So reduzieren Sie die Größe der Single-exe-Datei!?? oder warum ist die exe-datei soo groß, aber es ist nur ein hallo welt!??

Es gibt immer das Problem, und es muss angegangen werden, warum nicht gründlich vorgehen.
Tatsächlich sollte IL-Merge von Anfang an ähnliche Wege nutzen.

Tatsächlich sind die Leute nicht wirklich so besessen von einer einzigen EXE.
exe(1)+dll(1-2) auch OK, aber nicht 400 mount dlls .
ppl möchte den Code niemals auf die Serverfestplatte bringen und ihn ausführen, indem er die Serverspeicher nimmt.
Menschen möchten nur die Bereitstellungskosten reduzieren (Festplatte, Speicher, Bandbreite usw.).

Ich habe den 3.0-Meilenstein entfernt, sodass diese Ausgabe die Implementierung der Einzeldateifunktion durch die in diesem Dokument beschriebenen Phasen verfolgt, was über den Umfang der 3.0-Version hinausgeht.

@sgf , ich stimme zu, dass Arbeit erforderlich ist, um die Dateigröße zu reduzieren. Es gibt zwei Möglichkeiten zur Größenreduzierung, sie sind nicht speziell an Single-Exe gebunden:
1) Reduzieren Sie die Menge an Inhalten, die veröffentlicht werden müssen. Zum Beispiel:
* Verwenden Sie ILLinker-ähnliche Tools, um unnötige Binärdateien, Teile von Baugruppen usw. zu entfernen.
Diese Arbeit wird separat nach Problemen wie dotnet/coreclr#24092 und mono/linker#607 verfolgt
* Wir können andere Maßnahmen in Betracht ziehen, wie z. B. einen Modus mit „reduzierter Leistungsfähigkeit“, in dem JITting nicht unterstützt wird, um die
2) Hinzufügen einer Komprimierungsfunktion zum Veröffentlichen einzelner Dateien.

Die oben genannten Funktionen können zusammenarbeiten, um die Größe von Einzeldatei- (und Nicht-Einzeldatei-) Apps zu reduzieren:
Beispiel: Für die Konsolen-App „HelloWorld“
Normale Veröffentlichungsgröße = 67,4 MB
Beschnittene Größe = 27 MB
Getrimmt, Einzeldatei, komprimiert (über Prototyp) = 12 MB

@swaroop-sridhar Gibt es eine Möglichkeit, den Pfad Ihrer einzelnen exe-Datei in Ihrer Anwendung abzurufen?
Mit Assembly.GetExecutingAssembly().Location wird das Extraktionsverzeichnis in \AppData\Local\Temp.net ausgegeben.

@chris3713 Der beste Weg für den Zugriff auf den exe-Speicherort ist derzeit das PInvoke-ing zu nativen APIs. Zum Beispiel: GetModuleFileNameW (Null, <buffer>, <len>)

@chris3713 Der beste Weg für den Zugriff auf den exe-Speicherort ist derzeit das PInvoke-ing zu nativen APIs. Zum Beispiel: GetModuleFileNameW (Null, <buffer>, <len>)

Danke, am Ende habe ich Process.GetCurrentProcess().MainModule.FileName verwendet.

Funktioniert einwandfrei mit asp .net Core Worker/Web API als Windows-Dienst, der mit PublishSingleFile=true veröffentlicht wird.

Wenn ich den Dienst registriere und über sc create testwk binPath="[...]/MyAspNetCoreWorker.exe" dann sc start testwk starte, bekomme ich diese Erfolgsmeldung:

[...]\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

Ich kann es kaum erwarten, Stage 2 mit Running In Bundle zu sehen😀
Übrigens, wird Stage 2 weiterhin als Teil von .Net Core 3.0 geplant sein?

Vielen Dank für Ihre Arbeit, der Veröffentlichungsdienst in .net Core ist jetzt wirklich einfach 👍

CoreRT : ( 2,5 MB )

image

image

Kein Zip-Hack , keine versteckten Kosten , die Engine enthält nur das, was benötigt wird, und nicht verwendete Funktionen werden mithilfe von csproj config (Reflexion) deaktiviert .

Das ist es, was dotnet braucht, es konkurriert mit GO und übertrifft es sogar in Bezug auf Größe und Leistung

Für alle Interessierten, überprüfen Sie das Repo:

https://github.com/dotnet/corert

Es gibt Beispiele für MonoGame:

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

Keine der vorgeschlagenen Lösungen kann dieses Ergebnis erzielen, CoreRT ist wirklich das Beste, MS macht einen großen Fehler, indem es sich nicht darauf konzentriert

Ich habe diese Funktion auf macOS mit dotnet-sdk-3.0.100-preview8-013656-osx-x64.tar.gz getestet. Wenn wir die Konfiguration von Debug auf Release oder umgekehrt umschalten und erneut erstellen, werden 10 MB zur ausführbaren Größe hinzugefügt. Das erneute Kompilieren mit der alten Konfiguration stellt diese Größenzunahme nicht wieder her, es sei denn, wir löschen das Verzeichnis 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

Auch ohne Änderung der Build-Konfiguration erhöht sich die Ausgabegröße, wenn wir Rebuild target anschließend ( /t:Rebuild ) nach dem ersten Build aufrufen.

Danke @am11 für einen Blick. Das Veröffentlichen von alten Binärdateien ist ein bekanntes Problem (cc @nguerrera).

Seit .Net Core 3 Preview 8 kann ich meine veröffentlichte Einzeldatei-App nicht mehr starten.
In der Ereignisanzeige habe ich diesen Fehler:

image

Ich verwende Windows Server 2019

Bearbeiten: Dieser Fehler ist nach dem Aktualisieren von .Net Core SDK Preview 7 auf .Net Core SDK Preview 8 aufgetreten. Nach dem Neustart des Servers kann ich meine Anwendung wieder korrekt starten.

@Safirion wir haben eine Änderung am zugrunde liegenden internen Format um diese Vorschauen herum vorgenommen. Es ist möglich, dass Sie die Ausgabe einer Vorschau überspannt und mit einer anderen erstellt haben. Es gibt keine Pausen zwischen Preview 8 und 9.

Unter Linux scheint der Standard-Extraktionspfad /var/tmp/.net zu sein. Auf AWS Lambda ist der /var-Pfad nicht beschreibbar, daher schlägt das Erstellen dieses Ordners fehl. Um sofort einsatzbereit zu sein, ohne DOTNET_BUNDLE_EXTRACT_BASE_DIR einzustellen, schlage ich vor, dies in /tmp/.net zu ändern. Oder vielleicht sollte es mehrere Versuche an gemeinsamen Speicherorten geben (/var/tmp, /tmp, dasselbe Verzeichnis wie die Binärdatei usw.)

@stevemk14ebr danke, dass du dieses Problem gemeldet hast. Können Sie ein neues Problem einreichen, um diese Arbeit nachzuverfolgen? https://github.com/dotnet/core-setup

@jeffschwMSFT Derselbe Fehler wurde beim Übergang von .Net Core P9 zu RC1 ausgelöst.

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 danke, dass du dieses Problem gemeldet hast. Können Sie ein separates Problem erstellen, um dies zu reproduzieren? https://github.com/dotnet/core-setup
cc @swaroop-sridhar

@Safirion kannst du bitte eine Repro-Anleitung schicken? Ist dieser Fehler deterministisch?
Bitte melden Sie ein Problem im Core-Setup-Repo, wie oben von @jeffschwMSFT vorgeschlagen.

Ich habe mir das angesehen und dies würde nur passieren, wenn die App in einer Umgebung ausgeführt wird, in der auf das temporäre Verzeichnis nicht zugegriffen werden kann. Wenn ich zum Beispiel das mache:

set "TMP=wrong_path"
myapp.exe

Es scheitert mit

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

Beachten Sie, dass das Bundle mithilfe der GetTempPath win32-API nach temporären Verzeichnissen sucht. Welche verwendet die env. Variable TMP , gefolgt von TEMP und so weiter. Wenn der erste mit Wert einen ungültigen Pfad enthält, würde dies wie folgt fehlschlagen.

Sie können dies beheben, indem Sie entweder sicherstellen, dass der temporäre Pfad richtig eingestellt ist, oder Sie können DOTNET_BUNDLE_EXTRACT_BASE_DIR explizit auf einen Ort festlegen, an dem die Extraktion stattfinden soll.

@Safirion kannst du bitte eine Repro-Anleitung schicken? Ist dieser Fehler deterministisch?
Bitte melden Sie ein Problem im Core-Setup-Repo, wie oben von @jeffschwMSFT vorgeschlagen.

Ich kann dieses Problem nicht reproduzieren, nachdem ich .Net Core auf RC1 aktualisiert und meinen Server neu gestartet habe. (Ich habe versucht, RC1 zu deinstallieren und Preview 9 erneut zu installieren, um erneut auf RC1 zu aktualisieren, aber diesmal startet meine App gut.)

Dieser Fehler ist beim Übergang von SDK 3.0 P7 zu SDK 3.0 P8 und SDK 3.0 P9 zu SDK 3.0 RC1 aufgetreten.
Und in den beiden Fällen behebt ein einfacher Neustart des Servers das Problem.

Ich verwende einen .Net Core Windows-Dienst (Worker verwendet den C:\Windows\Temp\.net -Ordner zum Extrahieren seit dem Start durch das System) und eine .Net Core WPF-App (Start durch Benutzer-Startsitzungsskript), wenn ich auf RC1 aktualisiert habe. Vielleicht wird dieser Fehler durch .Net Core Worker verursacht, der während der .Net Core SDK-Installation ausgeführt wird, ich weiß es nicht ...

Beachten Sie, dass ich das SDK und nicht die Laufzeit installiere, da ich die 3 .Core-Laufzeit (asp.net-Kern, Desktop-.net-Kern und -Kern) gleichzeitig bereitstellen muss und https://dot.net uns keine "vollständige Laufzeit" gibt Installer" (Ich habe nicht einmal den Desktop Runtime Installer gefunden, also keine Wahl) ...

Update: egal, habe die Dokumentation gefunden.

Hey, danke für deine Mühe!

Wie sollen Konfigurationsdateien (z. B. App.config) verteilt werden? Ich habe gerade eine Konsolen-App auf RHEL 7.6 mit der genauen Befehlsfolge erstellt:

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

wobei SomeProj.csproj <PublishTrimmed>true</PublishTrimmed> aktiviert hat und 2 Dateien als Ergebnis erhalten hat: SomeProj.exe und SomeProj.pdb , aber nicht SomeProj.config

@catlion das Standardverhalten für *.config-Dateien zu haben, sollten sie aus dem Bundle ausgeschlossen werden. Standardmäßig sind alle Nicht-PDB-Dateien im Bundle enthalten.
Folgendes schließt die Konfiguration aus der einzelnen Datei aus:

<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

Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)

Headless- und WPF-Apps für Windows

Enthält Ihre App (nicht-.NET) C++/nativen Code?

Ja, wir P/Invoke für eine Vielzahl von nativen DLLs, einige Elemente von Drittanbietern, über die wir keine Kontrolle haben, einige interne von anderen Teams.

Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?

Ja, aber wir verwenden CompilerServices, um sie aus der Quelle zu kompilieren.

Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?

Jawohl

Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?

Ja, unsere App bleibt im Allgemeinen für längere Zeit geöffnet.

Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?

Ja, wir können mehrere Minuten warten.

Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?

Jawohl

Danke @john-cullen

Verknüpfen einiger PRs mit dem Single-Exe- Zweig für eine Prototyp-Implementierung zum Ausführen von Single-File-Apps ohne Extraktion ( Stufe 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

Lassen Sie mich auch einige Antworten für @morganbr geben :) Ich weiß nicht, ob Sie diese noch lesen :)

  1. Mit welcher Art von App würden Sie es wahrscheinlich verwenden? (z. B. WPF unter Windows? ASP.NET in einem Linux-Docker-Container? Etwas anderes?)

Textabenteuer (Konsolen-Apps), die auf verschiedenen Plattformen ausgeführt werden können (Linux, MacOS, Windows)

  1. Enthält Ihre App (nicht-.NET) C++/nativen Code?

Nein.

  1. Würde Ihre App Plugins oder andere externe DLLs laden, die Sie ursprünglich nicht in Ihren App-Build aufgenommen haben?

Derzeit nicht, aber es wäre großartig, auf lange Sicht bestimmte Szenarien zu unterstützen.

  1. Sind Sie bereit, Ihre App neu zu erstellen und neu zu verteilen, um Sicherheitsfixes zu integrieren?

Jawohl.

  1. Würden Sie es verwenden, wenn Ihre App 200-500 ms langsamer startet? Was ist mit 5 Sekunden?

Jawohl.
(Es wäre großartig, eine Textausgabe oder ein Meldungsfeld bereitzustellen, um den Benutzer darüber zu informieren, dass etwas passiert.)

  1. Was ist die größte Größe, die Sie für Ihre App akzeptieren würden? 5 MB? 10? 20? 50? 75? 100?

10-20 MB.

  1. Würden Sie eine längere Release-Build-Zeit akzeptieren, um die Größe und/oder Startzeit zu optimieren? Was ist die längste Zeit, die Sie akzeptieren würden? 15 Sekunden? 30 Sekunden? 1 Minute? 5 Minuten?

1+ Minute ist ok.

  1. Wären Sie bereit, zusätzliche Arbeit zu leisten, wenn dadurch die Größe Ihrer App halbiert würde?

Möglicherweise.

Danke für die Antwort, @lenardg.

Dieses Problem verfolgt den Fortschritt der .NET Core 3.0-Einzeldateiverteilungsfunktion.
Hier ist das Designdokument und der Bereitstellungsplan für das Feature.

Dies ist eine sehr nützliche Funktion, um die Bereitstellung zu vereinfachen und die Größe zu reduzieren.
Einige Verbesserungsgedanken zum Design, insbesondere für Unternehmensbereitstellungen, bei denen die Umgebung über Gruppenrichtlinien streng kontrolliert wird.

  1. Ist es bedingt möglich, beim Packen der einzelnen ausführbaren Datei zu komprimieren?
    dh fügen Sie Wrap-ähnliche Logik hinzu, sodass wir keine Integration anderer Tools benötigen.
    Die komprimierte Datei erzeugt eine noch kleinere exe.

  2. Beim Starten der exe erweitert sie ihren Inhalt in einen temporären Ordner. Für unser Produkt werden die Client-Rechner auf bestimmten Benutzerseiten streng kontrolliert und sie erlauben nicht, dass ausführbare Dateien aus dem temporären Ordner oder sogar den %userprofile%-Speicherorten gestartet werden.

Ist es möglich, anzugeben/zu steuern, wo extrahiert werden soll, oder kann es in einem ".\extract" oder einem solchen Unterordner "in place extract" sein?
Dies ermöglicht die Einhaltung von Gruppenrichtlinien sowie die Möglichkeit, die Single-Exe-Funktion zu verwenden.

  1. Ist es möglich, den Ordner vor dem Packen zu signieren und dann Dateien zum Packen auszuwählen?
    Wir können die einzelne EXE-Datei signieren, aber Extraktdateien sind nicht signiert, und daher ist an bestimmten anderen Client-Standorten die Ausführung nicht zulässig, es sei denn, die Binärdateien sind signiert.

Ich wollte Sie nur wissen lassen, dass ich heute das gleiche Problem wie @Safirion gesehen habe . Ich habe eine dotnetcore 3.0-App, die auf Ubuntu abzielt, und habe sie auf meinem Synology-Server ausgeführt. Es konnte nicht extrahiert werden - es schlug immer wieder mit der Fehlermeldung "Ein schwerwiegender Fehler ist aufgetreten. Inhalt des Pakets konnte nicht extrahiert werden" fehl. Mehrmals umgebaut, aber das gleiche. Nach einem Neustart des Hosts funktionierte es wieder einwandfrei.

Es wäre nützlich zu verstehen, ob es hier eine Dateisperre oder ähnliches gibt und ob es Zeiten gibt, wie man sie debuggt.

@RajeshAKumar dotnet/core-setup#7940

Ich bin mir nicht sicher, wie dieser Link hilft.
Es geht nur um die Temp-Extraktion, ich habe oben 3 Punkte aufgelistet.

Und ich habe dir die Lösung für einen von ihnen gegeben. Bei den anderen 2 habe ich keine Ahnung

Und ich habe dir die Lösung für einen von ihnen gegeben. Bei den anderen 2 habe ich keine Ahnung

Der temporäre Extrakt funktioniert bei uns nicht, daher ist das nicht die Lösung. Meine Anfrage war die Möglichkeit zu steuern, wo es extrahiert oder direkt in einen Unterordner extrahiert werden kann.
Die IT-Administratoren vieler unserer Client-Computer erlauben nicht, ausführbare Dateien aus temporären Ordnern oder aus Benutzerprofilen auszuführen.
Bitte lesen Sie den Beitrag https://github.com/dotnet/coreclr/issues/20287#issuecomment -542497711 erneut

@RajeshAKumar : Sie können DOTNET_BUNDLE_EXTRACT_BASE_DIR festlegen, um den Basispfad zu steuern, in dem der Host den Inhalt des Bundles extrahiert.
Weitere Einzelheiten finden Sie hier: https://github.com/dotnet/designs/blob/master/accepted/single-file/extract.md#extraction -location

@RajeshAKumar : Die Komprimierung der gebündelten Single-exe ist eine Funktion, die für .net 5 in Erwägung gezogen wird: https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md#compression

Im Moment müssen Sie andere Dienstprogramme verwenden, um die generierte Single-exe zu komprimieren.

@RajeshAKumar , in Bezug auf das Signieren können Sie alle Dateien/Binärdateien signieren, die veröffentlicht und in der Single-Exe gebündelt werden. Wenn der Host die eingebetteten Komponenten auf die Festplatte extrahiert, werden die einzelnen Dateien selbst signiert. Sie können auch die erstellte Einzeldatei selbst signieren, wie Sie bereits erwähnt haben.

Erfüllt das Ihre Anforderungen?

@Webreaper Wenn Sie das Problem reproduzieren können, können Sie die App bitte mit aktiviertem COREHOST_TRACE ausführen (setzen Sie die Umgebungsvariable COREHOST_TRACE auf 1 ) und das generierte Protokoll freigeben? Danke.

@swaroop-sridhar
Dies ist eine sehr coole Funktion. Haben Sie einen Link, wann verschiedene Phasen in welcher Dotnet-Version verfügbar sein werden?

@RajeshAKumar : Sie können DOTNET_BUNDLE_EXTRACT_BASE_DIR festlegen, um den Basispfad zu steuern, in dem der Host den Inhalt des Bundles extrahiert.
Weitere Einzelheiten finden Sie hier: https://github.com/dotnet/designs/blob/master/accepted/single-file/extract.md#extraction -location

Danke swaroop-sridhar

@RajeshAKumar , in Bezug auf das Signieren können Sie alle Dateien/Binärdateien signieren, die veröffentlicht und in der Single-Exe gebündelt werden. Wenn der Host die eingebetteten Komponenten auf die Festplatte extrahiert, werden die einzelnen Dateien selbst signiert. Sie können auch die erstellte Einzeldatei selbst signieren, wie Sie bereits erwähnt haben.

Erfüllt das Ihre Anforderungen?

Ich versuche herauszufinden, wie ich das "Kompilieren" unterbrechen und Teile veröffentlichen kann.
Ich verwende derzeit den folgenden Befehl, sodass ich nicht signieren kann.
Setzen Sie publishargs=-c Release /p:PublishSingleFile=True /p:PublishTrimmed=True /p:PublishReadyToRun=false
dotnet publish -r win-x64 -o bin\Output\Win64 %publishargs%

Da die obigen Kompilierungen sowie Trimmungen und Pakete nicht sicher sind, wie man sie bricht.
Um Ihren Ansatz zu nutzen, muss ich ihn idealerweise kompilieren, dann signieren und schließlich veröffentlichen.

@Webreaper Wenn Sie das Problem reproduzieren können, können Sie die App bitte mit aktiviertem COREHOST_TRACE ausführen (setzen Sie die Umgebungsvariable COREHOST_TRACE auf 1 ) und das generierte Protokoll freigeben? Danke.

Danke. Es ist jetzt weg, weil ich neu gestartet habe, aber es ist nützlich, dies zu notieren, falls es erneut auftritt!

@RajeshAKumar Sie müssen die Signierung mit einem Ziel markieren, das kurz vor dem Bündeln ausgeführt wird.
Da Sie PublishReadyToRun und PublishTrimmed verwenden, können Sie die Standardziele Afterbuild oder BeforePublish nicht verwenden.

Sie können ein Ziel hinzufügen, das kurz vor BundlePublishDirectory ausgeführt wird und die Signatur durchführt.

@swaroop-sridhar
Dies ist eine sehr coole Funktion. Haben Sie einen Link, wann verschiedene Phasen in welcher Dotnet-Version verfügbar sein werden?

Danke @etherealjoy. Die Arbeit für einzelne Dateien, die direkt vom Bundle ausgeführt werden, ist im Gange und zielt nach meinem besten Verständnis auf die Veröffentlichung von .net 5 ab.

@RajeshAKumar Sie müssen die Signierung mit einem Ziel markieren, das kurz vor dem Bündeln ausgeführt wird.
Da Sie PublishReadyToRun und PublishTrimmed verwenden, können Sie die Standardziele Afterbuild oder BeforePublish nicht verwenden.

Sie können ein Ziel hinzufügen, das kurz vor BundlePublishDirectory ausgeführt wird und die Signatur durchführt.

Danke.
Der Link, den Sie angegeben haben, sieht aus wie MS Build-Aufgaben.
Wie erstelle ich einen Handler für „BundlePublishDirectory“? Ist das in Studio/Project props/Build Events oder muss ich etwas von Grund auf neu erstellen.

@RajeshAKumar In diesem Fall benötigen Sie etwas Feineres als Pre-Build-Post-Build-Ereignisse.
Also, ich denke, Sie sollten die Projektdatei bearbeiten und etwas hinzufügen wie:

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

Was ist das erwartete Verhalten des Befehls dotnet pack damit? Nehmen wir an, wir haben ein Single-Exe-Artefakt in das lokale Nuget-Repository gepusht. Wenn ich versuche, es mit Chocolatey zu installieren, versucht es, alle in der Projektdatei aufgeführten Nuget-Deps wiederherzustellen. Was vorher erwartet wurde, aber ich bezweifle, ob dieses Verhalten für SFD richtig ist.

Ist es möglich, während des Extrahierens einer eigenständigen WPF-Anwendung mit einer einzelnen Datei einen Fortschrittsbalken oder eine Ladeanzeige hinzuzufügen, kann es einige Zeit dauern, bis einfach nichts passiert.
Eine einfache eigenständige WPF-App benötigt mehr als 80 MB und die Extraktion kann mehr als 5 Sekunden dauern. Es ist nicht sehr benutzerfreundlich und ich habe Beschwerden von meinen Endbenutzern erhalten.

Bearbeiten: Gibt es eine Möglichkeit, die alte Version beim Start automatisch zu bereinigen?

@Safirion Ich kann nicht sehen, wie das für diese Funktion in den Geltungsbereich fallen könnte. Wenn Sie dies wünschen, können Sie am besten Ihre eigene kleine App erstellen, die einen Begrüßungsbildschirm anzeigt und die echte App startet, und dann die echte App das Begrüßungsbildschirmprogramm stoppen lassen, wenn sie gestartet wird.

@ProfessionalNihilist Ich glaube, Sie verstehen meinen Punkt nicht.
Eine leere, eigenständige WPF-App verwendet beim Kompilieren 80 MB Festplattenspeicher. Sie können keine winzigere WPF-App als 80 Monate haben, ohne sie als Framework-abhängige App zu kompilieren 😉
Das Problem ist der Zeitpunkt der Extraktion des enthaltenen Frameworks, bevor die App überhaupt gestartet werden kann. Es muss also vom .Net Core erledigt werden und hängt vollständig mit dieser Funktion zusammen.

Vielleicht fügen Sie die Möglichkeit hinzu, ein png zu haben, das angezeigt wird, während die App dekomprimiert wird?

@Safirion @ayende das Fehlen von "UI-Feedback" während des Starts wird hier verfolgt: https://github.com/dotnet/core-setup/issues/7250

Was ist das erwartete Verhalten des Befehls dotnet pack damit? Nehmen wir an, wir haben ein Single-Exe-Artefakt in das lokale Nuget-Repository gepusht. Wenn ich versuche, es mit Chocolatey zu installieren, versucht es, alle in der Projektdatei aufgeführten Nuget-Deps wiederherzustellen. Was vorher erwartet wurde, aber ich bezweifle, ob dieses Verhalten für SFD richtig ist.

@catlion die Eigenschaft PublishSingleFile wird nur vom Befehl dotnet publish unterstützt. Es hat also keine Auswirkungen auf dotnet pack . Gibt es eine Motivation, sowohl Single File als auch Packaging zu verwenden?

Bearbeiten: Gibt es eine Möglichkeit, die alte Version beim Start automatisch zu bereinigen?

@Safirion in der aktuellen Version ist die Bereinigung manuell, der Host versucht nicht, die extrahierten Dateien zu entfernen, da sie möglicherweise in zukünftigen Läufen wiederverwendet werden könnten.

Ok, ich werde meinen eigenen Reiniger machen 😉
Danke für Ihre Antwort.

@cup , das ist nichts Besonderes an Mono, das ist nur eine Standardkompilierung, fügen Sie jetzt eine Nuget-Referenz hinzu und diese Lösung ist keine einzelne Datei mehr. Mono hat jedoch mkbundle , um einzelne Dateien zu erreichen

@Suchiman bist du sicher? Mein obiges Beispiel erzeugt eine einzelne 3-KB-Datei. Während die Mindestgröße von dotnet 27 MB zu betragen scheint:

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

@cup ja

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 bist du sicher? Mein obiges Beispiel erzeugt eine einzelne 3-KB-Datei. Während die Mindestgröße von dotnet 27 MB zu betragen scheint:

#24397 (Kommentar)

Ihre 3k-Datei funktioniert nur, weil Mono bereits installiert ist. Der springende Punkt bei der Einzeldateiverteilung von dotnetcore ist, dass Sie die clr nicht installieren müssen, es ist eine eigenständige einzelne EXE-Datei, einschließlich der Laufzeit.

@Webreaper eigentlich glaube ich, dass es nur mcs von Mono zum Kompilieren verwendet hat, da er mono sun-mon.exe nicht geschrieben hat, lief es wahrscheinlich auf .NET Framework.

Aber .NET Core unterstützt auch das vorinstallierte Runtime-Szenario, auch Framework-abhängige Bereitstellung genannt. In diesem Fall handelt es sich jedoch immer noch nicht um eine einzelne Dateibereitstellung, da es einige zusätzliche Dateien für .NET Core gibt, z. B. .deps.json und .runtimeconfig.json

@chris3713 Der beste Weg für den Zugriff auf den exe-Speicherort ist derzeit das PInvoke-ing zu nativen APIs. Zum Beispiel: GetModuleFileNameW (Null, <buffer>, <len>)

Es scheint, dass Environment.CurrentDirectory eine bessere Lösung ist, obwohl ich beide Ansätze noch nicht auf etwas anderem als Windows ausprobiert habe.

EDIT: Nein. Dieser Pfad kann sich an verschiedenen Einstiegspunkten in der Anwendung ändern. Nicht gut.

In einer etwas verwandten Anmerkung fand ich diese Regression bei der Einzeldateiveröffentlichung von Blazor-Apps in der neuesten Vorschau von VS für Mac: https://github.com/aspnet/AspNetCore/issues/17079 – ich habe es unter gemeldet AspNeCore/Blazor, aber es kann sein, dass dies für die Coreclr-Gruppe relevanter ist - nicht sicher. Überlasse es euch, sich zu bewegen!

@Suchiman Vorsicht, dieser Compiler hat Probleme:

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

@cup , außer dass Sie mit dem von mir benannten Dateipfad den alten C # 5-Compiler verwenden, der in C ++ geschrieben wurde, das ist nicht roslyn, und sie werden dieses Problem wahrscheinlich aus diesem Grund schließen. Aber Roslyn kann dasselbe tun, nur einen anderen Weg ...

In einer etwas verwandten Anmerkung fand ich diese Regression bei der Einzeldateiveröffentlichung von Blazor-Apps in der neuesten Vorschau von VS für Mac: aspnet/AspNetCore#17079 – Ich habe sie unter AspNeCore/Blazor gemeldet, aber es kann sein, dass dies der Fall ist ist relevanter für die coreclr-Gruppe - nicht sicher. Überlasse es euch, sich zu bewegen!

@Webreaper Vielen Dank für die Meldung des Problems, das wie ein ASP.net-Problem in Bezug auf statische Assets aussieht. Also, das ist der richtige Ort, um es einzureichen.

* Beitrag von einer anderen Ausgabe hierher verschieben.

@swaroop-sridhar,

Die Startzeiten von DotNet Core Single File WPF-Apps sind viel langsamer als die ursprüngliche ILMerge-ed WPF-Anwendung, die auf .net 4.7 erstellt wurde. Ist dies zu erwarten oder wird sich dies in Zukunft verbessern?

Builds stammen von meinem ImageOptimizer: https://github.com/devedse/DeveImageOptimizerWPF/releases

| Geben Sie | ein Geschätzte Erststartzeit | Geschätzte zweite Startzeit | Größe | Downloadlink |
| -- | -- | -- | -- | -- |
| .NET 4.7.0 + ILMerge | ~3 Sek. | ~1 Sek. | 39,3 MB | VERKNÜPFUNG |
| dotnet publish -r win-x64 -c Release --self-contained=false /p:PublishSingleFile=true | ~10 Sek. | ~3 Sek. | 49mb | |
| dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true | ~19 Sek. | ~2 Sek. | 201mb | |
| dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true | ~15 Sek. | ~3 Sek. | 136mb | VERKNÜPFUNG |
| dotnet publish -r win-x64 -c Release | ~2,5 Sek. | ~1,5 Sek. | 223 KB für exe (+400 MB in DLLs) | |

@devedse , um sicherzugehen, ist der "zweite Start" der Durchschnitt mehrerer Läufe (außer dem ersten)?
Ich bin neugierig, aber es fehlt eine Erklärung dafür, warum der /p:PublishSingleFile=true /p:PublishTrimmed=true -Lauf langsamer sein sollte als der ` /p:PublishSingleFile=true -Lauf.

Bevor ich also nachforsche, möchte ich sicherstellen, dass die Zahlen im "zweiten Start" stabile Zahlen sind und dass der Unterschied im Start reproduzierbar ist.

Außerdem geht es in dieser Ausgabe um Single-File-Plug-Ins. Können Sie die Perf-Diskussion bitte in eine neue Ausgabe oder nach dotnet/coreclr#20287 verschieben? Danke.

@swaroop-sridhar , als Antwort auf Ihre Frage, ob es sich um den Durchschnitt handelt:
Es ist ein bisschen schwierig für mich, dies sehr genau zu timen, also wurde das Timing durchgeführt, indem ich gezählt habe, während die Anwendung gestartet wurde, und es dann ein paar Mal versucht habe, um zu sehen, ob es einen signifikanten Unterschied in der Startzeit gibt. Wenn Sie eine bessere Methode kennen, können Sie sie leicht reproduzieren, indem Sie meine Lösung erstellen: https://github.com/devedse/DeveImageOptimizerWPF

Meine Hauptfrage bezieht sich darauf, warum es länger dauert, bis eine gebündelte (einzelne Datei) Anwendung im Vergleich zu einer entbündelten .exe-Datei gestartet wird.

Ich kann mich hier irren, aber es macht für mich Sinn, da eine einzelne Datei einen Overhead verursacht. Im Wesentlichen haben Sie eine App, die eine andere App startet. Während die ILMerge direkt startet. ILMerge hat nur referenzierte DLLs in die Exe zusammengeführt, es hat das Ganze nicht in eine andere Ebene gepackt, was derzeit mit PublishSingleFile gemacht wird.

@devedse Die einzelne Datei extrahiert im Wesentlichen, überprüft die Prüfsummen usw., bevor der dotnet-Lauf gestartet wird.
Denke deswegen hat es so lange gedauert.
Der Extrakt wird "zwischengespeichert", sodass beim nächsten Lauf kein IO-Overhead anfällt.

@RajeshAKumar , hmm, ist in diesem Szenario wirklich der richtige Weg? Wäre es nicht besser, den ILMerge-Weg zu gehen und die DLLs tatsächlich zu einem einzigen Bündel zusammenzuführen?

Insbesondere bei größeren .exe-Dateien verursachen Sie auch die Kosten für den Speicherplatz, um alle Dateien dann zweimal zu speichern.

@devedse Wir warten alle auf die nächsten Phasen dieser Funktion (Run from Bundle), aber im Moment ist dies die einzige Lösung. 😉

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

Dies ist, was Sie für die Verwendung von JIT auf dem Desktop erhalten. Langsamer Start, sieht so aus, als hätte nur Apple dies verstanden

(Meistens wiederholen, was bereits gesagt wurde):
Der erste Start wird voraussichtlich viel langsamer sein – er extrahiert die App auf die Festplatte – so viel E / A. Zweite und nachfolgende Starts sollten fast identisch mit der Nicht-Einzeldatei-Version der App sein. Bei unseren internen Messungen konnten wir keinen Unterschied feststellen.

Wie zu messen: Wir haben Tracing (ETW unter Windows) verwendet - es gibt Ereignisse, wenn der Prozess startet, und dann gibt es Laufzeitereignisse, die dafür verwendet werden können - es ist jedoch nicht ganz einfach.

Wie von @Safirion erwähnt, arbeiten wir an der nächsten Verbesserung für Einzeldateien, die den größten Teil des verwalteten Codes direkt aus der EXE-Datei ausführen sollten (kein Extrahieren auf die Festplatte). Kann aber noch keinen Release Train versprechen.

JIT: Das gesamte Framework sollte mit Ready2Run (CoreFX, WPF) vorkompiliert werden, sodass beim Start nur der Anwendungscode JITed werden sollte. Es ist nicht perfekt, aber es sollte einen großen Unterschied machen. Angesichts der Startzeiten von ~ 1-2 Sekunden denke ich, dass es diese bereits in allen Tests verwendet.

Vielen Dank an alle, ich war mir nicht bewusst, welche nächsten Schritte geplant sind. Das verdeutlicht es.

Der erste Start wird voraussichtlich viel langsamer sein – er extrahiert die App auf die Festplatte – so viel E / A.

Das hätte nie passieren dürfen, Sie machen die Benutzererfahrung BY DESIGN schrecklich, schreckliche Wahl, so bringen Sie Benutzer dazu, die Technologie zu hassen, die der Entwickler für sie verwendet

Wie von @Safirion erwähnt, arbeiten wir an der nächsten Verbesserung für Einzeldateien, die den größten Teil des verwalteten Codes direkt aus der EXE-Datei ausführen sollten (kein Extrahieren auf die Festplatte). Kann aber noch keinen Release Train versprechen.

Warum das jetzt offiziell veröffentlichen, wenn sich das bald ändern wird? sollte als Vorschau/experimentell gekennzeichnet sein

Meiner Meinung nach ist dies Zeit- und Ressourcenverschwendung, konzentrieren Sie sich auf die AOT-Kompilierung und das Tree-Shaking, legen Sie alle Ihre Ressourcen dort ab, hören Sie mit Hacks auf

@RUSshy Warum so viel Hass? Wenn Sie die Startverzögerung beim ersten Start nicht möchten, verwenden Sie keine Einzeldateibereitstellung.

Ich finde, der Start dauert deutlich weniger als 10 Sekunden, und da es nur das erste Mal ist, dass Sie laufen, ist es überhaupt kein Problem. Ich stelle eine serverseitige Webanwendung bereit, was bedeutet, dass sie in den meisten Fällen einmal gestartet und dann Tage/Wochen lang ausgeführt wird, sodass die anfängliche Extraktion im Schema der Dinge vernachlässigbar ist - daher würde ich dies als Stop-Gap, bis es ein einzeln kompiliertes Image gibt, weil es die Bereitstellung viel einfacher macht, als Hunderte von DLLs überall hin zu kopieren.

+1 In meinem Fall haben wir einen Build-Docker, der eine einzelne exe generiert, und einen separaten Docker, um die App auszuführen (unter Verwendung eines regulären Alpine-Docker-Image ohne Dotnet). Nach dem Bulid-Schritt laden wir den Runtime-Container einmal im laufenden Betrieb und docker-commit den Layer. In der Folge haben wir keine Performance-Regression im Vergleich zu einer Framework-abhängigen Bereitstellung beobachtet. Sobald der Load-from-Bundle-File-Mechanismus implementiert und ausgeliefert wurde, entfernen wir den Hot-Loading-Zwischenschritt.

@vitek-karas, gibt es ein Problem bei der Verfolgung der Funktion "Laufzeit-Assets aus Bundle laden"? daran interessiert zu verstehen, welche Art von Hindernissen es gibt. :)

@am11 Wir stellen gerade den Detailplan zusammen. Sie können sich den erstellten Prototyp unter https://github.com/dotnet/coreclr/tree/single-exe ansehen. Die reale Umsetzung wird wahrscheinlich nicht allzu anders sein (offensichtlich besseres Factoring usw., aber die Kernidee scheint solide zu sein).

@Webreaper Für Web-Apps ist dies überhaupt kein Problem, aber vielleicht, weil .Net Core 3 jetzt für die WPF/WinForm-Entwicklung empfohlen wird und das Teilen einer Desktop-Anwendungs-.exe, die in hundert .dll verloren geht, keine Option ist, dann bin ich total verstehen Sie die Frustration im Zusammenhang mit der ersten Phase dieser Funktion.
;)

Und kein Benutzer wartet heute 10 Sekunden (oder mehr als 3 Sekunden), bevor er erneut auf eine EXE-Datei klickt. Die Tatsache, dass es keine Ladeanzeige gibt, ist das zweite große Problem dieser Funktion. Leider scheint es, dass die Ladeanzeige kein Teil von .Net Core 3.1 sein wird, also müssen sich die Benutzer gedulden...

Desktop-Entwickler warten wirklich auf Phase 2, und ich gehe davon aus, dass dies ein Teil von .Net 5 sein wird, denn eigentlich ist die Desktop-Entwicklung in .Net Core eine wirklich schlechte Erfahrung für Endbenutzer.

@RUSshy Warum so viel Hass? Wenn Sie die Startverzögerung beim ersten Start nicht möchten, verwenden Sie keine Einzeldateibereitstellung.

Das ist kein Hass, das ist konstruktives und ehrliches Feedback, ich interessiere mich für C# und .net, ich benutze beides jeden Tag, ich möchte nicht, dass es durch GO oder etwas anderes ersetzt wird

erst kürzlich:
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/

Negatives Feedback ist genauso hilfreich wie positives Feedback, aber wenn Sie es als "Hass" auffassen, kann ich Ihnen nicht helfen

Die .net-Community ist viel zu still, passiv und voreingenommen, Störungen sind der einzige Weg

.NET ist heutzutage objektiv die beste Plattform für die meisten Anwendungen. Ich wünschte, mehr Menschen würden das erkennen.

Die Kriegsgeschichten, die ich von anderen Plattformen wie Java, Go, Rust, Node, ... höre, sind ehrlich gesagt verstörend. Diese Plattformen sind Produktivitätskiller.

Meiner Meinung nach ist dies Zeit- und Ressourcenverschwendung, konzentrieren Sie sich auf die AOT-Kompilierung und das Tree-Shaking, legen Sie alle Ihre Ressourcen dort ab, hören Sie mit Hacks auf

Ich stimme zu. .Net hat ein großartiges Typensystem. Zu oft wird es durch Reflektion umgangen. Die Werkzeuge müssen sich auf AOT konzentrieren, aber auch auf die Minimierung der Reflexion. https://github.com/dotnet/corert/issues/7835#issuecomment -545087715 wäre ein sehr guter Anfang. Der Milliarden-Dollar-Fehler von Nullen wird jetzt gemildert; Dasselbe sollte mit Reflexion mit einer Einstellung oder Markierung für reflexionsfreien Code (oder anderweitig Linker- oder Corert-kompatibler Code) erfolgen.

Das Eliminieren der Reflexion wäre großartig. So viel Leid ließe sich vermeiden, wenn das Nachdenken verboten wäre. Meine letzte Horrorgeschichte war die Entdeckung, dass ich Code nicht verschieben konnte, weil das verwendete Framework (Service Fabric SDK) es für ratsam hielt, die serialisierten Bytes an den Assemblynamen der Implementierung des Serialisierungsprogramms zu binden, ohne dass eine Überschreibung möglich war.

Jeder Fortschritt hin zu einer entmutigenden Reflexion wäre ein Fortschritt.

Übrigens suchte nach einer Möglichkeit, Assemblys zusammenzuführen, um die Bündelgröße und Ladezeiten zu reduzieren und eine Optimierung des gesamten Programms zu ermöglichen. Ich nehme an, dieses Problem ist nicht wirklich darauf ausgerichtet.

Bearbeiten: Da dieser Beitrag einige Reaktionen gesammelt hat, nur um das zu verdeutlichen. Ich glaube, Metaprogrammierung sollte zur Designzeit stattfinden, wo der Code die Daten sind und sie unter meiner Kontrolle stehen.

Typen, die ich gerne verwende, um Invarianten zu erzwingen, denen ich vertrauen kann. Laufzeitreflexionen brechen dieses Vertrauen.

Daher möchte ich, dass die Laufzeitreflexion durch die Designzeit-Metaprogrammierung ersetzt wird. Wo es auch leistungsfähiger sein könnte, sich mit Anwendungsfällen wie Analysatoren, Quick Fixes und Refactoring zu überschneiden.

Markieren von Abonnenten dieses Bereichs: @swaroop-sridhar
Benachrichtigen Sie danmosemsft, wenn Sie abonniert werden möchten.

Single-File-Feature-Design ist in diesem Dokument enthalten: https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/design.md
Verfolgung des Fortschritts von Single-File-Apps in dieser Ausgabe: https://github.com/dotnet/runtime/issues/36590.
Vielen Dank an alle für Ihr Feedback und Ihre Vorschläge zu dieser Ausgabe.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

v0l picture v0l  ·  3Kommentare

yahorsi picture yahorsi  ·  3Kommentare

noahfalk picture noahfalk  ·  3Kommentare

EgorBo picture EgorBo  ·  3Kommentare

chunseoklee picture chunseoklee  ·  3Kommentare