Mint ahogy az fejezet elején bemutattam, a PowerShell igazából a .NET osztályokat nem közvetlenül kezeli, hanem néha kicsit átalakítja annak érdekében, hogy még egységesebb, egyszerűbb, bizonyos esetekben biztonságosabb legyen ezen objektumok kezelése.
Különböző nézetek segítségével mi is láthatjuk azt, hogy milyen „csalafintaságokat” követett el ezeken az osztályokon a PowerShell:
Nézet neve |
Nézet tartalma |
PSBASE |
A .NET-es osztály eredeti állapotban |
PSADAPTED |
A PowerShell által adaptált nézet (ezt látjuk alaphelyzetben) |
PSEXTENDED |
Csak a kibővített tagok |
PSOBJECT |
Magának az adapternek a nézete |
Nézzünk ezekre néhány példát. Elsőként az XML adattípust mutatom, mert ott elég jól láthatóak ezen nézetek közti különbségek. Nézzük meg egy XML adat tagjellemzőit:
[20] PS C:\> $x = [xml] "<elem>érték<szint1><szint2>mélyadat</szint2></szint
1></elem>"
[21] PS C:\> $x | Get-Member
TypeName: System.Xml.XmlDocument
Name MemberType Definition
---- ---------- ----------
ToString CodeMethod static System.String X...
add_NodeChanged Method System.Void add_NodeCh...
add_NodeChanging Method System.Void add_NodeCh...
...
Validate Method System.Void Validate(V...
WriteContentTo Method System.Void WriteConte...
WriteTo Method System.Void WriteTo(Xm...
Item ParameterizedProperty System.Xml.XmlElement ...
elem Property System.Xml.XmlElement ...
Nagyon sok jellemzője van, az egyszerűbb áttekinthetőség miatt kicsit megvágtam a közepén. A legutolsó jellemző egy Property típusú, elem nevű tag. Hát ilyet biztos nem tettek bele a .NET keretrendszerbe. Erről meg is győződhetünk:
[22] PS C:\> $x.psbase | Get-Member
TypeName: System.Management.Automation.PSMemberSet
Name MemberType Definition
---- ---------- ----------
add_NodeChanged Method System.Void add_NodeCh...
add_NodeChanging Method System.Void add_NodeCh...
...
ChildNodes Property System.Xml.XmlNodeList...
DocumentElement Property System.Xml.XmlElement ...
DocumentType Property System.Xml.XmlDocument...
FirstChild Property System.Xml.XmlNode Fir...
HasChildNodes Property System.Boolean HasChil...
...
Value Property System.String Value {g...
XmlResolver Property System.Xml.XmlResolver...
A fenti listában tényleg nincs elem nevű tulajdonság. Miért tették bele ezt az elem tulajdonságot vajon a PowerShell alkotói? Azért, hogy egyszerűen lehessen hivatkozni az XML adathalmaz különböző elemeire, hiszen az XML egy hierarchikus felépítésű adattípus, így könnyen adódik az ötlet az ilyen jellegű hivatkozási lehetőségre:
[23] PS C:\> $x.elem
#text szint1
----- ------
érték szint1
[24] PS C:\> $x.elem.szint1
szint2
------
mélyadat
[25] PS C:\> $x.elem.szint1.szint2
mélyadat
Nézzük, hogy a PS1XML fájlban történt-e típusbővítés az XML típus esetében?
[53] PS C:\> $x.psextended | Get-Member
TypeName: System.Management.Automation.PSMemberSet
Name MemberType Definition
---- ---------- ----------
ToString CodeMethod static System.String XmlNode(PSObject instance)
Egyetlen egy CodeMethod lett csak definiálva, amellyel sztringgé alakíthatjuk az XML adatot.
Nézzük meg az általam létrehozott Tipus tulajdonságot a fájl és könyvtár objektumoknál:
[27] PS C:\> $fo = Get-Item C:\powershell2\demo\demo1.ps1
[28] PS C:\> $fo.Tipus
File
[29] PS C:\> $fo.psextended | Get-Member
TypeName: System.Management.Automation.PSMemberSet
Name MemberType Definition
---- ---------- ----------
PSChildName NoteProperty System.String PSChildName=demo1.ps1
PSDrive NoteProperty System.Management.Automation.PSDriveInfo PS...
PSIsContainer NoteProperty System.Boolean PSIsContainer=False
PSParentPath NoteProperty System.String PSParentPath=Microsoft.PowerS...
PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.C...
PSProvider NoteProperty System.Management.Automation.ProviderInfo P...
Tipus NoteProperty System.String Tipus=File
BaseName ScriptProperty System.Object BaseName {get=[System.IO.Path...
Mode ScriptProperty System.Object Mode {get=$catr = "";...
ReparsePoint ScriptProperty System.Object ReparsePoint {get=if($this.At...
Ott látható a listában az általam, a PS1XML fájlon keresztül történt típusbővítésnek a nyoma.
Nézzünk még egy példát a PSBase nézet használatára:
[30] PS C:\> PS C:\> $user = [ADSI] "WinNT://$env:computername/$env:username"
[31] PS C:\> $user.name
tibi
[32] PS C:\> $user | Get-Member
TypeName: System.DirectoryServices.DirectoryEntry
Name MemberType Definition
---- ---------- ----------
ConvertDNWithBinaryToString CodeMethod static string ConvertDNWithBinaryToS...
ConvertLargeIntegerToInt64 CodeMethod static long ConvertLargeIntegerToInt...
AutoUnlockInterval Property System.DirectoryServices.PropertyVal...
BadPasswordAttempts Property System.DirectoryServices.PropertyVal...
Description Property System.DirectoryServices.PropertyVal...
FullName Property System.DirectoryServices.PropertyVal...
HomeDirDrive Property System.DirectoryServices.PropertyVal...
HomeDirectory Property System.DirectoryServices.PropertyVal...
LastLogin Property System.DirectoryServices.PropertyVal...
LockoutObservationInterval Property System.DirectoryServices.PropertyVal...
LoginHours Property System.DirectoryServices.PropertyVal...
LoginScript Property System.DirectoryServices.PropertyVal...
MaxBadPasswordsAllowed Property System.DirectoryServices.PropertyVal...
MaxPasswordAge Property System.DirectoryServices.PropertyVal...
MaxStorage Property System.DirectoryServices.PropertyVal...
MinPasswordAge Property System.DirectoryServices.PropertyVal...
MinPasswordLength Property System.DirectoryServices.PropertyVal...
Name Property System.DirectoryServices.PropertyVal...
objectSid Property System.DirectoryServices.PropertyVal...
Parameters Property System.DirectoryServices.PropertyVal...
PasswordAge Property System.DirectoryServices.PropertyVal...
PasswordExpired Property System.DirectoryServices.PropertyVal...
PasswordHistoryLength Property System.DirectoryServices.PropertyVal...
PrimaryGroupID Property System.DirectoryServices.PropertyVal...
Profile Property System.DirectoryServices.PropertyVal...
UserFlags Property System.DirectoryServices.PropertyVal...
Egy helyi felhasználót betöltöttem a $user nevű változómba, szépen le is tudtam kérdezni a nevét. Majd amikor kilistázom a felhasználóm tagjellemzőit, meglepődve láthatjuk, hogy nincs köztük igazi, praktikus metódus sem! Márpedig nehezen hihető el, hogy tényleg semmi értelmeset nem tud egy felhasználói fiók magával kezdeni. Nézzünk az objektumunk mögé:
[34] PS C:\> $user.psbase | Get-Member
TypeName: System.Management.Automation.PSMemberSet
Name MemberType Definition
---- ---------- ----------
Disposed Event System.EventHandler Disposed(System.Ob...
Close Method System.Void Close()
CommitChanges Method System.Void CommitChanges()
CopyTo Method adsi CopyTo(adsi newParent), adsi Copy...
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateO...
DeleteTree Method System.Void DeleteTree()
Dispose Method System.Void Dispose()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Invoke Method System.Object Invoke(string methodName...
InvokeGet Method System.Object InvokeGet(string propert...
InvokeSet Method System.Void InvokeSet(string propertyN...
MoveTo Method System.Void MoveTo(adsi newParent), Sy...
RefreshCache Method System.Void RefreshCache(), System.Voi...
Rename Method System.Void Rename(string newName)
ToString Method string ToString()
AuthenticationType Property System.DirectoryServices.Authenticatio...
Children Property System.DirectoryServices.DirectoryEntr...
Container Property System.ComponentModel.IContainer Conta...
Guid Property System.Guid Guid {get;}
Name Property System.String Name {get;}
NativeGuid Property System.String NativeGuid {get;}
NativeObject Property System.Object NativeObject {get;}
ObjectSecurity Property System.DirectoryServices.ActiveDirecto...
Options Property System.DirectoryServices.DirectoryEntr...
Parent Property System.DirectoryServices.DirectoryEntr...
Password Property System.String Password {set;}
Path Property System.String Path {get;set;}
Properties Property System.DirectoryServices.PropertyColle...
SchemaClassName Property System.String SchemaClassName {get;}
SchemaEntry Property System.DirectoryServices.DirectoryEntr...
Site Property System.ComponentModel.ISite Site {get;...
UsePropertyCache Property System.Boolean UsePropertyCache {get;s...
Username Property System.String Username {get;set;}
Hoppá! Mindjárt más a helyzet. A metódusok zöme természetesen tartományi környezetben használható, de például a rename() vagy a set_password() metódus helyi gépen is praktikus szolgáltatás.
Vajon ezek a metódusok miért nincsenek alaphelyzetben adaptálva a PowerShell környezetre? Erre az igazi választ nem tudom, valószínű ez egy biztonsági megfontolás volt, hogy a szkriptelők ne írogassanak felelőtlenül olyan szkripteket, amelyekkel a felhasználói objektumokat módosítanak. Vagy az is lehet a magyarázat, hogy egy másik interfészt szánt volna igazából a Microsoft a felhasználó menedzsment céljaira, amin keresztül módosítani lehetett volna, de ez a PowerShell aktuális verziójába már nem fért bele.
Megjegyzése
A PowerShell 2.0-ban már a Get-Member is tud az objektumok mögé látni, azaz a [34]-es sor eredményét így is megkaphatjuk:
PS C:\> $user | Get-Member -View base
Hasonlóan megkaphatjuk a további nézeteket a –View paraméterhez megadott Extended, Adapted vagy All szavakkal.
Illetve maga a PSBase és PSExtended, stb. „tulajdonságokat” a get-member –force kapcsolójával tudjuk láttatni:
PS C:\> 1 | Get-Member -Force
TypeName: System.Int32
Name MemberType Definition
---- ---------- ----------
pstypenames CodeProperty System.Collections.ObjectModel.Collection`1[[Syste...
psadapted MemberSet psadapted {CompareTo, Equals, GetHashCode, ToStrin...
psbase MemberSet psbase {CompareTo, Equals, GetHashCode, ToString, ...
psextended MemberSet psextended {}
psobject MemberSet psobject {Members, Properties, Methods, ImmediateB...
CompareTo Method int CompareTo(System.Object value), int CompareTo(...
Equals Method bool Equals(System.Object obj), bool Equals(int obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode()
ToString Method string ToString(), string ToString(string format),...
Utoljára nézzük a PSObject nézetet. Vegyünk például megint egy fájlt, és nézzük meg tulajdonságait:
[1] PS C:\> $f = Get-Item C:\munka\a.txt
[2] PS C:\> $f
Directory: C:\munka
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2010. 01. 16. 10:59 402 a.txt
[3] PS C:\> $f.psobject
Members : {System.String PSPath=Microsoft.PowerShell.Core\FileSyst
em::C:\munka\a.txt, System.String PSParentPath=Microsoft
.PowerShell.Core\FileSystem::C:\munka, System.String PSC
hildName=a.txt, System.Management.Automation.PSDriveInfo
PSDrive=C...}
Properties : {System.String PSPath=Microsoft.PowerShell.Core\FileSyst
em::C:\munka\a.txt, System.String PSParentPath=Microsoft
.PowerShell.Core\FileSystem::C:\munka, System.String PSC
hildName=a.txt, System.Management.Automation.PSDriveInfo
PSDrive=C...}
Methods : {string get_Name(), long get_Length(), string get_Direct
oryName(), System.IO.DirectoryInfo get_Directory()...}
ImmediateBaseObject : C:\munka\a.txt
BaseObject : C:\munka\a.txt
TypeNames : {System.IO.FileInfo, System.IO.FileSystemInfo, System.Ma
rshalByRefObject, System.Object}
Látható a [2]-es sorban, hogy az $f változóban tényleg a fájl van, míg a [3]-as sorban a PSObject nézete ennek az objektumnak már nem a fájl jelleget adja vissza, hanem általában egy PowerShellbeli objektum jellegzetességeit, azaz hogy az objektumnak vannak tagjellemzői, tulajdonságai, metódusai. A TypeNames tulajdonságból kiolvasható, hogy az objektum milyen osztályok leszármazottja.