Automating the world one-liner at a time…
This topic is a little long but I strongly encourage you to walk through it and master the techniques it illustrates. I can assure you that you'll will use them a couple thousand times in the next couple of years.
.Net provides a wonderful class called System.Environment that tells you all about your environment. It is well worth taking a few minutes to stop what you are doing and explore this class so that you understand its capabilities. That way when a relevant issue comes up, you'll know that there is very simple way to get the answer.
First thing to remember is that they way you specify a type in PowerShell is with square brackets:
PS> [System.Environment]
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False Environment System.Object
The next thing to remember is that PowerShell allows you to drop the "SYSTEM" from types:
PS> [System.Diagnostics.Process]
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False Process System.ComponentModel.Component
PS> [Diagnostics.Process]
PS> [Environment]
The next thing to remember is that types can have STATIC properties and methods. What are a "static properties and methods"? Most properties are methods that you deal with are OBJECT properties and methods which is to say that they are the "properties of THAT object" or the "methods that can be invoked on THAT object". Static properties and methods do not require an object to be invoked. There are lots of reasons why programmers use statics but the thing you need to know is that it is well worth exploring static properties and methods because they often contain gems of functionality. Not all types have statics in fact most don't but those that do are often super useful so it is worth the explore.
So how do you explore? Well with PowerShell of course. Remember that PowerShell is designed to allow you to explore the system. We want to to cultivate a strong sense of curiosity about your system and want to make it easy and safe (where possible) for you to go splunking around. So the tool to explore Statics is Get-Member. Here is what you need to know:
1) Get-Member has a -STATIC parameter. 2) You can pipe INSTANCES or TYPES to get-member 3) "Get-Member -Static" can be invoked as "gm -s"
Let's explore:
PS> Get-Date |Get-Member -Static
TypeName: System.DateTime
Name MemberType Definition ---- ---------- ---------- Compare Method static int Compare(System.DateTime t1, System.DateTime t2) DaysInMonth Method static int DaysInMonth(int year, int month) Equals Method static bool Equals(System.DateTime t1, System.DateTime t2), static bool Eq FromBinary Method static System.DateTime FromBinary(long dateData) FromFileTime Method static System.DateTime FromFileTime(long fileTime) FromFileTimeUtc Method static System.DateTime FromFileTimeUtc(long fileTime) FromOADate Method static System.DateTime FromOADate(double d) IsLeapYear Method static bool IsLeapYear(int year) Parse Method static System.DateTime Parse(string s), static System.DateTime Parse(strin ParseExact Method static System.DateTime ParseExact(string s, string format, System.IFormatP ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object objB) SpecifyKind Method static System.DateTime SpecifyKind(System.DateTime value, System.DateTimeK TryParse Method static bool TryParse(string s, System.DateTime&, mscorlib, Version=2.0.0.0 TryParseExact Method static bool TryParseExact(string s, string format, System.IFormatProvider MaxValue Property static System.DateTime MaxValue {get;} MinValue Property static System.DateTime MinValue {get;} Now Property System.DateTime Now {get;} Today Property System.DateTime Today {get;} UtcNow Property System.DateTime UtcNow {get;}
PS> Get-Date |gm -s
PS> [DateTime] |gm -s
Now lets explore how you access these. You use "::" on types to invoke statics:
PS> [Datetime]::Today
Saturday, December 13, 2008 12:00:00 AM
PS> [Datetime]::IsLeapYear(2008) True
So with that background, let's explore some of SYSTEM.ENVIRONMENT properties:
PS> [Environment] |gm -s
TypeName: System.Environment
Name MemberType Definition ---- ---------- ---------- Equals Method static bool Equals(System.Object o... Exit Method static System.Void Exit(int exitCode) ExpandEnvironmentVariables Method static string ExpandEnvironmentVar... FailFast Method static System.Void FailFast(string... GetCommandLineArgs Method static System.String[] GetCommandL... GetEnvironmentVariable Method static string GetEnvironmentVariab... GetEnvironmentVariables Method static System.Collections.IDiction... GetFolderPath Method static string GetFolderPath(System... GetLogicalDrives Method static System.String[] GetLogicalD... ReferenceEquals Method static bool ReferenceEquals(System... SetEnvironmentVariable Method static System.Void SetEnvironmentV... CommandLine Property static System.String CommandLine {... CurrentDirectory Property static System.String CurrentDirect... ExitCode Property static System.Int32 ExitCode {get;... HasShutdownStarted Property static System.Boolean HasShutdownS... MachineName Property static System.String MachineName {... NewLine Property static System.String NewLine {get;} OSVersion Property static System.OperatingSystem OSVe... ProcessorCount Property static System.Int32 ProcessorCount... StackTrace Property static System.String StackTrace {g... SystemDirectory Property static System.String SystemDirecto... TickCount Property static System.Int32 TickCount {get;} UserDomainName Property static System.String UserDomainNam... UserInteractive Property static System.Boolean UserInteract... UserName Property static System.String UserName {get;} Version Property static System.Version Version {get;} WorkingSet Property static System.Int64 WorkingSet {get;}
PS> [Environment]::MachineName JPSW7-5 PS> [Environment]::OSVersion
Platform ServicePack Version VersionString -------- ----------- ------- ------------- Win32NT 6.1.7004.0 Microsoft Windo...
PS> [Environment]::ProcessorCount 2 PS> [Environment]::UserInteractive True PS> [Environment]::UserDomainName NTDEV PS> [Environment]::UserName jsnover PS> [Environment]::SystemDirectory C:\Windows\system32 PS>
Now let's explore some methods:
PS> [Environment]::GetLogicalDrives() C:\ D:\ E:\ PS> [Environment]::GetEnvironmentVariable("PATH") %SystemRoot%\system32\WindowsPowerShell\v1.0\;C:\Windows\system32;C:\Window s;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\P rogram Files\WTT 2.2\Client\;C:\PROGRA~1\CA\SHARED~1\SCANEN~1;C:\Program Fi les\CA\eTrust Antivirus;c:\ps PS> [Environment]::GetFolderPath() Cannot find an overload for "GetFolderPath" and the argument count: "0". At line:1 char:29 + [Environment]::GetFolderPath <<<< () + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest
PS>
Notice the error I got for GetFolderPath() - it's complaining about the number of arguments it got. So now let's learn the technique to discover method signatures. If you specify a method and use "()", it invokes the method. If you don't provide the "()" and just specify the name, it give you information about the method:
PS> [Environment]::GetFolderPath
MemberType : Method OverloadDefinitions : {static string GetFolderPath(System.Environment+Speci alFolder folder)} TypeNameOfValue : System.Management.Automation.PSMethod Value : static string GetFolderPath(System.Environment+Specia lFolder folder) Name : GetFolderPath IsInstance : True
This tells you that the method takes one argument whose name is "folder" and whose type is System.Environment+SpecialFolder. What the heck is that?
PS> [System.Environment+SpecialFolder]
IsPublic IsSerial Name BaseType -------- -------- ---- -------- False True SpecialFolder System.Enum
Notice that it is an ENUM. The great things about ENUMS is that when you specify an invalid value - it tells you what the valid values are:
PS> [Environment]::GetFolderPath("burp") Cannot convert argument "0", with value: "burp", for "GetFolderPath" to typ e "System.Environment+SpecialFolder": "Cannot convert value "burp" to type "System.Environment+SpecialFolder" due to invalid enumeration values. Speci fy one of the following enumeration values and try again. The possible enum eration values are "Desktop, Programs, Personal, MyDocuments, Favorites, St artup, Recent, SendTo, StartMenu, MyMusic, DesktopDirectory, MyComputer, Te mplates, ApplicationData, LocalApplicationData, InternetCache, Cookies, His tory, CommonApplicationData, System, ProgramFiles, MyPictures, CommonProgra mFiles"." At line:1 char:29 + [Environment]::GetFolderPath <<<< ("burp") + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
So let's try some of those values:
PS> [Environment]::GetFolderPath("cookies") C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\Cookies PS> [Environment]::GetFolderPath("mypictures") C:\Users\jsnover\Pictures
But wait - it's gets even better!
Now let's pull it all together by realizing that ENUM is a type and that it has statics as well use that to find all the folderpaths:
PS> [Enum] |gm -s
TypeName: System.Enum
Name MemberType Definition ---- ---------- ---------- Equals Method static bool Equals(System.Object objA, Syst... Format Method static string Format(type enumType, System.... GetName Method static string GetName(type enumType, System... GetNames Method static System.String[] GetNames(type enumType) GetUnderlyingType Method static type GetUnderlyingType(type enumType) GetValues Method static array GetValues(type enumType) IsDefined Method static bool IsDefined(type enumType, System... Parse Method static System.Object Parse(type enumType, s... ReferenceEquals Method static bool ReferenceEquals(System.Object o... ToObject Method static System.Object ToObject(type enumType...
PS> [Enum]::GetValues([System.Environment+SpecialFolder]) Desktop Programs Personal Personal Favorites Startup Recent SendTo StartMenu MyMusic DesktopDirectory MyComputer Templates ApplicationData LocalApplicationData InternetCache Cookies History CommonApplicationData System ProgramFiles MyPictures CommonProgramFiles PS> foreach ($f in [Enum]::GetValues([System.Environment+SpecialFolder])) { >> "{0,-20} - {1}" -f $f, [Environment]::GetFolderPath($f) } >> Desktop - C:\Users\jsnover\Desktop Programs - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\S tart Menu\Programs Personal - C:\Users\jsnover\Documents Personal - C:\Users\jsnover\Documents Favorites - C:\Users\jsnover\Favorites Startup - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\S tart Menu\Programs\Startup Recent - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\R ecent SendTo - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\S endTo StartMenu - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\S tart Menu MyMusic - C:\Users\jsnover\Music DesktopDirectory - C:\Users\jsnover\Desktop MyComputer - Templates - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\T emplates ApplicationData - C:\Users\jsnover\AppData\Roaming LocalApplicationData - C:\Users\jsnover\AppData\Local InternetCache - C:\Users\jsnover\AppData\Local\Microsoft\Windows\Tem porary Internet Files Cookies - C:\Users\jsnover\AppData\Roaming\Microsoft\Windows\C ookies History - C:\Users\jsnover\AppData\Local\Microsoft\Windows\His tory CommonApplicationData - C:\ProgramData System - C:\Windows\system32 ProgramFiles - C:\Program Files MyPictures - C:\Users\jsnover\Pictures CommonProgramFiles - C:\Program Files\Common Files
Is that cool or what?
Enjoy!
Jeffrey Snover [MSFT] Windows Management Partner Architect Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
hello,everyone here:
I have a question:
why powershell interpret "Environment.SpecialFolder" enum to "System.Environment+SpecialFolder"
Isn't it look strange?
another question:how powershell interpret .net EUNM type?
http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx
Thanks
PingBack from http://get-admin.com/blog/?p=212
Great post! As an admin it took me a very long time to grasp .net objects, and there subtleties. I really needed something like this a year ago! Get-Member is the hardest thing to convey to a new admin, but once they get it... windows administration is never the same!
That *is* cool, but I get this:
PS C:\Users\han\> [environment]::getfolderpath
MemberType : Method
OverloadDefinitions : {static System.String GetFolderPath(SpecialFolder folder)}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : static System.String GetFolderPath(SpecialFolder folder)
Name : GetFolderPath
IsInstance : True
The parameter to GetFolderPath is simply SpecialFolder instead of 'System.Environment+SpecialFolder'.
Could that be because I'm running CTP2?
@hans
> Could that be because I'm running CTP2?
No - it looks like someone refactored the class. "System.Environment+SpecialFolder" means that the class is defined within the System.Environment class. System.SpecialFolder is defined as a peer class to System.Environment. It shouldn't matter one way or the other - it should work the same.
Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
In my latest post Explore your [Environment] I said the following: PS> [System.Environment+SpecialFolder]
Hi Jeffrey,
it's really the GREAT post. Thanks a lot for that.
David
The sentence in the 5th paragraph "Most properties are methods that you deal with are OBJECT properties and methods which is to say that they are the "properties of THAT object" or the "methods that can be invoked on THAT object"." makes no sense.
I think what was meant was "Most Properties OR Methods that you deal with..."
Thanks for this post - I wish I'd seen this a couple of years ago. It would have helped me 'get' how PowerShell leverages .NET.
When I type a method without the "()" i get no response at all, just returns to the PS prompt. This looks like a really cool feature that I would like to explore. Anyone have any ideas why this doesn't work?
Re Macattack's question:
Omitting the () in a method call should return the method definition.
For example:
[system.int32]::tryparse (without the ()s) returns this, using CTP2:
OverloadDefinitions : {static System.Boolean TryParse(String s, Int32& result), static System.Boolean TryParse(String s, NumberSt
yles style, IFormatProvider provider, Int32& result)}
Value : static System.Boolean TryParse(String s, Int32& result), static System.Boolean TryParse(String s, NumberSty
les style, IFormatProvider provider, Int32& result)
Name : TryParse
I have the same issue as macattack:
PS>[Environment]::GetFolderPath
doesn't output the method signature
I just get the prompt. Not output at all.
@COnstantine:
Post the output of the following:
PS> [Environment] |gm -s g*
jps
@jps
Maybe it's because I'm use PS 1.
PS>"hello".CompareTo
...will give me a signature.
But I can's get signatures for static members except via the method you suggest:
Name MemberType Definition
---- ---------- ----------
GetCommandLineArgs Method static System.String[] GetCommandLineArgs()
GetEnvironmentVariable Method static System.String GetEnvironmentVariable(String variable), static System.Strin...
GetEnvironmentVariables Method static System.Collections.IDictionary GetEnvironmentVariables(), static System.Co...
GetFolderPath Method static System.String GetFolderPath(SpecialFolder folder)
GetLogicalDrives Method static System.String[] GetLogicalDrives()
get_CommandLine Method static System.String get_CommandLine()
get_CurrentDirectory Method static System.String get_CurrentDirectory()
get_ExitCode Method static System.Int32 get_ExitCode()
get_HasShutdownStarted Method static System.Boolean get_HasShutdownStarted()
get_MachineName Method static System.String get_MachineName()
get_NewLine Method static System.String get_NewLine()
get_OSVersion Method static System.OperatingSystem get_OSVersion()
get_ProcessorCount Method static System.Int32 get_ProcessorCount()
get_StackTrace Method static System.String get_StackTrace()
get_SystemDirectory Method static System.String get_SystemDirectory()
get_TickCount Method static System.Int32 get_TickCount()
get_UserDomainName Method static System.String get_UserDomainName()
get_UserInteractive Method static System.Boolean get_UserInteractive()
get_UserName Method static System.String get_UserName()
get_Version Method static System.Version get_Version()
get_WorkingSet Method static System.Int64 get_WorkingSet()
There is a known bug in PowerShell V1 where referencing a static method returned null instead of the method info. This was fixed for V2 and the fix is in the CTPs.
-bruce
------------------
Bruce Payette [MSFT]
I was hoping for an article that would tell me what string methods do, eg ToUpper vs ToUpperInvariant. And what parameters they required.
I guess I'll keep on looking.