Was zum Teufel ist mit diesem AD-Filter in PowerShell los?

9

Ich habe kürzlich diese Antwort geschrieben und bin auf etwas Interessantes gestoßen.

get-aduser -filter {-not (description -eq "auto")} | measure-object

und

get-aduser -filter {description -ne "auto"} | measure-object

Geben Sie zwei sehr unterschiedliche Dinge zurück, wenn Sie mit denselben Daten ausgeführt werden, wobei der erste Befehl den erwarteten Wert zurückgibt. Auf den ersten Blick scheint es, dass Benutzer mit einem Nullwert im Beschreibungsfeld im zweiten Befehl nicht als Übereinstimmungen zurückgegeben werden, obwohl NULL eindeutig nicht gleich "auto" ist.

Ein paar Leute im Chat haben sich das angesehen und bestätigt, dass ich nicht verrückt bin. Was ist hier los?

MDMarra
quelle
1
Interessant, dass es funktioniert, wenn man es durch das Where-Objekt leitet und den Filter anwendet, der oben nicht funktioniert. get-aduser -filter * -Properties description | ? {$ _. description -ne "Auto"} | Maßnahme
Mike
@Mike Ja, dies scheint nur das Verhalten des -neVergleichsoperators innerhalb des -FilterBlocks zu sein. Insbesondere, wenn der Eingabewert des Vergleichs ist $null.
Jscott
1
Like und Notlike scheinen ähnlich zu funktionieren. {description -notlike "Something"} funktioniert nicht, aber {-not (description -like "Something")} funktioniert. Auch die Bewertung dauert erheblich länger. Wie der kaputte bewertet nicht alle Objekte, die er sollte.
Mike
@ Mike Das stimmt. Ich bin -notlikeursprünglich auf diese Verwendung gestoßen , habe aber zu gewechselt, -nenachdem mir klar wurde, dass ich nicht das bekam, was ich wollte. TBH, ich habe vergessen, dass ich das sogar versucht habe, bis Sie es erwähnt haben - aber ich kann es auch reproduzieren.
MDMarra
2
Nur ein Gedanke, aber vielleicht versucht die -eq/ -ne-Klausel von PoSH , sich wie ein SQL =/ zu verhalten <>? In SQL foo = NULLund foo <> NULLwird immer false zurückgeben, da NULL 'unvergleichbar' ist - nur die foo IS NULLund foo IS NOT NULLspezielle Operatoren funktionieren. Das Verhalten muss in PoSH ähnlich sein, wo Ihr -not (foo -eq "bar")Filter alles (foo -eq "bar")zurückgeben würde, wofür zurückgegeben wurde $false, was foo -eq $nulltun würde. Wie wäre es stattdessen mit if (!foo -or foo -ne "bar")(äquivalentem SQL foo IS NULL OR foo <> 'bar')?
jimbobmcgee

Antworten:

4

Der Hauptunterschied zwischen den beiden besteht darin, dass der erste Befehl keinen direkten Vergleich der Werte beinhaltet, um alle Ergebnisse zu erhalten, und der zweite Befehl. Der erste Befehl enthält NULL-Ergebnisse und der zweite nicht (wie MDMarra bereits festgestellt hat). Beide Befehle beginnen mit diesem Cmdlet:

get-aduser

Denken Sie beim Durchgehen des Folgenden daran, dass die Ergebnisse dieses Cmdlets alle AD-Benutzer enthalten, unabhängig davon, ob der -filterParameter danach noch etwas enthält.

Lassen Sie uns nun die beiden Teile aufteilen, die unterschiedlich sind. Der erste:

{-not (description -eq "auto")}

...meint

  1. „herauszufinden , wo die Beschreibung Attribut gleich den Textstring‚auto‘. Für diesen Vergleich zu der Arbeit, ein String - Bedarf für die im Beschreibungsfeld existiert -eqBediener in der Lage sein , es zu vergleichen , um zu‚auto‘. NULL - Werte werden von diesem gelöscht Vergleich, da NULL nicht mit einem Zeichenfolgenwert verglichen werden kann.
  2. unabhängig von der -eqFilterparameter geben mir ALLES, was NICHT das Ergebnis von ist (description -eq "auto"), das NULL-Werte enthält, da das ursprüngliche Cmdlet get-aduseralle AD-Benutzer enthält. Es musste nichts mit etwas anderem mit dem -notBediener vergleichen. Es gab Ihnen nur alles außer den Ergebnissen des (description -eq "auto")Filters.

Angenommen, Sie haben in Ihrem Beispiel einen AD-Benutzer, dessen Beschreibung gleich "auto" ist, einige hundert mit etwas anderem als "auto" und einige hundert mit NULL-Beschreibungen. Durchlaufen der Befehlslogik:

  1. Geben Sie mir alle AD-Benutzer (get-aduser), bei denen die Beschreibung gleich "auto" ist - ergibt 1 Benutzer
  2. Geben Sie mir alle AD-Benutzer, die NICHT das sind, was Sie mir gerade gegeben haben - das Ergebnis sind die wenigen hundert mit etwas anderem UND die wenigen hundert, die NULL haben.

Da mit dem -notOperator nichts mit anderen verglichen werden musste, enthielt das Ergebnis die NULL-Beschreibungsbenutzer, die im ursprünglichen get-aduserCmdlet erfasst wurden.

Der zweite Befehl:

{description -ne "auto"}

...meint

  1. "Finden Sie heraus, wo das Beschreibungsattribut nicht der exakten Zeichenfolge" auto "entspricht. Damit dieser Vergleich funktioniert, muss im Beschreibungsfeld eine Zeichenfolge vorhanden sein, damit der -neBediener sie mit" auto "vergleichen kann. NULL-Werte werden aus diesem Vergleich entfernt, da NULL nicht mit einem Zeichenfolgenwert verglichen werden kann.

Nehmen wir in Ihrem Beispiel noch einmal an, Sie haben 1 AD-Benutzer, dessen Beschreibung gleich "auto" ist, einige hundert mit etwas anderem als "auto" und einige hundert mit NULL-Beschreibungen. Durchlaufen der Befehlslogik:

  1. Geben Sie mir alle AD-Benutzer, bei denen die Beschreibung nicht gleich "auto" ist. Dies führt dazu, dass die wenigen hundert Benutzer etwas anderes als "auto" in ihrer Beschreibung haben. Benutzer mit NULL-Beschreibungen werden nicht abgerufen, da NULL nicht mit einer Textzeichenfolge verglichen werden kann.

In beiden Fällen ist der gesamte Unterschied zwischen den beiden Befehlen definitiv nicht intuitiv.

Mit diesem Befehl sollten Sie auch in der Lage sein, die NULL-Werte mit einem "-und" wie folgt abzufangen:

{description -ne "auto" -and description -ne $NULL}

Ich bin nicht zu 100% mit der Syntax vertraut, da ich sie momentan nicht testen kann, und es gibt wahrscheinlich auch einen besseren Weg, dies zu tun. Wenn alles kaputt ist, ist es ziemlich antiklimatisch und es hat viel Tipparbeit gekostet, um es zu erklären, aber ich bin auf seltsame Dinge wie dieses gestoßen, bevor ich die verschiedenen Operatoren verwendet habe, und viel Versuch und Irrtum, da ich mich nie an alle Vorbehalte erinnern kann das geht mit der Verwendung jedes einzelnen einher.

Referenz: http://technet.microsoft.com/en-us/library/hh847732.aspx :

Vergleichsoperatoren

Verwenden Sie Vergleichsoperatoren (-eq, -ne, -gt, -lt, -le, -ge), um Werte und Testbedingungen zu vergleichen. Sie können beispielsweise zwei Zeichenfolgenwerte vergleichen, um festzustellen, ob sie gleich sind.

Zu den Vergleichsoperatoren gehören die Übereinstimmungsoperatoren (-match, -notmatch), die Muster mithilfe regulärer Ausdrücke finden. der Ersetzungsoperator (-replace), der reguläre Ausdrücke verwendet, um Eingabewerte zu ändern; ähnliche Operatoren (-like, -notlike), die Muster mithilfe von Platzhalterzeichen (*) finden; und die Containment-Operatoren (in, -notin, -contains, -notcontains), die bestimmen, ob ein Testwert in einem Referenzsatz erscheint.

Sie enthalten auch die bitweisen Operatoren (-bAND, -bOR, -bXOR, -bNOT), um die Bitmuster in Werten zu manipulieren.

Weitere Informationen finden Sie unter about_Comparison_Operators

Logische Operatoren

Verwenden Sie logische Operatoren (-and, -or, -xor, -not ,!), Um bedingte Anweisungen zu einer einzigen komplexen Bedingung zu verbinden . Sie können beispielsweise einen logischen Operator -und verwenden, um einen Objektfilter mit zwei verschiedenen Bedingungen zu erstellen.

Weitere Informationen finden Sie unter about_Logical_Operators.

August
quelle
Sicher eine gute Übersicht, aber warum werden Nullwerte von den Operatoren -ne und -notlike ausgeschlossen? Das ist der wahre Kopfkratzer. Ich frage mich, ob es von Natur aus eine esoterische .net-Spezifikationserklärung hat oder ob es ein Fehler oder ein unerwartetes Verhalten ist.
MDMarra
Warten Sie, lesen Sie einfach genauer. Es sieht so aus, als würden sie nur Zeichenfolgen vergleichen, und Nullattribute sind tatsächlich Null und keine leere Zeichenfolge. Interessant, wenn auch nicht intuitiv.
MDMarra
0

Hinzufügen zu dieser alten Frage, wie sie bei der Suche auftaucht:

Die Verwendung von -Filter mit negativer Übereinstimmung wie -ne oder -notlike schließt Ergebnisse mit leeren Nullwerten aus. Damit sie eingeschlossen werden können, müssen Sie auch explizit mit -notlike '*' übereinstimmen, da -eq '' und -eq $ NULL keine gültigen Filter sind. Beachten Sie, dass dies eine Eigenart bei -Filter ist, bei der ein direkter -LdapFilter verwendet wird.

Hier ist ein Filter- und LdapFilter-Beispiel für eine Mehrfachübereinstimmung mit einem Negativ:

Get-ADUser -Filter { mail -like '*example*' -and (description -ne 'example' -or description -notlike '*') }

Get-ADUser -LdapFilter '(&(mail=*example*)(!description=example))'
WhoIsRich
quelle