Powershell: Ist es Zeit für "PowerShell vZeroTechnicalDebt" und / oder für einen Opt-In-Mechanismus für neue / feste Funktionen, die die Abwärtskompatibilität beeinträchtigen?

Erstellt am 26. Apr. 2018  ·  69Kommentare  ·  Quelle: PowerShell/PowerShell

Beachten Sie, dass der Begriff "technische Schulden" hier lose verwendet wird, um "akkumuliertes gebrochenes Verhalten zu bedeuten, das nicht behoben werden kann, ohne die Abwärtskompatibilität zu brechen";


_Update_: @rjmholt hat offiziell eine Diskussion darüber gestartet, wie wichtige Änderungen implementiert und verwaltet werden können: # 13129.


Hinweis: Dieses Problem, das sich aus https://github.com/PowerShell/PowerShell/issues/5551#issuecomment -380522712 ergab, dient nur dazu , die Diskussion zu starten, um festzustellen,

Das unerschütterliche Engagement von PowerShell für die Abwärtskompatibilität hat der Community im Laufe der Jahre sehr gute Dienste geleistet.

Auf der anderen Seite war das unvermeidliche Nebenprodukt die Anhäufung technischer Schulden, die das Auswendiglernen von Ausnahmen erfordert und ein Hindernis für Neuankömmlinge darstellt.

Bestimmte grundlegende Probleme, die heute bestehen, können nur auf Kosten der Abwärtskompatibilität gelöst werden, und es gibt zwei - sich nicht gegenseitig ausschließende - Möglichkeiten, damit umzugehen:

  • Implementierung einer "PowerShell vZeroTechnicalDebt" -Version, die alle technischen Schulden beseitigt, jedoch die Abwärtskompatibilität einbüßt (möglicherweise mit zukünftigen Versionen, die eine semantische Versionierung verwenden, um die Kompatibilität anzuzeigen)

  • Integration von Funktionen / Korrekturen, die die Abwärtskompatibilität beeinträchtigen, in die vorhandene Codebasis, die ausschließlich auf Opt-In-Basis verfügbar ist.

Welche Ansätze sind wir gegebenenfalls in Betracht zu ziehen?
Sobald wir Klarheit darüber haben, können wir die Prozesse ausarbeiten.

Hier sind einige der bestehenden grundlegenden Probleme aufgeführt, die nur auf Kosten der Abwärtskompatibilität gelöst werden können. Ich bin sicher, andere werden an mehr denken:

Umgebungsdaten

Geschrieben ab:

PowerShell Core v6.0.2
Issue-Meta

Hilfreichster Kommentar

Es ist teuer, Probleme zu beheben, die ich als die technische Schuld von PowerShell betrachte, die keine neuen .NET-Konzepte übernommen haben

  • Sprachsyntax für Typparameter für generische Methoden # 5146

  • Engine-Unterstützung für Extension Methods , die automatisch im Typsystem auftaucht (wie in _compiled_ .Net-Sprachen). # 2226

  • Sprachunterstützung für asynchrone APIs # 6716 (und RFC )

Es gibt einige bedauerliche Merkmale:

  • Könnten wir etwas tun, das auf Typhinweisen basiert (wie FormatPx ), anstatt Cmdlets, die Formatierungsobjekte ausgeben? # 4594 # 4237 # 3886

  • Würden Sie den Registrierungsanbieter so normalisieren, dass er auf Inhalten basiert - anstatt sich wie eine Demo zu fühlen, wie ein Immobilienanbieter arbeiten könnte? # 5444

  • Würden Sie PSProviders gründlich überarbeiten, um das Schreiben zu vereinfachen? Es ist eine Schande, dass zwei Abstraktionsebenen erforderlich sind, um zu "SHiPS" zu gelangen und den Menschen endlich die Möglichkeit zu geben, Anbieter zu schreiben, die sie nutzen möchten

Wie wäre es mit einer größeren Frage:

Wären wir bereit, den Ansatz "Viele Wege sind besser" zu überdenken und an einem Ansatz "Erfolgsgrube" zu arbeiten? Ich meine, wären wir bereit, Funktionen zu entfernen, die als "der einfache Weg" gelten, aber grundsätzlich schlechter sind, um nur "den richtigen Weg" zu haben, um Dinge zu tun? Z.B:

  • Stellen Sie CmdletBinding immer ein
  • Die Notation @ () bedeutet List[PSObject]
  • Machen Sie @ {} zu einem Dictionary[PSObject, PSObject] (oder Dictionary[string, PSObject] 😲)
  • Machen Sie _Process_ zum Standardblock
  • Vielleicht sogar _ValueFromPipelineByPropertyName_ zum Standard machen ;-)

Alle 69 Kommentare

Interessant. Ich habe mich immer gefragt, warum das 1 in .ps1 verwendet wird, um PowerShell-Skripten eine Art semantische Versionierung hinzuzufügen, sodass ein Skript anzeigen kann, ob es an mögliche Änderungen angepasst wurde.

Es ist teuer, Probleme zu beheben, die ich als die technische Schuld von PowerShell betrachte, die keine neuen .NET-Konzepte übernommen haben

  • Sprachsyntax für Typparameter für generische Methoden # 5146

  • Engine-Unterstützung für Extension Methods , die automatisch im Typsystem auftaucht (wie in _compiled_ .Net-Sprachen). # 2226

  • Sprachunterstützung für asynchrone APIs # 6716 (und RFC )

Es gibt einige bedauerliche Merkmale:

  • Könnten wir etwas tun, das auf Typhinweisen basiert (wie FormatPx ), anstatt Cmdlets, die Formatierungsobjekte ausgeben? # 4594 # 4237 # 3886

  • Würden Sie den Registrierungsanbieter so normalisieren, dass er auf Inhalten basiert - anstatt sich wie eine Demo zu fühlen, wie ein Immobilienanbieter arbeiten könnte? # 5444

  • Würden Sie PSProviders gründlich überarbeiten, um das Schreiben zu vereinfachen? Es ist eine Schande, dass zwei Abstraktionsebenen erforderlich sind, um zu "SHiPS" zu gelangen und den Menschen endlich die Möglichkeit zu geben, Anbieter zu schreiben, die sie nutzen möchten

Wie wäre es mit einer größeren Frage:

Wären wir bereit, den Ansatz "Viele Wege sind besser" zu überdenken und an einem Ansatz "Erfolgsgrube" zu arbeiten? Ich meine, wären wir bereit, Funktionen zu entfernen, die als "der einfache Weg" gelten, aber grundsätzlich schlechter sind, um nur "den richtigen Weg" zu haben, um Dinge zu tun? Z.B:

  • Stellen Sie CmdletBinding immer ein
  • Die Notation @ () bedeutet List[PSObject]
  • Machen Sie @ {} zu einem Dictionary[PSObject, PSObject] (oder Dictionary[string, PSObject] 😲)
  • Machen Sie _Process_ zum Standardblock
  • Vielleicht sogar _ValueFromPipelineByPropertyName_ zum Standard machen ;-)

Alles tolle Vorschläge, @Jaykul.

Die Neuformulierung von @() bedeutet List[PSObject] : Ich denke, wir können dies weiterentwickeln und einen effizient erweiterbaren Sammlungstyp als grundlegenden Sammlungstyp von PowerShell verwenden, sodass er überall dort verwendet wird, wo [object[]] Derzeit ist (und wird sowohl intern als auch bei der Rückgabe von Sammlungen ohne Leistungseinbußen bei der Typkonvertierung verwendet). Es gibt Herausforderungen + Verwendung von @PetSerAl hat eine benutzerdefinierte .

Abgesehen davon, dass Process {} der Standardblock in Funktionen ist: Es ist das, was Filter derzeit tut, aber es ist auf den - implizierten - Process Block und diese Funktionsvariante beschränkt anscheinend nie wirklich verstanden; Die beiden im Kontext von Function vereinen, macht für mich Sinn.

Witzig, wenn die Azure PowerShell-Community gerade einen Standup-Aufruf ausführt und von AzureRm zu einem neuen Az-Modul wechselt, das plattformübergreifend ist (kein separates AzureRm.Core) und bei dem alle Befehlspräfixe von AzureRm in Az geändert wurden. Die beiden werden eine Weile nebeneinander sein, aber sie wechseln zum neuen Befehlssatz.

Schade, dass PowerShell noch keine Gelegenheit hatte, eine neue ausführbare Datei zu erstellen, die neben Windows PowerShell ausgeführt wird, die sich jedoch von einigen der alten Probleme lösen könnte, die sie nach unten ziehen.

Stellen Sie sich vor, was passieren würde, wenn wir es versuchen:
Realistisch gesehen würde es mindestens 6 Monate dauern, bis eine Version ohne Reue erstellt wurde, und weitere 6 Monate, um sie zu wiederholen. Dann müssen sich auch Module von Drittanbietern daran anpassen, damit diese Version nützlich ist. Es wird mindestens weitere 6 Monate dauern, bis eine angemessene Abdeckung erreicht ist (und bedenken Sie, dass einige Module dies niemals tun werden) Verzögerung und unerwartete Probleme usw. Also, nein, ich denke, es ist nur ein Wunschdenken, dass man alle technischen Schulden in einer Version auf einmal loswerden kann (und trotzdem die alte Version entwickeln und nicht nur beibehalten) kann.

So sehr ich mir wünschte, dass eine solche Version existiert, denke ich, dass es nur möglich sein wird, langsam eine bahnbrechende Änderung nach der anderen zu erreichen. Mit v6 wurden bereits viele wichtige Änderungen akzeptiert, aber ich denke, wenn zu viele wichtige Änderungen in einer Version enthalten sind, wird es zu komplex, vorhandene Skripte / Module zu aktualisieren. Es ist gut, die wertvollsten Änderungen zu diskutieren, aber bis es keine LTS-Version von pwsh gibt, denke ich nicht, dass es an der Zeit ist, über einen zweiten Zug von pwsh mit wesentlicheren Änderungen parallel zur bestehenden Mainstream-Version nachzudenken.

@bergmeister Einverstanden. Selbst relativ kleine Änderungen auf einem Kernpfad können die Einführung jedoch ernsthaft behindern. Schauen Sie sich Python 3 an. Es hat 10 Jahre gedauert, bis wir uns wirklich durchgesetzt haben. Mit viel größeren Änderungen, wer weiß, wie lange es dauern wird, bis Perl 6 dominant ist (und es hat 15 Jahre gedauert, bis sie die richtigen Sachen gefunden haben, also scheinen 1,5 Jahre für PowerShell ++ optimistisch :-)) brechen Sie die Dinge regelmäßig, möglicherweise aufgrund der Art und Weise, wofür sie verwendet werden.

Python 3 ist sicherlich die Horrorshow, hat es sich schon wirklich durchgesetzt? Ich verwende immer noch 2.7 und plane kein baldiges Upgrade. Aber ich habe in letzter Zeit auch nicht viel über Perl 6 gehört ...

Ich denke, die Lehren, die man aus Python ziehen kann, bestehen darin, wichtige Änderungen an der Sprache von einer Versionsänderung an der Engine zu trennen. Hypothetisch könnte eine PS 7-Engine noch frühere Skriptdateien (.PS1) in einem unveränderlichen Änderungsmodus ausführen, während sie, wenn das Skript als 7-fähig markiert wäre (z. B. mit der Erweiterung .PS7), deklarieren könnte, dass sie aktualisiert wurden Für die Ausführung ist mindestens PS 7 erforderlich. Hoffe das macht Sinn.

Die vielleicht beste Erfolgsgeschichte ist JavaScript / TypeScript / Babel. Ein Transpiler (mit Quellkartenunterstützung) scheint der richtige Weg für die Sprachentwicklung zu sein.

Javascript ist ein Sonderfall. Du steckst so ziemlich fest, also ist das Transpilieren wirklich die einzige Option. Typoskript ist "nur" Javascript mit Erweiterungen, so dass es für die Benutzer einfach zu übernehmen ist. Jedes Javascript-Programm ist ein Typoskript-Programm. Sie beginnen also mit dem, was Sie haben, und fügen von dort aus einfach Anmerkungen hinzu. Dart hingegen ist eine eigene Sprache, wird jedoch entweder in Javascript oder in eine native Laufzeit in Chrome übertragen (zumindest war dies zu einem bestimmten Zeitpunkt geplant). Dart scheint außerhalb von Google nicht viel Akzeptanz gefunden zu haben, wahrscheinlich weil es seine eigene Sprache ist.

@ BurtHarris

Python 3 ist sicherlich die Horrorshow, hat es sich schon wirklich durchgesetzt?

Ich habe letzte Woche einen Artikel gelesen, in dem der Autor behauptete, für Python 3 sei eine kritische Masse erreicht worden. Alle Kernmodule seien verfügbar, und jetzt würden Menschen in Scharen migrieren. Wir werden sehen..

Interessant. Ich habe mich immer gefragt, warum die 1 in .ps1 verwendet wird, um PowerShell-Skripten eine Art semantische Versionierung hinzuzufügen, sodass ein Skript anzeigen kann, ob es an mögliche Änderungen angepasst wurde.

WRT .ps1 , wir haben uns das Recht vorbehalten, die Erweiterung zu ändern, falls die Sprache völlig falsch ist, was zu katastrophalen Änderungen an der Laufzeit führt, sodass Skripte für die vorherige Version einfach nicht funktionieren. Das Ändern der Erweiterung führt jedoch auch zu einem enormen Arbeitsaufwand, da so viele Dinge im Ökosystem mit einer Erweiterung verbunden sind. Es ist also nicht leichtfertig zu tun. Und natürlich müssten wir als Teil von Windows, wenn wir die Erweiterung verzweigen würden, immer noch beide Versionen beibehalten (ähnlich wie Python 2/3).

@bergmeister :

Gültige Bedenken, aber im Sinne von:

Es ist gut, die wertvollsten Änderungen zu besprechen

Bitte teilen Sie alle, die Sie vielleicht im Sinn haben.

langsam eine brechende Änderung nach der anderen

Während ein (lexikalischer) Opt-In-Mechanismus für inkompatible Änderungen eine Lösung darstellt, mache ich mir zwei Sorgen:

  • Die schrittweise Einführung kann dazu führen, dass sich niemand daran erinnern kann, welche Version für welche Funktion erforderlich ist. Perl (v5-) fällt mir ein.

  • Die Codebasis wird aufgebläht und schwer zu warten, und die resultierende Binärdatei wird gleichermaßen aufgebläht, was die Startleistung (zumindest) beeinträchtigt.

Ich habe es schon einmal gesagt: Für mich - und das ist nur eine Vermutung - war der v6 GA ein unglücklicher Kompromiss zwischen der Unzufriedenheit von Oldtimern mit bahnbrechenden Änderungen und der Weitergabe von genügend Gepäck, um die Einführung in der Unix-Welt zu verhindern.

Angesichts der relativen Jugend von PowerShell in der Unix-ähnlichen Welt besteht (noch) eher die Bereitschaft, Probleme durch inkompatible Änderungen zu lösen. Wie @BrucePay feststellt , muss Windows PowerShell ohnehin gewartet werden und kann der sichere Hafen für die Abwärtskompatibilität bleiben.

Ich denke, das Ausmaß der negativen Folgen solcher bahnbrechenden Veränderungen wurde bereits abgedeckt, und ich stimme den meisten dieser Punkte zu. Ich schreibe dies, weil ich bezweifle, dass diese Änderungen im größeren Zusammenhang überhaupt erhebliche Vorteile bringen würden. Zumindest für die Art, wie ich PowerShell benutze.

Das OP enthält die folgende Aussage:

Auf der anderen Seite war das unvermeidliche Nebenprodukt die Anhäufung technischer Schulden, die das Auswendiglernen von Ausnahmen erfordert und ein Hindernis für Neuankömmlinge darstellt.

Die implizite Prämisse dieser Aussage scheint zu sein, dass das Durchführen dieser verschiedenen bahnbrechenden Änderungen die Last des Auswendiglernen von Ausnahmen verringern würde. Das wäre in der Tat ein großartiges Ergebnis. Ich bin jedoch skeptisch, dass dies das Ergebnis sein würde. Das Verhalten von PowerShell ist bewusst umfangreich. Dies macht es sowohl ausdrucksstark als auch unvorhersehbar. Ausdruckskraft und Vorhersehbarkeit scheinen gegeneinander zu wirken, zumindest unter den Sprachen, die ich kenne.

Ich stimme zwar zu, dass viele der oben genannten bahnbrechenden Änderungen in einigen Fällen die Vorhersagbarkeit etwas verbessern würden, aber viele unvorhersehbare und überraschende Aspekte der Sprache bleiben bestehen. Obwohl ich jahrelang PowerShell geschrieben habe, bin ich immer noch häufig überrascht über das Verhalten von PowerShell, das beabsichtigt zu sein scheint und wahrscheinlich nicht geändert werden sollte. Einige aktuelle Beispiele, die mir in den Sinn kommen, sind folgende:

  • bedingte verzögerte Bindung von [scriptblock] Argumenten (# 6419)
  • wenn genau implizite Aufzählung auftritt (# 5832)
  • Konvertierung von [AutomationNull]::Value in $null während der Parameterbindung (# 6357 ist verwandt)
  • die Auswirkungen von break und continue auf den Kontrollfluss in der Pipeline (# 5811)
  • Was passiert, wenn Sie $null ( SO ) teilen?
  • Wie sich die Verwendung von Skriptblöcken über Sitzungsstatus hinweg auf $_ ( SO 1 , SO 2 ) auswirkt

Ich gehe davon aus, dass diese Beispiele nur einen kleinen Bruchteil der vielen anderen sorgfältig entworfenen, aber überraschenden Nuancen darstellen, die ich noch nicht entdeckt habe. Ich habe diese Beispiele ausgewählt, weil

  1. Sie stellen Verhalten dar, das in PowerShell wahrscheinlich nicht verbessert werden kann
  2. Ich habe keine Hoffnung, alle ihre Auswirkungen beim Lesen oder Schreiben von PowerShell zuverlässig zu erkennen.

Mir geht es gut. Die überwiegende Mehrheit des überraschenden PowerShell-Verhaltens hat keinen dauerhaften Einfluss auf meinen Erfolg mit PowerShell. Überraschendes Verhalten wird fast immer sofort durch Tests während der Entwicklung erfasst. Ich lerne aus den Dingen, die durchgehen, und nutze sie, um meine Teststrategie zu verbessern. Dies gilt unabhängig davon, ob diese überraschenden Verhaltensweisen beseitigt werden können oder bleiben müssen.

Unabhängig davon, ob die oben genannten Änderungen vorgenommen wurden oder nicht, wird PowerShell niemals so vorhersehbar, dass ich die Testabdeckung erheblich reduzieren kann. Mit anderen Worten, bei der Art und Weise, wie ich PowerShell verwende, glaube ich nicht, dass es einen großen Vorteil gibt, der überhaupt möglich ist, wenn die oben vorgeschlagenen Änderungen vorgenommen werden.

(Übrigens, danke @ mklement0 , dass Sie diese Frage direkt gestellt haben. Das habe ich schon eine Weile im Hinterkopf. Es ist gut zu sehen, dass jeder die Möglichkeit hat, sein Stück zu sagen.)

Danke, @ alx9r.

Ich denke, es ist wichtig, zwischen intrinsischer Komplexität und extrinsischer Komplexität zu unterscheiden:

  • Die intrinsische Komplexität ergibt sich aus der inhärenten Komplexität der implementierten Konzepte, die im Fall von PowerShell zwei Hauptquellen hat: die interne Komplexität durch die Einführung eines neuen Paradigmas (objektbasierte Pipeline) und die Verbindung zweier unterschiedlicher Welten (Shell-Syntax und Programmiersprachen-Syntax) ) und _externe_ Komplexität durch die Schnittstelle mit mehreren, unterschiedlichen Außenwelten.

  • Die extrinsische Komplexität ergibt sich aus undichten Abstraktionen und Inkonsistenzen.

    • Eine solche Komplexität sollte beseitigt werden.
    • Wenn dies aus Gründen der Abwärtskompatibilität keine Option ist, sollte diese Komplexität als bekannte Probleme dokumentiert werden.

    • Das Scoping-Verhalten der Skriptmodulvariablen (auf das Sie im Zusammenhang mit $_ verweisen) ist mehr als nur eine Eigenart: Es ist die Hauptursache für ein Hauptproblem, das zuvor erwähnte # 4568.

    • Alle anderen Probleme, die Sie erwähnen, fallen für mich in die extrinsische Kategorie (anstatt das Ergebnis sorgfältiger Gestaltung zu sein), da sie alle als Inkonsistenzen vorliegen, die keine offensichtlichen (dokumentierten) Gründe oder Vorteile haben:

      • Es ist sinnvoller, mit $null zu splattern, um _no_ Argumente zu übergeben, als ein positionelles $null Argument.
      • Warum sollte [System.Management.Automation.Internal.AutomationNull]::Value während der Parameterbindung in $null konvertiert werden, obwohl der Typ in der direkten Variablenzuweisung beibehalten wird? Siehe https://github.com/PowerShell/PowerShell/issues/9150#issuecomment -473743805
      • Welchen Vorteil hat das dynamische Scoping von break und continue über den Aufrufstapel mit _stillter Beendigung_, wenn keine umschließende Schleife gefunden wird?

Während die Fülle von Merkmalen und das Zusammenfügen unterschiedlicher Welten es schwierig macht, sich an alle erforderlichen intrinsischen Komplexitäten zu erinnern, ist die Minimierung der extrinsischen Komplexität immer noch wichtig.

Es ist ein ernstes Hindernis für die Produktivität (und das Vergnügen), Ihren beabsichtigten Ansatz zuerst testen zu müssen, ohne nur zu wissen und darauf zu vertrauen, dass er funktioniert - oder dass Dinge aufgrund überraschenden Verhaltens unerwartet kaputt gehen (obwohl PowerShell es lobenswerterweise sehr einfach macht, das Verhalten interaktiv zu testen ).

Es kommt auf solide Konzepte (die nicht den intuitiven Erwartungen widersprechen), beschreibende Namen und eine gute Dokumentation an:

Wenn ich es nicht weiß / nicht sicher bin, ob ich mich richtig erinnere, muss ich wissen, wo ich es nachschlagen muss, und darauf vertrauen, dass auch bekannte Probleme und Randfälle dokumentiert sind (entweder als Teil der regulären Hilfethemen oder über Links von Dort).

Selbst wenn wir entscheiden, dass die Beseitigung der extrinsischen Komplexität keine Option ist, können wir sie zumindest systematisch dokumentieren - und die Diskussion hier kann als Ausgangspunkt für die Erstellung einer "Fallstrickgalerie" dienen (die auch Fälle unvermeidbarer innerer Komplexität umfassen kann) kann überraschend sein).

wir können es zumindest systematisch dokumentieren - und die Diskussion hier kann als Ausgangspunkt für die Erstellung einer "Fallstrickgalerie" dienen.

Roman Kuzmin sammelt seit einiger Zeit eine solche Galerie hier: https://github.com/nightroman/PowerShellTraps

Danke, @HumanEquivalentUnit - das sieht nach einer großartigen Sammlung aus.

Zusammen mit den in diesem Thread gesammelten Themen könnte es die Grundlage für eine Galerie bilden, die Teil der offiziellen Dokumentation ist, wobei jeder Eintrag gegebenenfalls ergänzt wird mit:

  • eine Design-Begründung, die erklärt, warum das Verhalten, obwohl es vielleicht überraschend ist, doch gerechtfertigt ist (eine richtig gerahmte Erklärung kann dazu führen, dass das Überraschungselement verschwindet)

  • eine Bestätigung des Problems, aus der hervorgeht, dass:

    • entweder: es wird nicht im Interesse der Abwärtskompatibilität behoben.
    • oder: dass eine zukünftige Änderung in Betracht gezogen wird
    • oder: dass das Problem bereits in PS _Core_ behoben ist

Es ist seltsam, dass gefragt werden muss, ob es Zeit für "PowerShell vZeroTechnicalDebt" ist.

Genau dafür ist ein Versionsbefehl erforderlich.

Wenn in einer neuen Version etwas kaputt geht, ist der einzige Schmerz, den wir bekommen, dass wir die normalerweise kleinen Unterschiede studieren und lernen müssen.

Aber wir bekommen (endlich) eine Plattform, die mit jeder Iteration im Kern wirklich besser wird. Und viel einfacher zu pflegen.

Nein, es ist nie eine Frage, schlechte Designs und Entscheidungen mit neuem Know-how und neuer Technologie in Gang zu setzen.

Um die Lebenden aus einem toten Pferd herauszupeitschen, ist es immer noch erstaunlich schwierig, eine gut erzogene Funktion oder ein Cmdlet zu schreiben, das sich mit den magischen Unterschieden zwischen dem nativen Dateisystem des Hosts und dem Dateisystemanbieter befasst. Solch nuancierter Code ist schwer zu schreiben und wird oft falsch verstanden. Hier ist ein Beitrag über Stackoverflow, den ich vor sieben oder acht Jahren beantwortet habe und der noch gültig ist:

https://stackoverflow.com/questions/8505294/how-do-i-deal-with-paths-when-writing-a-powershell-cmdlet

Ref: # 8495

Es gibt einige seltsame Vorrangregeln für Operatoren, die überarbeitet werden sollten:

PS> 1, 2, 2 + 1, 4, 4 + 1
1
2
2
1
4
4
1

In den meisten Sprachen würde man häufiger erwarten, dass dies die Ausgabe ist:

1
2
3
4
5

Eine Option, die ihre eigenen Vor- und Nachteile hat, ist ein neues Feature-Flag, mit dem das gesamte "ideale" Verhalten aktiviert wird, sodass es aktiviert werden kann. Wenn wir Telemetrie hätten, die anzeigt, dass der größte Teil der Nutzung auf das neue Verhalten umgestellt wurde, könnten wir es umdrehen, damit es nicht mehr verfügbar ist. Dies könnte alles nur ein Wunschtraum sein, da ich keinen realen Fall gesehen habe, in dem ein solches Modell funktioniert ...

In der Tat wäre das schön, aber angesichts der ziemlich ... gründlichen ... Natur einiger dieser Überarbeitungen in diesem Thread besteht die Gefahr, dass die Kompatibilität von Skripten zwischen "normal" und "experimentell" vollständig aufgeteilt wird und möglicherweise in mehrere Teile zerlegt wird. abhängig davon, welche Flags eine Person aktiviert hat.

Dies bedeutet, dass wir uns nicht wirklich auf etwas verlassen können, das auf diese Weise experimentell ist, und auch keine Skripte und Module schreiben können, die auf ihnen basieren, es sei denn, wir fügen den Dokumentenseiten eine große Warnung hinzu oder verhindern möglicherweise, dass sie importiert werden, es sei denn, bestimmte Flags sind aktiviert.

Dies könnte jedoch vermeidbar sein ... wenn wir nach Belieben bestimmte experimentelle Funktionen für jeden Modulbereich aktivieren und deaktivieren können. Angesichts der Tatsache, dass dies die Sache nur noch komplizierter macht, bin ich mir nicht einmal sicher, ob dies auch eine besonders gute Lösung ist.

@ vexx32 nur um klar zu sein, ich schlug kein experimental Flag vor, das irgendwann nicht experimentell werden würde. Ich dachte etwas anderes (vielleicht eher wie Enable-PSFeature da es offiziell unterstützt würde (und somit im Gegensatz zu experimentellen Funktionen vor Änderungen geschützt ist)). Ich dachte auch, es wäre eine einzelne Flagge, bei der Sie sich für diese neuen Änderungen als Set und nicht einzeln entscheiden.

Oh, in diesem Fall ... Ja, absolut. Das würde es uns ermöglichen, alles ordentlich unter einem Dach zusammenzufassen und tatsächlich zu verwenden. Viel besser als ich dachte! 😄

@ jszabo98s Ergänzung zur Liste der hier zusammengestellten Probleme, basierend auf # 8512:

-and und -or unerwartet die gleiche Priorität, wohingegen in den meisten Sprachen (einschließlich C #) -and eine höhere Priorität als -or .

Beispielausdruck, der den Erwartungen widerspricht:

PS> $true -or $true -and $false
False

Aufgrund der linken Assoziativität und der gleichen Priorität von -and und -or wird das oben Gesagte eher als ($true -or $true) -and $false als als das erwartete $true -or ($true -and $false) bewertet

Dies könnte alles nur ein Wunschtraum sein, da ich keinen realen Fall gesehen habe, in dem ein solches Modell funktioniert ...

Tatsächlich haben wir bereits ein Modell, das auf der ganzen Welt funktioniert - LTS. MSFT verwendet dies zur Entwicklung von Windows 10. Das Modell wird zur Entwicklung von Unix-Distributionen verwendet.
Für uns bedeutet dies, dass wir alle zwei Jahre LTS PowerShell Core-Versionen veröffentlichen und diese in Windows 10 LTS-Versionen und Unix LTS-Versionen aufnehmen können. (Ein Problem besteht darin, Windows- und Unix-Veröffentlichungsdaten für LTS-Versionen zu synchronisieren. Ich denke, MSFT kann mit den wichtigsten Unix-Unternehmen verhandeln.)
Während dieser zwei Jahre sammeln wir kleinere Bruchänderungen und übertragen bedeutendere Bruchänderungen auf den nächsten Zyklus.
Für jede neue LTS-Version sollte der ScriptAnalyzer eine Reihe neuer Regeln erhalten, um die Skriptmigration zu erleichtern.
Bei diesem Modell müssen kritische Produkte und Skripte erst nach gründlichen Tests und Migrationen von der vorherigen Version zur nächsten springen.

Ich habe diesen Ansatz verwendet, als ich Schritt für Schritt (Version für Version) ein altes System von der PHP 4-Version auf die nächste PHP-Version migrierte, bis ich die unterstützte PHP 5.x-Version erreichte. Bei jedem Schritt musste ich relativ kleine und schnelle Änderungen vornehmen, wonach das System einige Zeit bis zum nächsten Schritt weiter arbeitete.

Update: Es sollte mit .Net Core LTS-Versionen synchronisiert sein. Ich gehe davon aus, dass .Net Core 3.1 das nächste LTS sein wird und PowerShell Core 6.x in der Version enthalten sein sollte.

Ehrlich? Das klingt nach einer wirklich großartigen Idee für PowerShell Core. Dies würde es uns ermöglichen, solche Änderungen vorzunehmen, die wirklich dazu beitragen könnten, vorwärts zu kommen, ohne sie mit Kompatibilitätsproblemen zu überlasten, während wir sie auch nicht mit zu vielen Änderungen in der Zwischenzeit zwischen LTS-Versionen überlasten.

Ref: https://github.com/PowerShell/PowerShell/pull/8407#issuecomment -453221566

Get-Variable -ValueOnly -Name myVar | Should -Be $var Assertion schlägt fehl, wenn $var ein Array ist.

Dies liegt daran, dass Get-Variable -ValueOnly die Aufzählungsüberladung für WriteObject() .

In Bezug auf mehrere Versionen von Powershell mit unterschiedlichen Funktionen und wichtigen Änderungen: Wir haben dies bereits mit Legacy und Core. Was auf den ersten Blick schlecht erscheint, aber möglicherweise ein funktionierendes Modell für die Zukunft darstellt. Bleib bei mir...

Wir müssen fast alle Prozesse festlegen, die Powershell verwenden, um den Kern pwsh.exe aufzurufen, bevor die eigentlichen Skripte ausgeführt werden, da geplante Windows-Aufgaben, Jenkins und viele Umgebungen den Powershell-Kern nicht kennen. Wir tun dies, weil wir Funktionen verwenden, die nur in einer bestimmten PS-Version verfügbar sind.

In Fällen, in denen wir einen Aufruf des Kerns nicht erzwingen können, müssen wir jedes Skript überprüfen lassen, unter welcher PS-Version es ausgeführt wird, und sich dann mit der entsprechenden PS-Version auf dem Host-System selbst aufrufen. Unabhängig davon, welchen Trick wir verwenden, um den richtigen Code für die Ausführung in der richtigen Umgebung zu erhalten, übergeben wir häufig alle Umgebungen und Parameter an dasselbe Skript, das bereits ausgeführt wurde.

Das ist die UNIX-Philosophie. Lassen Sie ein Werkzeug eine Sache tun und machen Sie es gut. Kombinieren Sie dann Werkzeuge, um ein Ganzes zu erstellen, das größer ist als die Summe seiner Teile. Dies ist die Welt der Skripterstellung, in der wir ständig Subshell-Aufrufe an andere Dienstprogramme durchführen und Ergebnisse verarbeiten. Historisch gesehen ist das Scripting. Powershell tendiert zu einer seltsamen Konvention, indem versucht wird, den gesamten Code nativ zu halten, aber das ist nur eine Konvention - keine Anforderung. PS wird mit Zugriff auf das Betriebssystem und alle verfügbaren Dienstprogramme ausgeführt, genau wie Unix-Shell-Skripte.

Dies wäre viel einfacher, wenn die Dateierweiterung für Core auf .ps6 aktualisiert worden wäre, damit die Powershell-Engine die Arbeit für uns erledigen könnte. Jede binäre Version von Powershell kann unabhängig von den anderen bleiben, solange jeder Aufruf einer Umgebung Umgebungen durchläuft und die Ausgaben, Fehler, Warnungen und Ausnahmen an die andere zurückgibt - was wir jetzt mit großem Aufwand manuell tun müssen. Es ist nicht erforderlich, abwärtskompatible Flags in der Engine zu haben, solange die Engine weiß, welche Version ausgeführt werden soll. Die Kontextumschaltung findet bereits statt, sodass wir uns bereits im schlimmsten Fall befinden.

Wir werden gezwungen sein, für immer schreckliche Hacks in Powershell einzusetzen, es sei denn, wir gehen voran und brechen die Dinge auf eine genau definierte Weise. Durchbrechende Veränderungen werden unser Leben nicht schwieriger machen als sie es bereits sind. Wenn wir alternativ eine inkrementelle, kontinuierliche Verbesserung verwenden und die Engine den Schaltkontext stark aufheben lässt, ist unser Code (und unsere Lebensdauer) besser.

@ jtmoree-kahalamgmt-com Vielen Dank für Ihr Feedback! Sie können gerne neue Ausgaben öffnen, um Ihre Erfahrungen und Ihr Feedback zu teilen und neue hilfreiche Funktionen anzufordern.

Dies wäre viel einfacher, wenn die Dateierweiterung für Core auf .ps6 aktualisiert worden wäre, damit die Powershell-Engine die Arbeit für uns erledigen könnte.

Siehe https://github.com/PowerShell/PowerShell/issues/2013#issuecomment -247987977

Und ich habe https://github.com/PowerShell/PowerShell/issues/9138 basierend auf Ihrem Feedback erstellt.

Python 3 ist sicherlich die Horrorshow, hat es sich schon wirklich durchgesetzt? Ich verwende immer noch 2.7 und plane kein baldiges Upgrade. Aber ich habe in letzter Zeit auch nicht viel über Perl 6 gehört ...

Ich denke, die Lehren, die man aus Python ziehen kann, bestehen darin, wichtige Änderungen an der Sprache von einer Versionsänderung an der Engine zu trennen. Hypothetisch könnte eine PS 7-Engine noch frühere Skriptdateien (.PS1) in einem unveränderlichen Änderungsmodus ausführen, während sie, wenn das Skript als 7-fähig markiert wäre (z. B. mit der Erweiterung .PS7), deklarieren könnte, dass sie aktualisiert wurden Für die Ausführung ist mindestens PS 7 erforderlich. Hoffe das macht Sinn.

Ich finde es zu dramatisch, Python 3 als Horrorshow zu bezeichnen. Wenn ich mir die am häufigsten heruntergeladenen PyPi-Pakete ansehe und die einzelnen Paket-Metadaten zu v2- und v3-Downloads

Das Wichtigste, was Python 3 lange Zeit zurückhielt, war die Unterstützung der wissenschaftlichen Gemeinschaft für Pandas und Pysci. In den neuesten Statistiken bevorzugt die wissenschaftliche Community jetzt Python 3 gegenüber Python 2: https://pypistats.org/packages/pandas 231k v3-Downloads gegenüber 175k v2-Downloads.

Wie der berühmte Dr. W. Edwards Deming sagen würde: "Wir vertrauen auf Gott; alle anderen bringen Daten!" Vielleicht können Sie ein PowerShell-Skript schreiben, um den PyPi-Datensatz zu analysieren und mir zu sagen, wie schrecklich Python 3 Daten verwendet: https://packaging.python.org/guides/analyzing-pypi-package-downloads/

Ich würde mich freuen über (in genau dieser Reihenfolge):

  1. Einfacheres Modulsystem, das gute Stapelspuren erzeugt.

    • Mit der Datei psm1 können beispielsweise beliebige Regeln für das Laden von Funktionen beschrieben werden. Dies führt jedoch zu kryptischen Stapelspuren, bei denen alle Funktionen logisch in die Datei psm1 integriert werden. Dies bedeutet, dass Zeilennummern auf Stapelspuren ungefähr so ​​nützlich sind wie eine Schokoladenteekanne.
  2. Ersetzen Sie die PowerShell-Standardformatierung für Fehlerobjektzeichenfolgen, die 99% der Nützlichkeit der Programmierung in einer stapelbasierten von Neumann-Architektur verschlingt.

    • C # macht das mehr oder weniger richtig. PowerShell ist um die Hälfte zu clever.
  3. Korrigieren Sie die Nullumleitung, sodass die drei verschiedenen Möglichkeiten zum Umleiten von Ausgabestreams auf das Nullgerät eine gleichwertige Leistung aufweisen.

  4. Dynamisches Scoping korrigieren :

function a($f) {& $f}
function main() {
    $f = {write-host 'success'}
    a {& $f} # stack-overflow
    a {& $f}.getnewclosure() # okay
}
[void] (main)
  1. Variablenerfassung korrigieren :
set-strictmode -version 'latest'
$erroractionpreference = 'stop'

function main() {
    $a = 'foo'
    $f = {
        $g = {$a}.getnewclosure()
        & $g # "variable '$a' cannot be retrieved because it has not been set."
    }.getnewclosure()
    & $f
}

main
  1. Ausgabe akkumuliert; return macht nicht dasselbe wie andere Sprachen; repariere es.

  2. PowerShell verfügt nicht über syntaktischen Zucker zum Entsorgen der externen Ressourcen von Objekten

  3. Schreiben Sie PowerShellGet neu. Es ist schrecklich. Funktionen mit Hunderten von Codezeilen, verschluckten Ausnahmen, keine Testabdeckung.

  4. Befreien Sie sich von der Funktionsweise des Modul-Caching.

    • Der Cache ist nicht threadsicher. WTF?
    • Das gesamte Konzept des Zwischenspeicherns eines Moduls für Analysezwecke ist ein Kludge / Hack. Ich stelle fest, dass Microsoft diese Funktion sehr unterstützt, weil PowerShell so verdammt langsam ist, aber siehe meinen nächsten Vorschlag für eine echte Lösung.
    • Die einzige Möglichkeit , Ihren AnalysisCache zu
    • Durch das Zwischenspeichern von Modulen zu Analysezwecken wird die Analyse eng mit dem Laufzeitstatus von Modulen verknüpft.
  5. Stellen Sie "kompilierte Module" bereit, ähnlich wie Py-Dateien zu Pyc-Dateien kompiliert werden, um die Leistung zu verbessern.

  6. Fügen Sie $none Literal hinzu

    • Ersetzen Sie $null $none an vielen Stellen durch
    • Überdenken Sie die Funktionsweise von ParameterSetName und erlauben Sie die Übergabe des Sonderwerts $none an Parameter, damit ich keine verrückten switch-Anweisungen schreiben muss, um Code 5 auf verschiedene Arten aufzurufen. COM und C # dynamic machen das richtig - PowerShell macht dies zu einer Katastrophe. Ein Beispiel wäre, wie ich eine Bereitstellungskonfiguration für SSRS-Berichte im ReportingServicesTools-Modul basierend auf dem Typ des Abonnementvorkommens dynamisch zuordnen muss. Ich würde es vorziehen, nur eine Tüte mit Eigenschaften zu übergeben und die Methode intern mit der Komplexität zu befassen, anstatt den Endbenutzern externe Komplexität aufzuzwingen. ParameterSetName ist nur als Konzept als Vorlage nützlich, nicht zum Programmieren geeignet. Es verwechselt Ad-hoc-Polymorphismus mit Intellisense.

@jzabroski In Bezug auf die Formatierung von ErrorRecord gibt es ein separates Problem, mit dem https://github.com/PowerShell/PowerShell/issues/3647 Da die Formatierung nicht als wichtige Änderung angesehen wird, können wir dort Verbesserungen vornehmen.

Einige Ihrer anderen Anforderungen sind potenziell additiv und nicht fehlerhaft. Daher sollten dies separate Probleme sein. In diesem speziellen Problem werden Anfragen zur Änderung von Änderungen erörtert, wenn wir die Gelegenheit dazu hatten und eine neue Hauptversion von PS rechtfertigen könnten.

@jzabroski In Bezug auf die Formatierung von ErrorRecord gibt es ein separates Problem, mit dem

Warum ist es nicht eine bahnbrechende Veränderung? Weil Entwickler Musterübereinstimmungen für Zeichenfolgen in Fehlermeldungen überhaupt nicht sollten? Ich denke das ist gültig. Aber es wird immer noch nachgelagerte Verbraucher brechen.

Einige Ihrer anderen Anforderungen sind potenziell additiv und nicht fehlerhaft. Daher sollten dies separate Probleme sein.

Welche sind Ihrer Meinung nach potenziell additiv? Ich kann Probleme für sie erstellen, damit wir diese Diskussion nicht entgleisen, aber ich habe diese Liste heute Morgen sorgfältig zusammengestellt. Ich hasse PowerShell mit der Wut und Leidenschaft, Donner zu rollen und Blitze zu explodieren. PowerShell ist eine Bowlingkugel mit einem Fleischermesser. Meine fünf peinlichsten Momente als Ingenieur ereigneten sich alle während der Verwendung von PowerShell. Ich werde diese Zeit nie zurückbekommen.

Ich habe meine Vorschläge aktualisiert, um zu verdeutlichen, warum diese Änderungsvorschläge brechen (und großartig sind).

Ausgabe akkumuliert; return macht nicht dasselbe wie andere Sprachen; repariere es.

return verhält sich innerhalb einer class -Methode so, wie Sie es erwarten. Die Art und Weise, wie sich "Ausgabe" in einer regulären / erweiterten PS-Funktion ansammelt, ist ziemlich typisch für Shell- Scripting-Umgebungen, z. B. Korn Shell und Bash. Kopieren Sie also mehrere Befehle von der Konsole und fügen Sie sie in eine Funktion ein. Wenn Sie diese Funktion aufrufen, wird sie von jedem Befehl genauso ausgegeben, wie Sie diese Befehle über die Konsole ausgeführt haben.

Mein Hauptproblem mit PowerShell ist, dass im Fall der regulären / erweiterten Funktion return niemals Argumente hätte annehmen dürfen. Weil so etwas wie:

return $foo

wird wirklich ausgeführt als:

$foo
return

Dies gibt den Leuten das Gefühl, dass sie die Ausgabe mithilfe von return steuern können und nicht.

return verhält sich innerhalb einer class -Methode so, wie Sie es erwarten. Die Art und Weise, wie sich "Ausgabe" in einer regulären / erweiterten PS-Funktion ansammelt, ist ziemlich typisch für Shell- Scripting-Umgebungen, z. B. Korn Shell und Bash.

Ich höre Leute dies sagen, einschließlich @BrucePay (siehe meine Betonung unten, zitiert ihn), aber das Fazit lautet:

Nur in PowerShell haben wir diese unlogische "Rückkehr bringt nicht zurück" unsinnig und die Ausgabe sammelt sich an. Dies ist ein verherrlichter Speicherverlust, und Sie sollten ihn als solchen betrachten.

Um ehrlich zu sein, suche ich überall in PowerShell In Action nach dem Ausdruck "Probleme" und kann der vZeroTechnicalDebt-Liste etwas hinzufügen. Folgendes schreibt Bruce über die Rückgabeerklärung:

7.3 RÜCKGABE VON FUNKTIONEN
Jetzt ist es Zeit, über die Rückgabe von Werten aus Funktionen zu sprechen. Wir haben das die ganze Zeit gemacht, aber es gibt etwas, das wir hervorheben müssen. Da PowerShell eine Shell ist, gibt es keine Ergebnisse zurück - es schreibt Ausgaben oder gibt Objekte aus. Wie Sie gesehen haben, besteht das Ergebnis eines Ausdrucks oder einer Pipeline darin, das Ergebnisobjekt an den Aufrufer zu senden. Wenn Sie in der Befehlszeile drei durch Semikolons getrennte Ausdrücke eingeben, werden die Ergebnisse aller drei Anweisungen ausgegeben:
[...]
Beim herkömmlichen Ansatz müssen Sie eine Ergebnisvariable, $result , initialisieren, um das erzeugte Array zu halten, jedes Element zum Array hinzufügen und dann das Array ausgeben:

PS (16) > function tradnum
> {
> $result = @()
> $i=1
> while ($i -le 10)
> {
> $result += $i
> $i++
> }
> $result
> }

Dieser Code ist wesentlich komplexer: Sie müssen jetzt zwei Variablen in der Funktion anstelle einer verwalten. Wenn Sie in einer Sprache schreiben, die die Größe des Arrays nicht automatisch erweitert, wäre dies noch komplizierter, da Sie Code hinzufügen müssten, um die Größe des Arrays manuell zu ändern. Obwohl PowerShell die Größe des Arrays automatisch ändert, ist es im Vergleich zur Erfassung der gestreamten Ausgabe nicht effizient. Der Punkt ist, dass Sie darüber nachdenken, wie Sie die von PowerShell angebotenen Funktionen zur Verbesserung nutzen können
dein Code. Wenn Sie Code schreiben, der explizit Arrays erstellt, sollten Sie ihn überprüfen, um festzustellen, ob er neu geschrieben werden kann, um stattdessen das Streaming zu nutzen.

Ich denke, die Motivation hinter dieser Funktion ist gut, aber es gibt viel sauberere und besser lesbare Möglichkeiten, um dasselbe Ziel zu erreichen: Implizite Beförderung von einem einzelnen Objekt zu einer Sammlung von Objekten. Darüber hinaus bietet PowerShell bereits eine einfache Möglichkeit, die Ausgabe zur Umleitung zurückzugeben: Write-Output .

In Bash beendet return eine Funktion, Punkt.

Huh? Bash sammelt trotzdem Output:

hillr@Keith-Dell8500:~$ function foo() {
> echo "Hello"
> ls ~
> date
> return
> echo "World"
> }
hillr@Keith-Dell8500:~$ foo
Hello
bar.ps1  date.txt   test.ps1
baz.ps1  dotnet    powershell-preview_6.2.0-rc.1-1.ubuntu.16.04_amd64.deb
Tue Mar 26 16:06:18 DST 2019

Genau wie bei PowerShell gibt Bash von jedem Befehl bis zur Anweisung return alles aus.

Ah, ich denke, Sie beziehen sich auf das, was in $? . Ja, das ist ein Unterschied. Ich denke, das müssen int Rückgabewerte in Bash sein, um Erfolg / Misserfolg anzuzeigen. In PS gibt $? Erfolg / Misserfolg als Bool an, basierend auf von der Funktion generierten Fehlern. In der Praxis denke ich nicht, dass $? nicht so oft verwendet wird. Ich verwende stattdessen die Ausnahmebehandlung über try/catch/finally .

Ja. return hat in diesen Sprachen nur einen Zweck. In PowerShell wird es mit der Ausgabe gemischt. Das Mischen von Rückgabewerten und Ausgabestreams ist eine schlechte Idee. Dies kann auch zu Speicherverlust-ähnlichen Leistungsproblemen führen. Was Sie wirklich wollen, sind Co-Routinen oder "Yield Return" oder Generatoren, Generatorbauer und Scanner (wie in Icon). Der Grund dafür ist, dass der Eingangsverbrauch träge ist und ein Fehler die Berechnung unterbricht, während der bisher erzeugte Teil der Berechnung entsorgt werden kann.

Sie können sich "Ausgabeumleitung" als zwei Objekte vorstellen: einen Prozessor und einen Prozessorkontext.

Bearbeiten: Ich verstehe, warum Sie meinen ursprünglichen Punkt widerlegt haben. Sie dachten, ich sage, es ist schlecht, Output liefern zu können. Ich sage stattdessen, dass es schlecht ist, die Ausgabe so zurückzugeben, wie PowerShell es tut.

Ich verwende stattdessen die Ausnahmebehandlung über try/catch/finally .

Das ist viel Tippen und drückt nicht in allen Fällen klar die Absicht aus.

Nun, PowerShell basiert auf .NET, bei dem es sich um Müll handelt, sodass keine Speicherlecks auftreten sollten. Das heißt aber nicht, dass Sie keinen Speicherhort haben können. Sie müssen also etwas vorsichtig sein, wenn Sie große Ausgaben / Sammlungen verarbeiten, die einer Variablen zugewiesen oder in eine Hashtabelle eingefügt werden.

Ich denke, PowerShells return -Anweisung sollte nur einen einzigen Zweck haben und das heißt, früh zurückzukehren - sonst nichts. Wenn jemand return 42 , hat dies keinen Einfluss auf $? . Es ist nur eine weitere Elementausgabe (nachgegeben) an den Ausgabestream.

Wie bereits erwähnt, wird $? von PowerShell verwaltet und hat nichts damit zu tun, was eine Funktion ausgibt / zurückgibt. $? wird basierend auf generierten Fehlern (oder deren Fehlen) festgelegt. Dies bedeutet, dass bei der Ausführung von $res = foo - $ res jedes von der Funktion foo ausgegebene Objekt enthält. Wenn Sie wissen möchten, ob die Funktion "fehlgeschlagen" ist, können Sie $? bei jedem einzelnen Befehl überprüfen, den Sie ausführen, ODER Sie können eine Reihe von Befehlen in einen try/catch -Block einschließen. Ich finde das erstere viel weniger tippen (in Skripten).

Hören Sie, wie Leute dies sagen, einschließlich @BrucePay (siehe Hervorhebung von mir unten, zitiert ihn), aber das Fazit lautet:
In Korn Shell beendet return eine Funktion, Punkt.
In Bash beendet return eine Funktion, Punkt.

In PowerShell beendet return auch eine Funktion:

PS C:\> function test { "hello"; return "!"; "world"}
PS C:\> test
hello
!

Das Mischen von Rückgabewerten und Ausgabestreams ist eine schlechte Idee. Dies kann auch zu Speicherverlust-ähnlichen Leistungsproblemen führen

Es wird nicht gemischt, da in PowerShell kein Unterschied zwischen dem Ausgabestream und dem Rückgabewert besteht. Sie sprechen so, als ob die Funktion die Zeichenfolgen in stdout schreibt und dem Aufrufer separat ein Ausrufezeichen zurückgibt, dies ist jedoch nicht der Fall. Auf write-output scheint der gleiche Fehler zu sein. All dies: write-output 'x' , 'x' , return 'x' senden Sie etwas über denselben Ausgabepfad an die Pipeline. Es gibt keinen separaten Rückgabewert.

Was Sie wirklich wollen, sind Co-Routinen oder "Yield Return" oder Generatoren, Generatorbauer und Scanner (wie in Icon). T.

Das würde bedeuten, dass sich ein Befehl, der in die Befehlszeile geschrieben und dann in ein Skript oder eine Funktion eingefügt wird, anders verhält:

PS C:\> robocopy /whatever
PS C:\> "robocopy /whatever" | set-content test.ps1; .\test.ps1
PS C:\> function test { robocopy /whatever }

Ich mag es, in allen drei Fällen die gleiche Ausgabe zu sehen, die Ausgabe in zwei Fällen nicht verschluckt zu haben, weil ich nicht ohne Grund yield return . Die Art und Weise, wie PowerShell dies tut, ist konsistent und praktisch für eine Shell und das Schreiben von Shell- / Batch-Skripten. Nehmen Sie etwas, das Sie in die Befehlszeile geschrieben haben, und platzieren Sie es an einem Ort, an dem Sie es immer wieder aufrufen können. Dadurch sollte sich das Verhalten des Codes nicht vollständig ändern.

Der Grund dafür ist, dass der Eingangsverbrauch träge ist und ein Fehler die Berechnung unterbricht, während der bisher erzeugte Teil der Berechnung entsorgt werden kann.

Die PowerShell-Pipeline wird von der Laufzeit gesteuert. Wenn ich verstehe, was Sie sagen, ist dies bereits möglich:

PS D:\> 1..1mb |foreach { write-verbose -Verbose "incoming number: $_"; $_ } |select -first 3
VERBOSE: incoming number: 1
1
VERBOSE: incoming number: 2
2
VERBOSE: incoming number: 3
3

Das select beendet die Pipeline, sobald es drei Dinge enthält. Der Rest der Millionenzahlen wurde nicht in foreach eingespeist. Informationen, die sich in der Pipeline bewegen, sind ein "Push" -Modell, werden jedoch von der PowerShell-Engine gesteuert.

Obwohl es sich um eine Shell handelt, ist nicht klar, was dies für "Eingabefehler beim Anhalten der Berechnung" bedeuten würde, wenn die Eingabe von einem nativen Befehl oder etwas außerhalb eines PS-Cmdlets stammt.

Stellen Sie "kompilierte Module" bereit, ähnlich wie Py-Dateien zu Pyc-Dateien kompiliert werden, um die Leistung zu verbessern.

Ich denke, die beabsichtigte Lösung für mehr Leistung besteht darin, Module in C # zu schreiben. PowerShell-Code wird in einigen Situationen zwar JIT-kompiliert, aber PS-Teammitglieder haben bereits gesagt, dass sie nicht vorhaben, dies Endbenutzern zur Anpassung zur Verfügung zu stellen, z. B. IIRC Dongbo Wangs PS Conf Asia-Vortrag über die PS Engine-Interna im November 2018. (Ich denke das könnte sich ändern).

Korrigieren Sie die Nullumleitung, sodass die drei verschiedenen Möglichkeiten zum Umleiten von Ausgabestreams auf das Nullgerät eine gleichwertige Leistung aufweisen.

Wünschenswert, aber es scheint unwahrscheinlich; $null = 4 ist eine einfache Variablenbindung. 4 | out-null benötigt den Aufwand, eine Pipeline zu starten und die Befehlsauflösung durchzuführen - was wäre, wenn jemand absichtlich out-null einem Proxy-Wrapper gemacht hätte, der die Protokollierung hinzugefügt hat Code? Ist diese technische Verschuldung, dass die Anforderung einer Pipeline und eines Cmdlets langsamer ist als ein Ausdruck?

Dynamisches Scoping korrigieren:

Wenn Sie "kein dynamisches Scoping verwenden" meinen, war dies eine bewusste Entscheidung, z. B. Bruce Payette, der hier sagte: "Dynamisches Scoping wird fast nie verwendet. Früher, wie vor 30 Jahren, hatte LISP dynamisches Scoping, aber es wird sehr, sehr selten verwendet." Der Grund, warum wir es verwenden, ist: Das verwenden Shells. Shells verwenden das Äquivalent von dynamischem Scoping, sogar Bash, und die Unix-Shells verwenden das Äquivalent von dynamischem Scoping, wobei die Variablen aus dem Kontext des Aufrufers stammen - in ihrem Fall Die Variablen aus dem Kontext des Aufrufers werden in den untergeordneten Kontext kopiert. [..] Mit einer Änderung, normalerweise im dynamischen Bereich, suchen Sie die Aufrufkette nach und legen die Variable dort fest, wo sie existiert. Wir tun das nicht, wir setzen die Variable im aktuellen Bereich immer wieder und das emuliert wieder das Verhalten von Muscheln ".

Das mag ärgerlich sein, aber ist das "technische Verschuldung" für eine Shell und wäre "zeroTechnicalDebt", wenn es geändert würde?

Nun, PowerShell basiert auf .NET, bei dem es sich um Müll handelt, sodass keine Speicherlecks auftreten sollten. Das heißt aber nicht, dass Sie keinen Speicherhort haben können. Sie müssen also etwas vorsichtig sein, wenn Sie große Ausgaben / Sammlungen verarbeiten, die einer Variablen zugewiesen oder in eine Hashtabelle eingefügt werden.

Ich hatte einen Systemadministrator, der kein Ingenieur ist, der eine Logik schrieb, um zu versuchen, Metadaten für alle Dateien auf einer 8-TB-Dateifreigabe zu tabellieren. Das endete nicht gut: Es hat viel Speicherplatz verbraucht und das System auf 100% CPU eingestellt ... wir konnten uns nach dem Start des Skripts nicht einmal bei der Box anmelden und die einzige Lösung in der Produktion, um den Server zu retten war zu hart, es neu zu starten.

Nach meiner Erfahrung macht es PowerShell einfach, solchen Müll zu schreiben. Sie können mit meinem Feedback umgehen und es kritisieren, wie Sie möchten. Es ändert nichts an der Tatsache, dass PowerShell das Schreiben von Skripten erleichtert, mit denen Produktionsmaschinen effektiv zum Absturz gebracht werden können.

@jzabroski Kannst du irgendwelche Details des Skripts teilen?

Powershell-Benutzer versuchen, das Pipeline-Streaming ( get-childitem | foreach-object {} ) zu fördern, anstatt ein Dataset ( $files = get-childitem; $files | foreach-object ) absichtlich vorzuladen, um die Speichernutzung zu reduzieren. Hat es das im Voraus geladen?

Gab es eine Verwendung von Group-Object , um ähnliche Dateien zu sammeln? In letzter Zeit wurde die

PowerShell ist standardmäßig Single-Core. Gab es dort Jobs / Runspaces-Code, war es ein Single-Core-Server? PS 6.1 verfügt über Start-ThreadJob, das mehrere Jobs mit viel weniger Overhead und Drosselung ermöglicht, um die CPU

Nach meiner Erfahrung macht es PowerShell einfach, solchen Müll zu schreiben

Alle Tutorials und Bücher, in denen Sie aufgefordert werden, $files = @(); $files += $f zu schreiben, müssen die Welt ein kleines Vermögen an CPU-Zyklen und Speicher gekostet haben. Das ist ein Muster, das langsam, teuer für Prozessor und Speicher und äußerst häufig ist. Ich bin gespannt, ob dieses Muster überhaupt im Skript enthalten war. (Und wenn es eine Möglichkeit gibt, könnten wir es blockieren, ohne die Abwärtskompatibilität zu beeinträchtigen, oder + = in Arrays bei zukünftigen Änderungen ungültig machen?).

Aber hier gibt es einen Kompromiss. Get-ChildItem -Recurse besteht aus 22 Zeichen und verbraucht 800 + MB RAM nur auf meinem C: -Laufwerk. Das C #, um dies zu tun, ohne Tonnen von Speicher zu verwenden, besteht aus mehr als 50 Zeilen und erhält überhaupt keine Dateimetadaten eher wie 80MB. Das ist kein PS, der Speicher verliert, sondern PS, der ihn verwendet, um die Benutzerfreundlichkeit zu erhöhen.

Gibt es eine Sprache, in der Sie sich nicht um die Funktionsweise kümmern müssen, nützlichen Code schreiben können, keinen schlechten Code schreiben können und kein erfahrener Programmierer sein müssen? (Und welches ist auch eine Muschel?)

Hätte eine Ihrer zuvor vorgeschlagenen Änderungen dazu geführt, dass das Skript funktioniert?

Sie können ein Bash-Skript schreiben, um Dateien aufzulisten und für jeden einen Prozess zu erzeugen, bis Ihr Server umfällt und Sie nicht einmal SSH darin ausführen können. Sie können ein Python-Skript schreiben, das os.walk() der Dateibaum ist und os.stat() für jede Datei aufruft, weniger Speicher benötigt und schneller fertig wird - aber 10 Zeilen anstelle von 1 benötigt und Sie sich immer noch darum kümmern müssen Betriebssystem und Pflege der Codedetails (und es ist immer noch keine Shell und funktioniert nicht mit PS-Anbietern).

Ich möchte, dass PS mehr "Erfolgsgruben" und weniger Stolperfallen hat. Die schnelle Auflistung von Dateinamen ist eine davon, für die ich viel Verwendung sehe. Es radikal zu ändern, um es zu einer völlig anderen Sprache zu machen, und die Bereiche zu humpeln, die es gut macht, wird das nicht tun.

Sie möchten Python, Python existiert, es ist eine schöne Sprache, es wird nicht durch den Versuch behindert, in zwei verschiedene Welten zu passen und den Umfang und die Funktionsrückgabesemantik einer 30 Jahre alten Shell von einem anderen Betriebssystem (warum, Microsoft) oder durch das Engagement von Microsoft aufrechtzuerhalten auf Abwärtskompatibilität (und Besessenheit mit .Net), so dass es all diesen Fragen ausweichen kann, anstatt sich ihnen zu stellen.

Ich möchte, dass PS mehr "Erfolgsgruben" und weniger Stolperfallen hat.

Wenn ich allein dafür zwanzig Daumen hoch addieren könnte, würde ich. Dies ist genau das Muster und der Ansatz, den PowerShell verfolgen muss.

For-EachObject ist eine PowerShell-Funktion, mit der PowerShell-Sammlungen in unlesbare Stapelspuren konvertiert werden können.

Heute habe ich ein von Amazon geschriebenes Skript verwendet, um EC2-Windows-Festplatten aufzulisten: https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-volumes.html#windows -list-disks

Erraten Sie, was? Ich hatte kein Initialize-AWSDefaults Setup auf diesem PC und da der Skriptautor ForEach-Object verwendet hat, sah mein Stack-Trace wie folgt aus: _garbage_:

PS C:\Windows\system32> D:\Installs\PowerShell\List-EC2Disks.ps1
Could not access the AWS API, therefore, VolumeId is not available. 
Verify that you provided your access keys.
ForEach-Object : You cannot call a method on a null-valued expression.
At D:\Installs\PowerShell\List-EC2Disks.ps1:39 char:12
+ Get-disk | ForEach-Object {
+            ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [ForEach-Object], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull,Microsoft.PowerShell.Commands.ForEachObjectCommand

Dies geschieht jedes Mal, wenn Benutzer ForEach-Object-Ausdrücke in ihrem Code verwenden. Die Stapelspuren sind immer schrecklich. Das neu zu schreiben ist schmerzhaft. Zum Glück ist es nur ein Skript, das ich kopiere, in eine zufällige Datei einfüge, speichere und ausführe. Wenn es ein Problem in einem großen Modul ist, muss ich den Quellcode für das Modul abrufen, das Skript neu schreiben und hoffen, dass Gott es überarbeitet hat. Ich habe nichts im gesamten Modul durch Konvertieren des ForEach-Object-Ausdrucks UND der Hoffnung gebrochen Ich kann herausfinden, wo der REAL-Fehler liegt, nur damit ich meinen Job machen kann. Und jetzt habe ich einen benutzerdefinierten Code, den ich aus einem großen Repository gegabelt habe, um herauszufinden, warum ich einen Fehler erhalte, weil PowerShells Write-Error im Vergleich zu C # einfacher Redewendung von throw new Exception("message", ex) schrecklich ist.

Wenn Sie dies neu schreiben, um ein for ($var in $list) und die Ergebnisse in einer Variablen $results akkumulieren, wird der folgende Fehler angezeigt:

PS C:\Windows\system32> D:\Installs\PowerShell\List-EC2Disks.ps1
Could not access the AWS API, therefore, VolumeId is not available. 
Verify that you provided your access keys.
You cannot call a method on a null-valued expression.
At D:\Installs\PowerShell\List-EC2Disks.ps1:58 char:26
+ ... lDevice = If ($VirtualDeviceMap.ContainsKey($BlockDeviceName)) { $Vir ...
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Übrigens, jedes Mal, wenn ich dies tun muss, kann ich mich nicht an die dummen Regeln von PowerShell erinnern, mit denen Elemente zu Listen hinzugefügt werden. Daher muss ich Google https://www.google.com/search?q=powershell+append + zu + Liste und lesen Sie einen Blog-Beitrag über jemanden, der erklärt, wie nicht intuitiv die Listenoperationen von PowerShell sind.

Wenn Sie C # oder eine Sprache, die dies gut kann, nicht kennen, können Sie leicht argumentieren, dass dieses Verhalten in Ordnung ist. C # behandelt dieses Problem jedoch intelligent, indem es die Ausnahme in eine AggregateException einschließt, sodass Sie sowohl die innere als auch die äußere Ausnahme erhalten. Power Shell? Hahahaha. Ja, das wäre zu nützlich.

@jzabroski Kannst du irgendwelche Details des Skripts teilen?

Leider ( und glücklich ) erinnere ich mich nicht daran. Es war ein Fileshare, also waren es mit ziemlicher Sicherheit höchstens ein oder zwei Kerne. Wenn es sich um zwei Kerne handelte, wurde die verbleibende CPU wahrscheinlich von Windows Defender übernommen.

Bearbeiten: Gefunden im Team-Chat.

$big32 = Get-ChildItem D:\Data\Website\Data -recurse | Sort-Object length -descending | select-object -first 32 | measure-object -property length –sum

Als zusätzlichen Bonus habe ich gerade mit der Person gesprochen, die diesen Befehl ausgeführt hat (und sich unglaublich schlecht gefühlt hat), und er sagte, der Anwendungsfall bestehe darin, "die 32 größten Dateien für die anfängliche Größenanforderung der Replikationsgruppe für DFS abzurufen".

Es wird nicht gemischt, da in PowerShell kein Unterschied zwischen dem Ausgabestream und dem Rückgabewert besteht.

Ich habe noch nicht gesehen, dass Leute dies beim ersten Versuch richtig verwenden. Auch dies ist nicht das, was Bash oder eine andere Shell macht. Während es ein interessantes Experiment war, die beiden Konzepte zu vereinheitlichen, war es vom Standpunkt der Lesbarkeit aus eine vollständige und völlige Katastrophe. Es hilft nicht, dass Write-Output in PowerShell v6 16 Monate lang nicht funktioniert hat.

@jzabroski Aus Ihrer Ausgabe von For-EachObject geht hervor, dass Sie Powershell Core nicht verwenden (dem ist dieses Repository gewidmet). Könnten Sie bitte Powershell Core ausprobieren und prüfen, ob Sie es reproduzieren können. Stellen Sie sicher, dass Sie die neueste Version verwenden. Beachten Sie, dass Windows-spezifische Funktionen (z. B. Get-Disk) nicht Teil von Powershell Core sind. Sie müssen dies bei Ihren Tests berücksichtigen.

Ich habe noch nicht gesehen, dass Leute dies beim ersten Versuch richtig verwenden. Auch dies ist nicht das, was Bash oder eine andere Shell macht.

$ test () { ls /tmp; ls /etc/pm; return 5; ls /v*; } ; x=$(test)
$ echo "$x"
tmux-1000
sleep.d
$ echo $?
0

Dies ist sowohl die Ausgabe von zwei separaten Befehlen, die sich in einer Bash-Funktion ansammeln, als auch die Bash-Rückgabe, die in C # nicht als Rückgabefunktionen fungiert. Was genau ist "nicht das, was Bash tut"?

Sie erfassen den Rückgabewert für das Bash-Beispiel nicht korrekt. Die Rendite geht verloren, weil die $? ist immer der letzte Befehl. in deinem Fall 'Echo'.

$ test () { ls /tmp; ls /etc/pm; return 5; ls /v*; } ; x=$(test)
$ echo $?
5
$ echo $x
tmux-1000
sleep.d

POWERSHELL macht das anders

> function test() { ls; return 5 ; ls } ; $x=test
> echo $?
True
> echo $x
    Directory: c:\foo\bar

Mode                LastWriteTime         Length Name
----                -------------         ------ ----

Weitere PowerShell-Kuriositäten:

Chocolatey fügt eine RefreshEnv.cmd hinzu, die ein GODSEND ist. Warum wird dies nicht einfach mit PowerShell geliefert? Warum muss ich meine Shell neu starten oder ein dummes Skript aus dem Internet herunterladen, um meine $ env zurückzusetzen?

@jzabroski Dies wurde in https://github.com/PowerShell/PowerShell-RFC/pull/92 erwähnt. Vielleicht möchten Sie sich dort einschalten .

Erstellen Sie ein Standardobjektmodell für PowerShell-Anbieter: https://github.com/PowerShell/SHiPS/issues/66#issuecomment -368924485

In dem Link zu SHiPS Ausgabe 66 skizziere ich mögliche Kandidaten-Cmdlets. Mir ist nicht klar, warum wir für diese Kern-Cmdlets kein Verhalten der Haskell-Typklasse implementieren können.

Diese APIs sind bereits in PowerShell enthalten.

@iSazonov Können Sie bitte bearbeiten und zitieren, worauf Sie antworten, und einen Kontext hinzufügen, z. B. einen Hyperlink zur Dokumentation dieser APIs? TYVM

@jzabroski Dateien im Ordner srcSystem.Management.Automationnamespaces suchen.

POWERSHELL macht das anders

Es ist bash , das es anders macht - return kann nur den (ganzzahligen) Prozess-Exit-Code festlegen (das bedeutet nicht "return" in anderen Programmiersprachen, das ist ein exit ). .

PowerShell kann das auch mit exit 5

Es ist nur so, dass wir in PowerShell nicht sehr oft Exit-Codes verwenden (so ziemlich nur für geplante Aufgaben und Interop mit anderen Betriebssystemen), da es sich nicht um eine prozessbasierte Shell handelt und Funktionen nicht beendet werden sollten.

Letztendlich ist es der gleiche Grund, warum das Erkennen des stdout-Handle-Typs in PowerShell nicht nützlich ist (und warum das "Umleiten" nach out-null nicht dasselbe ist wie das Umwandeln in [void] oder das Zuweisen zu $null )

Ich empfehle Leuten, neue Probleme einzureichen, wenn sie tatsächlich Feedback haben, auf das sie reagieren möchten - da das Team eine nicht abwärtskompatible Version von PowerShell eindeutig und eindeutig ausgeschlossen hat, weiß ich nicht, warum dieser Thread einfach weitergeht ...

da das Team eine nicht abwärtskompatible Version von klar und eindeutig ausgeschlossen hat

Das sind Neuigkeiten für mich. Wie ist das klar? Bitte geben Sie Links zu Beiträgen oder anderen Dokumentationen an.

Es ist ein bisschen frustrierend für einige von uns zu hören, "wir werden niemals die Kompatibilität brechen", während wir jeden Tag mit einem Bruch ringen. Der Sinn dieses Threads ist, dass der freie Markt der Ideen einige dieser Probleme lösen kann, wenn dies nicht der Fall ist.

Jemand könnte es vorteilhaft genug finden, Powershell zu gabeln und eine Version mit minimalem technischen Aufwand zu erstellen. Diese Gruppe wird von den in diesem Thread vorgestellten Ideen profitieren. (So ​​funktioniert die Welt jetzt. Möge die beste Powershell gewinnen.)

Ich werde wiederholen, dass das Team bereits eine "nicht rückwärtskompatible" Version von Powershell erstellt hat, indem der Befehl von Powershell in Pwsh umbenannt wurde. Power (SHELL) ist eine Shell. Die Aufgabe einer Hülle ist es, der Klebstoff für den Menschen zu sein, der digitale Systeme miteinander verbindet. Es ist keine kompilierte Binärdatei mit minimalen externen Abhängigkeiten. Selbst traditionelle Programmiersprachen planen und nehmen wichtige Änderungen vor.

POWERSHELL macht das anders

Es ist bash , das es anders macht - return kann nur den (ganzzahligen) Prozess-Exit-Code festlegen (das ist nicht der Fall)

Ich bin neugierig auf andere Muscheln. Was machen Sie? korn, csh usw.

In diesem Artikel wird die return-Anweisung in mehreren Sprachen erläutert :

Es wird darauf hingewiesen, dass das Betriebssystem [Shells] die Rückgabe mehrerer Dinge ermöglicht: Rückkehrcode und Ausgabe.

Mein Team verfügt über eine Vielzahl von Skripten, die nur in PowerShell 5 ausgeführt werden, obwohl wir PowerShell 6 so oft wie möglich verwenden. Nach meiner Erfahrung ist die Annahme, dass PowerShell vollständig abwärtskompatibel ist, definitiv falsch. Es gibt zumindest einige extreme Fälle (z. B. ErrorActionPreference nicht intuitiv verhalten), die definitiv als brechende Änderung behandelt werden sollten - Fälle, in denen die Korrektur weniger "brechen" würde, als dies nicht zu tun.

@chriskuech Gibt es ein Problem, das Ihr Problem mit ErrorActionPreference detailliert beschreibt?

@ SteveL-MSFT Ich glaube, das Mosaik, auf das @KirkMunro direkt unter den Kommentaren von

Allerdings hat @iSazonov die ursprüngliche Ausgabe von https://github.com/PowerShell/PowerShell/issues/7774

Es scheint, dass dieses Zeug in verschiedenen Formen immer wieder auftaucht und der Ausschuss immer wieder Probleme damit schließt.

@jzabroski hat mein Hauptproblem gefunden, das auf die Grundursache

Ich habe in der Vergangenheit auch ein Problem mit einem der Symptome eingereicht: Invoke-WebRequest , das einen Beendigungsfehler auslöst. Ich habe persönlich gesehen, wie mehrere Personen völlig verblüfft über das gesamte Boilerplate try / catch für die Behandlung fehlgeschlagener HTTP-Anforderungen waren, was auftritt, weil die internen .NET-Methoden Beendigungsfehler auslösen. In jedem der drei verschiedenen Fälle antwortete der Ingenieur mit einer Erklärung, als ich das zugrunde liegende Verhalten erklärte und erklärte, warum das Problem angeblich niemals behoben werden würde.

Zusammenfassend lässt sich sagen, dass durch das Beenden von Fehlern das Skript beendet wird, da PowerShell-Ersteller der Ansicht sind, dass das Skript nicht logisch über den Fehler hinausgehen kann. Ich denke jedoch, dass dies buchstäblich nie jemand anderes ist als die Entscheidung des Skripters, von Fall zu Fall zu entscheiden. Nur der Scripter kann entscheiden, ob das Skript Stop , SilentlyContinue , Continue usw. sein soll.

(Tangential zum obigen Problem)

Wenn PowerShell einen opt-in "ZeroTechDebt" -Modus implementiert, denke ich definitiv, dass $ErrorActionPreference = "Stop" standardmäßig festgelegt werden sollte. Offensichtlich ist diese Einstellung in einer REPL nicht sinnvoll und sollte daher nicht standardmäßig für alle Szenarien festgelegt werden, aber buchstäblich allen meinen Skripten wird $ErrorActionPreference = "Stop" vorangestellt, um "defensive Programmierung" zu aktivieren und sich wie "normal" zu verhalten " Programmiersprache.

@chriskuech Wenn Sie dies noch nicht werfen Sie bitte einen Blick auf diese Sammlung von RFCs: https://github.com/PowerShell/PowerShell-RFC/pull/187. Sie sprechen direkt mit dem, worüber Sie hier sprechen, ohne eine neue Zero-Tech-Schuldenversion von PowerShell zu benötigen.

Sie können die vier RFCs auch in separaten Ausgaben auf der Seite Probleme in diesem Repo finden, wenn dies das Lesen / Verdauen erleichtert. Suchen Sie einfach nach offenen Ausgaben, die von mir gepostet wurden, und Sie werden sie finden

@ SteveL-MSFT Hier ist ein ähnliches Problem, das meine Produktivität beeinträchtigt. Es ist nicht $ErrorActionPreference sondern $ConfirmPreference :

Unten finden Sie ein hässliches Skript, das ich zum Festlegen von SQL Server-Datenträgern auf 64 KB geschrieben habe.

Import-Module Storage;

function Format-Drives
{
    # See https://stackoverflow.com/a/42621174/1040437 (Formatting a disk using PowerShell without prompting for confirmation)
    $currentconfirm = $ConfirmPreference
    $ConfirmPreference = 'none'

    Get-Disk | Where isOffline | Set-Disk -isOffline $false
    # The next line of this script is (almost) copy-pasted verbatim from: https://blogs.technet.microsoft.com/heyscriptingguy/2013/05/29/use-powershell-to-initialize-raw-disks-and-to-partition-and-format-volumes/
    Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -Confirm:$false -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize -IsActive | Format-Volume -FileSystem NTFS -AllocationUnitSize 64kb -Confirm:$false

    # See https://stackoverflow.com/a/42621174/1040437 (Formatting a disk using PowerShell without prompting for confirmation)
    $ConfirmPreference = $currentconfirm
}

Format-Drives

Einige Nebenpunkte:

  1. Die Dokumentation für Format-Volume will mehr. Nur zwei Beispiele? Die offizielle Dokumentation stimmt nicht mit der Website überein :
  2. Warum muss ich zu StackOverflow gehen, um zu lernen, wie man eine GUI für eine Skriptsprache vermeidet?
  3. Die Tatsache, dass dies so fehleranfällig / dumm ist, "ohne nachzudenken" zu schreiben, unterstreicht nur verwandte Themen wie https://github.com/PowerShell/PowerShell-RFC/issues/198 - es ist ein weiteres Beispiel dafür, wie Bruce Payette verspricht " PowerShell In Action ", dass Sie nur das eingeben, was Sie für richtig halten und es funktioniert ... ist völlig falsch.
  4. Siehe auch das Problem von @ mklement0 : https://github.com/PowerShell/PowerShell/issues/4568

Benötigt -Version kann keine maximale Version angeben

Siehe: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-6

Dies ist ärgerlich, wenn Sie erweiterte Funktionen schreiben, mit denen .NET Framework-Bibliotheken geladen werden, bei denen sich die API zwischen .NET Framework und .NET Core vollständig unterscheidet, z. B. wie die AccessControl-API funktioniert.

@jzabroski Sie können die Edition jedoch angeben, um Folgendes zu trennen:

#requires -PSEdition Desktop
# versus
#requires -PSEdition Core

Nur eine kurze Anmerkung, dass gestartet hat, wie wichtige Änderungen implementiert und verwaltet werden können: # 13129.

Außerdem sind # 6817 und # 10967 weitere Verhaltensweisen, die es wert sind, erneut betrachtet zu werden, sobald wichtige Änderungen zulässig sind.
(Sie haben dieselbe Grundursache, die unter https://github.com/PowerShell/PowerShell/issues/10967#issuecomment-561843650 erläutert wird.)

Die Tatsache, dass , stärker als + ist, ist logisch, da es bei PowerShell mehr um Listen als um Zahlen geht. MEINER BESCHEIDENEN MEINUNG NACH.

@rjmholt hat offiziell eine Diskussion gestartet

Ich sollte sagen, es ist nicht offizieller als jede andere Diskussion

Ich würde gerne die Bearbeitungszeit für Importe und Funktionssignaturen streng überprüfen.
Denken Sie darüber nach, neue Importsemantiken einzuführen, wie sie EcmaScript-Module bieten?
Keine globale Namespace-Verschmutzung mehr. Langsame Importmechanik.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen