{"id":427,"date":"2021-04-24T08:00:00","date_gmt":"2021-04-24T06:00:00","guid":{"rendered":"https:\/\/pascal-korz.de\/blog\/?p=427"},"modified":"2021-04-17T16:27:54","modified_gmt":"2021-04-17T14:27:54","slug":"powershell-fallen-1-die-schwarze-null-oder-ueber-den-strict-mode","status":"publish","type":"post","link":"https:\/\/pascal-korz.de\/blog\/2021\/04\/24\/powershell-fallen-1-die-schwarze-null-oder-ueber-den-strict-mode\/","title":{"rendered":"PowerShell-Fallen #1: Die schwarze $null oder \u00fcber den Strict Mode"},"content":{"rendered":"\n<p>Wer PowerShell lernt, stolpert h\u00e4ufig \u00fcber Eigenarten der Sprache, die sich von jenen anderer bekannter Sprachen unterscheiden und darum zun\u00e4chst \u00fcberraschend sind. Hier m\u00f6chte ich ein paar von ihnen hervorheben und erl\u00e4utern, wie das oft eigentlich gew\u00fcnschte Ergebnis erzielt werden kann.<\/p>\n\n\n\n<p>Los geht&#8217;s mit dem Standardverhalten von PowerShell, wenn der Interpreter auf eine nicht deklarierte Variable st\u00f6\u00dft: Er l\u00f6st sie einfach als <code>$null<\/code> auf!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$undeclared_variable -eq $null\n\nOutput:\nTrue<\/code><\/pre>\n\n\n\n<p>Das kann in vielen Situationen praktisch sein, aber auch zu schwierig zu erkennenden Fehlern f\u00fchren, wenn der Variablenname versehentlich falsch geschrieben wurde: Dann gibt eine <code>if<\/code>-Anweisung pl\u00f6tzlich <code>$false<\/code> zur\u00fcck, weil mit <code>$null<\/code> anstatt mit dem Wert der richtigen Variable verglichen wird, und das Programm arbeitet ohne Warnung oder Fehlermeldung einfach weiter.<\/p>\n\n\n\n<p>Wer lieber gleich auf die undeklarierte Variable hingewiesen werden m\u00f6chte, muss den Strict Mode aktivieren, der das Programm mit einer Fehlermeldung beendet. Der Strict Mode ist in verschiedenen Versionen verf\u00fcgbar:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Strict Mode Version 1.0<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 1.0\n$undeclared_variable -eq $null\n\nOutput:\nInvalidOperation: The variable '$undeclared_variable' cannot be retrieved because it has not been set.<\/code><\/pre>\n\n\n\n<p>In seiner einfachsten Form merkt der Strict Mode blo\u00df, dass die Variable nicht existiert. Doch schon wenn die Variable in einem String eingesetzt wird, wird sie wieder als <code>$null<\/code> aufgel\u00f6st:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 1.0\n\"Value between brackets: &#91;$undeclared_variable]\"\n\nOutput:\nValue between brackets: &#91;]<\/code><\/pre>\n\n\n\n<p>Genauso ergeht es \u00fcbrigens nicht existierenden Eigenschaften (w\u00e4hrend nicht existierende Methoden grunds\u00e4tzlich terminierende Fehler aufwerfen):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 1.0\n$test = \"hi there\"\n$test.NonExistingProperty -eq $null\n\nOutput:\nTrue<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Strict Mode Version 2.0<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 2.0\n\"Value between brackets: &#91;$undeclared_variable]\"\n\nOutput:\nInvalidOperation: The variable '$undeclared_variable' cannot be retrieved because it has not been set.<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 2.0\n$test = \"hi there\"\n$test.NonExistingProperty -eq $null\n\nOutput:\nPropertyNotFoundException: The property 'NonExistingProperty' cannot be found on this object. Verify that the property exists.<\/code><\/pre>\n\n\n\n<p>In Version 2.0 f\u00fchren auch nicht gesetzte Variablen in Strings und nicht existierende Eigenschaften zu einem terminierenden Fehler.<\/p>\n\n\n\n<p>Allerdings erlaubt er es auch nicht mehr, Funktionen mit mehreren Arguemnten mit der Syntax von Methoden aufzurufen \u2013 ein Stolperstein f\u00fcr alle, die mit anderen Programmiersprachen vertraut sind:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 2.0\n\nfunction Test {\n    param(\n    $arg1,\n    $arg2\n    )\n    $arg1\n    $arg2\n}\n\nTest(\"hi\", \"there\")\n\nOutput:\nInvalidOperation: The function or command was called as if it were a method. Parameters should be separated by spaces. For information about parameters, see the about_Parameters Help topic.<\/code><\/pre>\n\n\n\n<p>Korrekt ist folgende Schreibweise: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Test \"hi\" \"there\"\n\nOutput:\nhi\nthere<\/code><\/pre>\n\n\n\n<p>Doch entgegen der Fehlermeldung lassen sich die Argumente in diesem Fall auch mit Komma trennen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Test \"hi\", \"there\"\n\nOutput:\nhi\nthere<\/code><\/pre>\n\n\n\n<p>Und wenn man Funktionsname und \u00f6ffnende Klammer mit einem Leerzeichen trennt, wird zwar kein Fehler aufgeworfen, aber der Inhalt der Klammer wird als ein einziges argument und damit als <code>$arg1 <\/code>interpretiert, w\u00e4hrend <code>$arg2<\/code> implizit als <code>$null<\/code> gesetzt wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Test (\"hi, there\")\n\nOutput:\nhi, there<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Strict Mode Version 3.0<\/h2>\n\n\n\n<p>F\u00fcr Version 3.0 gilt ebenso alles f\u00fcr Version 2.0 Ausgef\u00fchrte. Zus\u00e4tzlich f\u00fchren aber auch ung\u00fcltige Indizes zu einem Fehler, w\u00e4hrend \u00e4ltere Versionen wieder einmal <code>$null<\/code> zur\u00fcckgaben:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 3.0\n$list = \"apples\", \"oranges\", \"peaches\"\n$list&#91;3]\n\nOutput:\nOperationStopped: Index was outside the bounds of the array.<\/code><\/pre>\n\n\n\n<p>PowerShell versucht, Indizes notfalls in den Typ <code>System.Int32<\/code> zu konvertieren (<code>\"002\"<\/code> zu <code>2<\/code>), und wenn das nicht m\u00f6glich ist, geben fr\u00fchere Versionen \u2026 richtig, <code>$null<\/code> zur\u00fcck. Nicht so mit Version 3.0:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version 3.0\n$list = \"apples\", \"oranges\", \"peaches\"\n$list&#91;\"test\"]\n\nOutput:\nInvalidArgument: Cannot convert value \"test\" to type \"System.Int32\". Error: \"Input string was not in a correct format.\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p>PowerShell ist von Natur aus sehr fehlertolerant und konvertiert gerne Fehlendes und Unm\u00f6gliches zu $null. Das ist praktisch, aber auch eine m\u00f6gliche und dann unter Umst\u00e4nden nicht offensichtliche Fehlerursache. Wer den Strict Mode einsetzt und sp\u00e4ter wieder ausschalten m\u00f6chte, kann das nat\u00fcrlich auch tun:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Off<\/code><\/pre>\n\n\n\n<p>Und wer immer den strengsten Modus anwenden m\u00f6chte, w\u00e4hlt einfach Latest (Vorsicht, es k\u00f6nnte ja einmal Version 4.0 eingef\u00fchrt werden):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-StrictMode -Version Latest<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Wer PowerShell lernt, stolpert h\u00e4ufig \u00fcber Eigenarten der Sprache, die sich von jenen anderer bekannter Sprachen unterscheiden und darum zun\u00e4chst \u00fcberraschend sind. Hier m\u00f6chte ich ein paar von ihnen hervorheben und erl\u00e4utern, wie das oft eigentlich gew\u00fcnschte Ergebnis erzielt werden kann. Los geht&#8217;s mit dem Standardverhalten von PowerShell, wenn der Interpreter auf eine nicht deklarierte&hellip; <a class=\"more-link\" href=\"https:\/\/pascal-korz.de\/blog\/2021\/04\/24\/powershell-fallen-1-die-schwarze-null-oder-ueber-den-strict-mode\/\"><span class=\"screen-reader-text\">PowerShell-Fallen #1: Die schwarze $null oder \u00fcber den Strict Mode<\/span> weiterlesen<\/a><\/p>\n","protected":false},"author":6,"featured_media":429,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-427","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","entry"],"_links":{"self":[{"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/posts\/427","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/comments?post=427"}],"version-history":[{"count":2,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/posts\/427\/revisions"}],"predecessor-version":[{"id":430,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/posts\/427\/revisions\/430"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/media\/429"}],"wp:attachment":[{"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/media?parent=427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/categories?post=427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pascal-korz.de\/blog\/wp-json\/wp\/v2\/tags?post=427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}