scenariusz: w atrybucie proxyAddresses w AD użytkownicy mają wpisane nieużywane adresy X4oo, które trzeba było usunąć. prościzna… przynajmniej tak mi się wydawało. sporo ciekawych drobiazgów przy tym wyszło i zadanie, które oceniałem na 15-2o min zajęło mi ze 2h /:
a takież to ciekawostki powychodziły…
najpierw trzeba wyszukać wszystkie obiekty [user/contact], które mają w proxyaddresses X400. szczęśliwie filtry są na tyle sprytne, że radzą sobie z multivalue [zaraz napiszę jak to robią] i nie trzeba się męczyć z jakimiś konwersjami:
get-adobject -f {proxyaddresses -like "*x400*"} -properties proxyaddresses|%{
<...tu bedzie obsluga...>
}
w 'normalnym’ języq, trzeba by się pomęczyć najpierw wyszuqjąc wszystkie obiekty posiadające wartość proxyaddresses, potem konwertując tablicę do stringa, a potem sprawdzić czy w tym stringu jest wartość x400 – bo w 'normalnym’ języq świat nie jest tak prosty (;
#tak nie trzeba robić, bo PowerShell rządzi!
get-adobject -f {proxyaddresses -like "*"} -properties proxyaddresses|%{
$pa=$_.proxyaddresses -join ';'
if( $pa -like "*X400*") {
<...>
proxyaddresses jest tupu 'mulivalue’ czyli jako parametr przyjmuje tablicę stringów i z tejże tablicy trzeba usunąć linijkę, która zawiera wartość 'x4oo’. wartość można łatwo odczytać, ale jak z tej tablicy wywalić ową linijkę?i tutaj czas na wyjaśnienie, jakim cudem filtr zadziałał dla tablicy tak, jakby to był pojedynczy string. spróbuję to zobrazować na trochę prostszym przykładzie:
C:\ :))o- $a=@("abc","cde","efg")
C:\ :))o- $a
abc
cde
efg
C:\ :))o- $a|gm
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
<...CUT..>
Replace Method string Replace(char oldChar, char newChar), string Replace(string ol..
<...CUT...>
na powyższym przykładzie widać, że po zdefiniowaniu tablicy i sprawdzeniu jej typu przy pomocy get-member, PS traktuje ją jak zwykły string… jeśli jednak sprawdzi się typ zmiennej….
C:\ :))o- $a.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
choć nieco dziwne, to wiele ułatwia. pozostaje jednak nadal pytanie – jak łatwo usunąć element z tablicy stringów? można kombinować z metodami replace i remove, które tu zadziałają jak dla zwykłego stringa, ale dają średnie rezultaty. dużo ciekawszym sposobem jest metoda remove, dla klasy ArrayList.
get-adobject -f {proxyaddresses -like "*x400*"} -properties proxyaddresses|%{
$newpa=[System.Collections.ArrayList]$_.proxyaddresses
foreach($p in $_.proxyaddresses) {
if($p -like '*x400*') {$newpa.remove($p)}
}
set-adobject $_ -Replace @{proxyaddresses=[array]$newpa}
}
na koniec jeszcze jedna ciekawostka. zanim wpadłem na konwersję do ArrayList, kombinowałem z przepisaniem zmiennej do drugiej tablicy i próbowałem wycinać z niej wartości na różne sposoby. tak trafiłem na kolejną 'ciekawostkę’ – w cudzysłowiu, bo de facto taki sposób działania jest normalny dla środowisk obiektowych: powiązanie zmiennej z atrybutem obiektu jest robione przez referencję a nie jest ona kopiowana. taki jakiś niedziałający kod:
get-adobject -f {proxyaddresses -like "*x400*"} -properties proxyaddresses|%{
$newpa=$_.proxyaddresses
foreach($p in $_.proxyaddresses) {
if($p -like '*x400*') {$newpa.remove($p)}
}
set-adobject $_ -Replace @{proxyaddresses=$newpa}
}
podczas działania dostawałem taki błąd:
An error occurred while enumerating through a collection: Collection was modified; enumeration operation may not execute..At D:\ISCG\scriptz\cleanX400.ps1:11 char:16
+ foreach <<<< ($p in $_.proxyaddresses) {
+ CategoryInfo : InvalidOperation: (System.Collecti…numeratorSimple:ArrayListEnumeratorSimple) [], RuntimeException
+ FullyQualifiedErrorId : BadEnumeration
kolekcja została zmodyfikowana… i faktycznie – kiedy sprawdziłem modyfikacje na $newpa, wyświetlenie $_.proxyaddresses je odzwierciedlało. wniosek – z obiektami nie ma żartów, trzeba uważać (;
na koniec jeszcze jedna metoda usuwania konkretnej linii a tablicy stringów, która jednak mi się nie przydała, ponieważ trzeba znać index. załóżmy, że chcę usunąć 4tą wartość:
$a=@('abc','def',1,5,8,'fgt',43)
$a=$a[0..2+4..($a.Length-1)]
reasumując – atrybuty zostały poprawione, a te 2h nie poszły na marne – rozumiem bardziej ^^
eN.


SieQ