potęgą PowerShell jest jego obiektowość, dzięki czemu cały język jest bardzo elastyczny. np filtrowanie wyjścia staje się bardzo proste:
ps|? name -match 'svc'
proste, jasne i przyjemne… i łatwo znaleźć na setkach tysiącach stron…
dla tego inne pytanie – a jak przefiltrować po wartościach wszystkich parametrów? np. „pokaż wszystkie parametry obiektu, które mają 'name’ w nazwie”, albo „pokaż wszystkie wartości parametrów, które zawierają 'abc'”. tego już tak łatwo zrobić się nie da. to będzie nieco nieprzyjemna przejażdżka, bo wymaga rozebrania obiektu na kawałki – czyli tracimy automatykę PS, która tak ślicznie pomaga w 'normalnych’ zapytaniach, i grzebiemy we flakach.
aby osiągnąć cel trzeba skorzystać z ukrytego parametru 'psobject’, który pokazuje wnętrzności obiektu. dodatkowo sprawę kompliqje fakt, że wyjście jest często tablicą obiektów a nie pojedynczym obiektem. pobawmy się 'get-service’ i zrealizujmy takie zadania:
- wyświetlmy wszystkie nazwy i wartości parametrów, które mają w nazwie 'name’
- wyświetlmy wszystkie nazwy i wartości parametrów, dla których wartość jest równa 'true’
w pierwszej kolejności zobaczmy jak taki obiekt wygląda wewnątrz. najpierw klasycznie…:
PS C:\_scriptZ> Get-Service|gm TypeName: System.ServiceProcess.ServiceController Name MemberType Definition ---- ---------- ---------- Name AliasProperty Name = ServiceName RequiredServices AliasProperty RequiredServices = ServicesDependedOn Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs) Close Method void Close() Continue Method void Continue() CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) Dispose Method void Dispose(), void IDisposable.Dispose() Equals Method bool Equals(System.Object obj) ExecuteCommand Method void ExecuteCommand(int command) GetHashCode Method int GetHashCode() GetLifetimeService Method System.Object GetLifetimeService() GetType Method type GetType() InitializeLifetimeService Method System.Object InitializeLifetimeService() Pause Method void Pause() Refresh Method void Refresh() Start Method void Start(), void Start(string[] args) Stop Method void Stop() WaitForStatus Method void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desiredStat... CanPauseAndContinue Property bool CanPauseAndContinue {get;} CanShutdown Property bool CanShutdown {get;} CanStop Property bool CanStop {get;} Container Property System.ComponentModel.IContainer Container {get;} DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;} DisplayName Property string DisplayName {get;set;} MachineName Property string MachineName {get;set;} ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;} ServiceName Property string ServiceName {get;set;} ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;} ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;} Site Property System.ComponentModel.ISite Site {get;set;} StartType Property System.ServiceProcess.ServiceStartMode StartType {get;} Status Property System.ServiceProcess.ServiceControllerStatus Status {get;} ToString ScriptMethod System.Object ToString();
a potem… od środka:
PS C:\_scriptZ> (get-service).psobject Members : {Count = Length, int Length {get;}, long LongLength {get;}, int Rank {get;}...} Properties : {Count = Length, int Length {get;}, long LongLength {get;}, int Rank {get;}...} Methods : {void Set(int , System.Object ), System.Object&, mscorlib, Version=4.0.0.0, Culture=neutral, Publ icKeyToken=b77a5c561934e089 Address(int ), System.Object Get(int ), System.Object GetValue(Params int[] indices), System.Object GetValue(int index), System.Object GetValue(int index1, int index2 ), System.Object GetValue(int index1, int index2, int index3), System.Object GetValue(long index) , System.Object GetValue(long index1, long index2), System.Object GetValue(long index1, long inde x2, long index3), System.Object GetValue(Params long[] indices)...} ImmediateBaseObject : {aciseagent, AdobeARMservice, AdobeFlashPlayerUpdateSvc, agiptd...} BaseObject : {aciseagent, AdobeARMservice, AdobeFlashPlayerUpdateSvc, agiptd...} TypeNames : {System.Object[], System.Array, System.Object}
nas będą interesować 'properties’, których nazwy zawierają 'name’. nie będę się bawił w step-by-step, myślę, że taki początek wystarczy, a całą resztę trzeba po prostu usiąść i się pobawić. mamy podstawy więc teraz trzeba po PowerShellowemu zapisać zadanie „wyświetl wszystkie usługi (obiekty), następnie dla każdej usługi przefiltruj te parametry, który mają w nazwie 'name’ a następnie wyświetl tylko nazwę i wartość”. po takim zapisie to już bułka z masłem:
Get-Service|%{$_.psobject.properties|? name -match 'name'}|ft name,value
a teraz drugie zadanie – i tu robi się na prawdę pasqdnie, bo wartości mogą być różnych typów i też są obiektami. ponadto samo 'property, value’ będzie bezużyteczne bez dodatkowej informacji – nazwy usługi dla której je znaleźliśmy. poniżej rozwiązanie, zachęcam do zrozumienia – czyli samodzielnych testów:
get-service|%{$sn=$_.name;$_.psobject.members|?{$_.membertype -eq 'property' -and $_.value -eq $true}}|select @{N='ServiceName';E={$sn}},name,value
żeby nie było za łatwo… i tego nie potrafię wyjaśnić – z jakiegoś powodu 'Stopped’ jest traktowany jako $true. fragment wyjścia:
ServiceName Name Value ----------- ---- ----- aciseagent CanStop True AdobeARMservice CanStop True AdobeFlashPlayerUpdateSvc Status Stopped agiptd CanStop True AJRouter Status Stopped ALG Status Stopped ApHidMonitorService CanS... True ApHidMonitorService CanStop True AppHostSvc CanP... True AppHostSvc CanS... True AppHostSvc CanStop True AppIDSvc Status Stopped Appinfo CanStop True AppMgmt Status Stopped AppReadiness Status Stopped
… ale już nie chce mi się zagłębiać dalej.
sztuka dla sztuki? niekoniecznie. często trafiam na scenariusz, prostszy niż zaprezentowane, gdzie dostaję obiekt o dużej liczbie parametrów – np. obiekty EXO – i chcę sprawdzić czy gdzieś nie siedzi jakaś wartość, przy czym nie mam pojęcia jak może nazywać się parametr. o ile w ogóle istnienie. np. wyświetlmy wszystkie URI jakie są skonfigurowane dla grupy o365:
PS C:\_scriptZ> (Get-UnifiedGroup -Identity GuestGroupTest).psobject.Members.value|Select-String 'http' https://outlook.office365.com/owa/?path=/group/GuestGroupTest@w-files.pl/calendar https://outlook.office365.com/owa/?path=/group/GuestGroupTest@w-files.pl/mail https://outlook.office365.com/owa/?path=/group/GuestGroupTest@w-files.pl/people https://outlook.office365.com/EWS/Exchange.asmx/s/GetUserPhoto?email=GuestGroupTest@w-files.pl
to tak w ramach przygotowań do ShareCon365 (; zapraszam na moją sesję!
PS. aahhh… jeśli ktoś czytał z uwagą, to powinien zadać pytanie – „a jakie jeszcze ukryte parametry mają obiekty?„. i jeśli ktoś takie pytanie by zadał, otrzymałby zapewne odpowiedź: „<your-command>|gm -force”
eN.
ziembor
nExoR
Mateusz
nExoR