With the New Year just ahead, this old paper makes great reading. Of course, as the blog post points out, this is not an official white paper and it’s no longer very accurate (and shows the very old syntax that we had in the early versions of MSH). But as a vision, writen in 2002, this paper is required reading.
It’s interesting that it’s taken nearly 6.5 years from that paper to CTP3, and we’re still 6-9 months (or more) away from V2 RTW/RTM. I’ve always sort of thought the pace of development in PowerShell was fairly quick. As the Grateful Dead sing: “What a long, strange trip it’s been”.
[WMICLASS] – a short cut to a WMI Class definition to enable access to the class’s static properties and methods. I describe this type accelerator below.
[WMISEARCHER] – a short cut to .NET’s ManagementObjectSearcher enabling you to search for objects easily. This type accellerator is an opportunity for a future article.
The [WMICLASS] type accelerator takes a string containing a relative or absolute path to an WMI class, and returns a a System.Management.ManagementClass object that represents the specified class (as opposed to an occurance of that class). For example let’s take a look at the Win32_Share WMI Class. First, look at what Get-WMIObject returns, then look at what the [WMICLASS] type accelerator returns:
In this example, you can see that Get-WMIObject returns System.Management.ManagementObject objects, while [WMICLASS} returns System.Management.ManagementClass objects – in other words, different object types with different members. I note that the MSDN library documentation does not really differentiate static and object members clearly – so you just have to know which is which when dealing with WMI classes.
The object occurrences returned from Get-WMIObject contain three methods: Delete, GetAccessMask and SetShareInfo. These three methods operate on a particular occurrence, i.e. Delete means “delete this occurrence”. However, the object returned from [WMICLASS} both contains none of those three dynamic methods, but does create a static method: Create, i.e. create a new share.
Why bother with [WMICLASS] you might ask. The answer is simple: to access the static methods and properties/fields that the class exposes. In the case of theWin32_Share class, the class has a static method (create) and three dynamic methods( delete, GetAccessMask and SetShareInfo). If you want to create a new share, then use [WMICLASS] to get access to the create method. You can get access to the Delete method by getting the appropriate method. This bit of code illustrates this:
<#
.SYNOPSIS
Demonstrates WMI and Win32_Share
.DESCRIPTION
This script looks at objects retured from Get-WMIObject, and [WMICLASS] and demonstrates
the use of a static method (create) and a dynamic or object method (delete).
.NOTES
Author : Thomas Lee - tfl@psp.co.uk
.LINK
http://www.pshscripts.blogspot.com
.EXAMPLE
Left as an exercise for the reader
#>
# Display shares at start
$start = get-wmiobject win32_share | where {$_.name -match "Foo"}
if ($start) {
"{0} foo shares at start, as follows:" -f $start.count;
$start}
else {"No foo shares"}
# Create a foo22 share
"";"Adding Foo22 share"
$class = [WMICLASS]'win32_share'
$ret = $class.create("c:\foo", "foo22", 0,$null,"Test Share Creation with WMI")
if ($ret.returnvalue -eq 0){
"Foo22 Share created OK"}
else {
"Share not created, error code: {0}" -f $ret.returnvalue
}
# Display results
"";"Foo shares now:"
get-wmiobject win32_share | where {$_.name -match "foo"}
""
# Delete the foo22 share
$del = Get-WmiObject win32_share | where {$_.name -eq "foo22"}
$ret = $del.delete()
if ($ret.returnvalue -eq 0){
"share deleted OK"}
else {
"Share not deleted, error code: {0}" -f $ret.returnvalue
}
# Display final results
"";"Foo at the end:"
$finish = get-wmiobject win32_share | where {$_.name -match "foo"}
if ($finish) {
"{0} foo shares at the end, as folllows:" -f $start.count;
$start}
else {"No foo shares at the end:"}
""
This sample, after the now obligatory Advanced Function help stuff, obtains and displays any shares on the local system that contain the string “foo”. Then, in line 24 the scripts gets the Win32_Share class, and in line 25 used the create static method to create a new share (Foo22). In line 39, the script deletes the newly added share, and finally prints out the remaining shares matching “foo”.
In summary, the [WMICLASS] gives you access to the static methods or members exposed by a WMI class.
Type Accelerators are a PowerShell feature that simplifies access to underlying WMI or .NET objects. Earlier this year I wrote two blog articles, the first about the WMI type accelerators and the second specifically about the [WMI] type accelerators. At some point, I intend to write about the other two ([WMICLASS] and [WMISEARCHER]) WMI related type accelerators.
In a most interesting Christmas Day post, Osin posted a detailed look at Type Accelerators within PowerShell CTP3. By using Reflector to look at the actual PowerShell code, you can see how PowerShell implements Type Accelerators, through using the TypeAccellerator class. Neat! But neater still, Osin shows how to make use of this technique to both list out the existing Type Accelerators as well as how to add more.
Here’s a simple function definition that returns the existing type accelerators:
I’ve been playing a lot with AutoHelp in PowerShell CTP3. Not sure if this is the official name, but Auto-Help enables you to decorate a script with help information. This information can then be read by Get-Help to provide help text back to a user of your script. From an enterprise, production scripting point of view, this is very cool and super useful. Production scripts should always be well documented. And for community generated scripts, having great help text will only aid other users trying to integrate these community scripts into their environment.
The auto-help information is specified inside a block comment at the start of your script. A bloc comment begins with “<# “ and ends with “#>”- everything inside these two character blocks is considered to be a comment. Here’s a very simple auto-help block:
<#
.SYNOPSIS
Cool Script
.DESCRIPTION
No really. It's really really cool"
.NOTES
Author : Thomas Lee - tfl@psp.co.uk
.LINK
http://tfl09.blogspot.com
#>
"The meaning of life, the universe and everything is {0}" -f 42
You can of course run this script, and it'll produce a predicable output. BUT, if you save it, say as truth.ps1, you can then run Get-Help against it, with output as follows:
REMARKS To see the examples, type: "get-help C:\Users\tfl\AppData\Local\Temp\Untitled19.ps1 -examples". For more information, type: "get-help C:\Users\tfl\AppData\Local\Temp\Untitled19.ps1 -detailed". For technical information, type: "get-help C:\Users\tfl\AppData\Local\Temp\Untitled19.ps1 -full".
DETAILED DESCRIPTION No really. It's really really cool"
PARAMETERS <CommonParameters> This cmdlet supports the common parameters: -Verbose, -Debug, -ErrorAction, -ErrorVariable, -WarningAction, -WarningVariable, -OutBuffer and -OutVariable. For more information, type, "get-help about_commonparameters".
I’ve been doing some digging into this feature. The CTP3 release notes make mention of the various sections that help reports. I’ve built a sample script with what I think to be all the section names used. The idea being that this basic script can be used to demonstrate get-help in all its glory. However, what I’ve discovered is a great idea, but with some challenges.
First, here’s my sample auto-help demo script:
<#
.SYNOPSIS
A summary of what this script does
In this case, this script documents the auto-help text in PSH CTP 3
Appears in all basic, -detailed, -full, -examples
.DESCRIPTION
A more in depth description of the script
Should give script developer more things to talk about
Hopefully this can help the community too
Becomes: "DETAILED DESCRIPTION"
Appears in basic, -full and -detailed
.NOTES
Additional Notes, eg
File Name : Get-AutoHelp.ps1
Author : Thomas Lee - tfl@psp.co.uk
Appears in -full
.LINK
A hyper link, eg
http://www.pshscripts.blogspot.com
Becomes: "RELATED LINKS"
Appears in basic and -Full
.EXAMPLE
The first example - just text documentation
You should provide a way of calling the script, plus expected output
Appears in -detailed and -full
.EXAMPLE
The second example - more text documentation
This would be an example calling the script differently. You can have lots
and lots, and lots of examples if this is useful.
Appears in -detailed and -full
.INPUTTYPE
Documentary text, eg:
Input type [Universal.SolarSystem.Planetary.CommonSense]
Appears in -full
.RETURNVALUE
Documentary Text, eg:
Output type [Universal.SolarSystem.Planetary.Wisdom]
Appears in -full
.COMPONENT
Not sure how to specify or use
Does not appear in basic, -full, or -detailed
Should appear in -component
.ROLE
Not sure How to specify or use
Does not appear in basic, -full, or -detailed
Should appear with -role
.FUNCTIONALITY
Not sure How to specify or use
Does not appear in basic, -full, or -detailed
Should appear with -functionality
.PARAMETER foo
The .Parameter area in the script is used to derive the contents of the PARAMETERS inGet-Help output which
documents the parameters in the param block. The section takes a value (in this case foo,
the name of the first actual parameter), and only appears if there is parameter of that name in the
params block. Having a section for a parameter that does not exist generate no extra output of this section
Appears in -det, -full (with more info than in -det) and -Parameter (need to specify the parameter name)
.PARAMETER bar
Example of a parameter definition for a parameter that does not exist.
Does not appear at all.
#>
# Note above section does not contain entries for NAME, SYNTAX and REMARKS sections of in get-help output
# These sections appear as follows:
# NAME - generated from the name passed to get-help.
# SYNTAX - generated from param block details.
# REMARKS - generated based on script name (e.g. what's shown in NAME) inserted into some static text.
#
# Not sure how to generate/document -component, -role, -functionality
# Not sure how to generate/use -category
param (
[Parameter(ParameterSetName='Wisdom')]
[int64] $foo=42
)
$foo=42
"The meaning of life is $foo!"
If you take this script (I’ll post it shortly to http://pshscripts.blogspot.com) and save it away as get-autohelp, you can then run auto-help against it.
While this works really well, there are a number of issues with CTP3:
1. Put a #Requires –Version 2.0 at the top of the script and the script does not work with get-help. You just get the syntax block and nothing else.
2. In get-help’s output In the REMARKS section, the 1st line says: To see the examples..." but the examples are there just above? Maybe this should say: “To just see the Examples look above or type -examples”
3 There is no blank line in the output before “REMARKS”- sloppy output.
4. Running Get-help – in the output in the remarks section says ‘to get more informaiton used –detailed. Well – DUHH – I just did!
5. Get-Help adds two extra blank lines between the mini-header and an example – for each example.
6. Get-Help’s –online parameter seems to not work.
7. You can not specify a .NAME section in auto-help. If you do, then the output returned by get-help is heavily truncated. You should enable the developer to specify a name section, with Get-Help then supplementing this with the file name that the script lived in.
8. Two sections change name from script file to output by Get-Help. The ".DESCRIPTIION" section becomes "Detailed Description" in get-help output. And .LINK befomes "RELATED LINKS. This is inconsistent. Either make Get-Help produce the section names in the file, or change what sections you can specify in the file to match what get-help produces.
9. The links in the .LINK section are shown in basic get-help output, and with -FULL, but not -Detailed. This is inconsistent - anything shown in basic output should be shown with -full AND -detailed.
10. It's not clear how to use .COMPONENT, .ROLE and .FUNCTIONALITY sections. These do not appear to be output in any use of get-help. If nothing else, there needs to be more details on these sections.
11. Adding any new section into the comment block, and the get-help output is truncated as in 1.
Auto-Help is a great feature. But it needs some more work.
Looking at the MSDN Library site tonight and I noticed a new “Feature Spotlight” – point to a new site that enables you to search for code inside MSDN. The site enables you to search for code, and if you find something of interest, you can book mark it, or create a unique URL to the appropriate page. It’s clearly early days for this site. You can’t yet search for code on the MSDN Forums, the MSDN Code Gallery or Codeplex.
Another downside – under Language, there’s no PowerShell. There’s Perl and Ruby and Python and C++ and C#, etc – but no PowerShell. :-( You can filter on PowerShell and find some PowerShell related code. Shame no one in MSDN recognises PowerShell as a language!
I’ve been reading Jeffrey Snover's discussions on ENUMs over on the PowerShell Team blog (here, and here). I knew most of this stuff and have been playing with Enums and PowerShell for a while. I’ve created a bunch of sample scripts I’ve uploaded both to the MDSN Wiki and to my PowerShell Scripts blog. This morning, I stumbled upon an interesting use of Enums – parsing strings into Integer values, as shown on the MSDN Library at http://msdn.microsoft.com/en-us/library/system.globalization.numberstyles.aspx.
Effectively want I wanted to do was to convert the following C# code to PowerShell:
// Parse the string, allowing a leading sign, and ignoring leading and trailing white spaces.
num = " -45 ";
val = int.Parse(num, NumberStyles.AllowLeadingSign |
Console.WriteLine("'{0}' parsed to an int is '{1}'.", num, val);
Initially, I could not work out how to use the enums (In System.Globalization.NumberStyles). Thanks to Shay Levy, it turns out to be remarkably easy (although not quite as succinct as in C'#). Basically, in true PowerShell style, every enum value is just an object. Objects have properties, and one property of an enum value is “value__” as demonstrated here:
As you can see from this output, the enum [System.Globalization.NumberStyles]::AllowLeadingSign displays normally the value “AllowLeadingSign” , but if you use the .value__ property on this enum value, you get back a number – in this case a decimal 4 (0x0004). You can then combine these as follows to convert the above C# Code into PowerShell:
Thanks to Shay Levy for his post in the PowerShell newsgroup for helping me to work this out. FWIW: you can the results of this up on the MSDN Library and on my PowerShell Scripts blog.
Today is Christmas day and I’m away from the computer, enjoying Christmas dinner with my wife and daughter – I’m off the grid! As is our tradition, we’ll start with a nice bottle of Champagne and some smoked salmon. Then a bottle of Opus 1, with some cold roast duck, along with roasted turkey and roasted boneless chicken. We’ll finish up with some pudding and a nice bottle of vintage port. If anyone’s in the area and is not driving, they would be most welcome – I’d be happy to open up another bottle or two should that prove needed!
And for the real hard-core PowerShell Addict, I’ll be posting tomorrow with some interesting stuff I discovered about using Enums and .NET. Stay tuned.
The lab, which lasts up to 2 hours 50 minutes, covers the following topics:
PowerShell Variables
Branching and Script Blocks
Looping, Functions, and Filters
WMI Scripting
.NET Forms with Windows PowerShell
Visual Basic scripting functionality within PowerShell
PowerShell and Active Directory Domain Services
PowerShell scripting to reset a ADDS user password
Remote management using PowerShell
If you are unfamiliar with PowerShell, or if you want to dig a bit deeper into some of these areas, then head on over. It takes a minute or two for the TechNet Virtual Lab to come up, but once it does, you’re presented with a screen like this:
This lab is based on PowerShell 1.0 (although everything in the lab should work fine with PowerShell V2.0).
Now this is neat - Tweet Grid, a page that shows recent posts about PowerShell, side by side with CTP3. It looks like this:
The page auto updates, so you can see new Tweets as they come in. I will be using this page a lot over the coming days to monitor the Twitter-sphere reaction to CTP 3.
One minor issue – the right hand pane is searching just for the phrase “CTP3” – which could also be some other product, or a part of a URL. While most tweets are relevant, a few aren’t. A slightly improved URL is here.
Well –this is cool and a tad unexpected. In a recent post, I noted that I’d heard PowerShell had been delayed till the new year. Well, that’s WRONG. It released last night, as explained over on the PowerShell Team blog.
If you are a clustering person, you should check this article out – it documents that the team will deliver over 60 cmdlets to manage clustering. There will also be a custom console, as shown in the blog article.
It looks like the Windows team(s) now finally get PowerShell!
If you are in to Twitter, and into PowerShell –here's a list of PowerShell Twitterers. It appears to be relatively up to date! The list was created by Steven Murawski, a US based PowerShell guy.
Jaykul has created a pretty cool Yahoo Pipe application (PowerShell Bloggers). However, today it seems to be not working – I am getting the error message: The Pipes engine request failed (504). :-(
This is a shame as the application is pretty useful in keeping up with PowerShell bloggers. Hopefully it will get fixed soon.
[Later]
It’s now working again! And along with it is the news that today should see CTP 3! Yeah!!
Microsoft has published a number of White Papers on various aspects of Windows 7 (including Windows Server 7). These White papers come from Microsoft’s Windows Hardware Engineering Conference (aka WINHEC). You can get the papers here.
If you are posting PowerShell code sample and want to format the text nicely, there’s an on-line high-lighter tool that will do this for you available here.
# Parse and TryParse static methods on Int64 type
# Sample using PowerShell
# Thomas Lee - tfl@psp.co.uk
# Create an int64 and two strings
$i=new-object system.int64
"varable `$i created - type is {0}" -f $i.GetTypeCode()
$s1="1234"
$s2="12345678934212321212"
# Use the Parse static method on S1 that WILL work OK
$i=[system.int64]::parse($s1)
"The integer `$i={0} - parsed OK as Int64" -f $s1
""
# Use the TryParse static method with small and too large a number
$result=[system.int64]::tryparse($s1,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s1,$result
$result=[system.int64]::tryparse($s2,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s2,$result
"Variable `$i created - type is {0}" -f $i.GetTypeCode()
$s1="1234"
$s2="12345678934212321212"
# Use the Parse static method on S1 that WILL work OK
$i=[system.int64]::parse($s1)
"The integer `$i={0} - parsed OK as Int64" -f $s1
""
# Use the TryParse static method with small and too large a number
$result=[system.int64]::tryparse($s1,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s1,$result
$result=[system.int64]::tryparse($s2,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s2,$result
The Highlighter tool can create the HTML fragement with or without a link to a CSS style sheet. In using this tool with Live Writer to produce this blog posting there seems to be little difference. To demonstrate this point, here’s the code without a CSS link:
# Parse and TryParse static methods on Int64 type
# Sample using PowerShell
# Thomas Lee - tfl@psp.co.uk
# Create an int64 and two strings
$i=new-object system.int64
"varable `$i created - type is {0}" -f $i.GetTypeCode()
$s1="1234"
$s2="12345678934212321212"
# Use the Parse static method on S1 that WILL work OK
$i=[system.int64]::parse($s1)
"The integer `$i={0} - parsed OK as Int64" -f $s1
""
# Use the TryParse static method with small and too large a number
$result=[system.int64]::tryparse($s1,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s1,$result
$result=[system.int64]::tryparse($s2,[ref] $i)
"The string `"{0}`" parsed correctly as an int64: {1}" -f $s2,$result
Sadly, I don’t speak Czech – if I did, the PowerShell CZ blog would be more useful. Nevertheless, some of the articles are clear enough to PowerShell folks – just look at the code posted in the article. I tried the translator at www.tranexp.com, but the results were not very good.
Maybe the author could be persuaded to translate into English?
In an article posted during TechEd Barcelona, I suggested that PowerShell CTP 3 was coming “soon”. The statements from the MS folks suggested that “soon” would be “early December”. I joked last week that I did not ask which December. :-)
I can see from hits to this blog that many folks are trying to find this update or more information on it. I’m sorry to disappoint those visitors to this blog, but it looks like CTP 3 is delayed (again). I’m now hearing on the grapevine that CTP3 will not now come this year, but will come sometime in January in concert with the Windows 8 beta.
Of course, this information could be wrong too. MS could decide to release it today (if only to prove this post wrong).We will just have to wait and find out. I’m accurate, then you heard it here first. And if I’m wrong, well, this blog post is just one more in a set of unsubstantiated and incorrect rumours about when CTP3 will hit. :-)
But whatever, I know two things. First, CTP3 will rock whenever it’s released. Second, no matter how late, CTP3 is worth waiting for. I also recognise that despite being very late, PowerShell Version 2 is really going to be a world beating release. I can’t wait. I’ll be posting a lot more both here and on my PowerShell Scripts blog as soon as the new release if available.
Like many techies I know, I use Windows Server 2008 as my main workstation OS. I find it much more stable than any other MS OS, with none of the consumer gimmicks of Vista. I am very happy with using Server 2008 – I get all the useful features of Vista, plus I get key features like Hyper-V, SMTP Server, and DFS. It rocks! My new laptop (due “soon”) will also be tricked out this way!
As an aside, I think there’s a market here for a workstation class OS – in effect what I have running now. Tools like DFS, or more importantly Hyper-V are are needed for a small but important set of users. A workstation OS would put (client) Windows on a better footing against Linux/Unix OSs which allow these sorts of tools. Instead of having upteen home versions of Win7, why not have a Windows 7 Professional Workstation edition? Slug it with limited inbound connections (say 25 vs 10 for client), and don’t allow some features like being a DC. You could even call this Windows 7 Ultimate and have the term “ultimate” actually mean something other than just being misleading marketing waffle.
One of the (very few!) problems I’ve had up to now is that Windows Live Writer and Windows Live Messenger did not install since the OS version is not supported. I really like Live Writer, and use it on all three of my blogs (here, here and here) as the main tool for adding blog posts.
On Sunday, on the very long flight from Bangalore back home (an 11 hour flight, with two unscheduled stops was 11 hours late into LHR!), I had a brain spark. I guess 5 hours on the ground in Baku with no drink or food tends to do that! The idea was very simple: just use the compatibility tab on the program installer and tell the OS to lie to the installer as shown here:
After selecting Windows XP SP2, click OK and then run the setup program. On my system, it took another 2-3 minutes and I now have Live Messenger and Live Writer working perfectly.
Thanks to the Application Compatibility team at Microsoft for helping out!
This week, Jeffrey Snover has posted an excellent post, Explore Your [Environment], that examines both some of the details of the [System.Environment] class but also on how PowerShell integrates with .NET. As I said in a comment on the blog, I wish I’d seen this post many years ago, as I struggled in the early days to understand how you could reach into .NET with PowerShell.
As Jeffrey describes, the .NET class has thousands of types, or types of objects. For example, System.Int32, a 32-bit integer. To access this type in Powerhell, simply enclose the type name in square brackets, as follows:
PS C:\Users\tfl> [system.int32]
IsPublic IsSerial Name BaseType
----------------------------TrueTrue Int32 System.ValueType
You can also pipe the class to Get-Member to discover some of the properties and methods this type supports, as follows:
As you can see, the System.INT32 class has a number of methods and properties. A method is something you can invoke to do something on the object, for example ToString() produces a string representing the value of the system.int32. A property is some attribute of the type, for example Name which is the name of the object. Within .NET there are two types of methods: static and object. Object methods are methods that you can invoke on a particular occurrence of a type. The ToString() method, for example, converts a specific System.Int32 to a string while TryParse() takes a value and sees if it will fit inside a 32-bit integer vaue. Static methods are methods that the class provides but that are not tied to a specific instance of a class. Classes can also have static fields, or values you can use in a PowerShellscript. In the case of system.int32, there are two static fields MaxValue and MinValue.
Here is a look at the TryParse static method, the ToString object method, plus the two static fields.
To see the static methods, object methods and object properties, you can use Get-Member or for fuller information, see the MSDN Library documentation on-line. To find this imploration simply, just Google for the type name (enclosed in square brackets) – this should show a link to the class definition as the first result, from which you can drill down to see more details about the class.
I’ve been writing about WMI and PowerShell of late – and notices this cool PowerShell Audit Script on Alan Renouf’s Virtu-Al’s blog. It’s not a particularly new post, but the result if pretty awesome. It produces a nice rich HTML file as output that looks a bit like this:
A great demonstration of what you can get from WMI plus what you can do with HTML in PowerShell
For those of you who like podcasts and PowerShell, take a look at the PowerScripting Podcast site. These podcasts are primarily all about PowerShell and air weekly. The last episode (their 50th!!) featured Ed Wilson, who wrote PowerShell Step-by-Step.
You can listen to them online. Or you can do as I do and subscribe to them and get them downloaded to my Zune (or your IPOD via I-Tunes). Using my Zune software, I just add the feed from http://feeds.feedburner.com/PowerScripting. I’ve got the last few podcasts loaded up and will be listening to them on my long flight to India.
I just got a Google alert showing where I could download a free copy of the Windows PowerShell Scripting Guide. However, the download contains a Trojan!
Be careful and avoid http: //download-apps.net/2008/11/28/windows-powershell-scripting-guide.html.
[Later]
Thanks to Halr9000, who noted that Blogger had "helpfully" added in a hyperlink to the above content. Hyperlink now gone.
The key thing for IT Pros to understand is that WMI is both a friend and other folks’ friend. What I meant by that is that WMI was built to be an interface. And for Microsoft, that means developer focused. WMI was the way for one application to surface management information and for other applications to leverage that information. This enables tools such as SCCM (aka SMS) to do such cool things.
But with PowerShell, the various classes of information are but a simple command away. The key is the GET-WmiObject cmdlet. This cmdlet enables you to retrieve any WMI class and access both its properties and methods and that means considerable power. PowerShell also provides WMI type accelerators, such as [WMI] that further simplify the use of WMI.
So how does an IT Pro get started. The first thing, I suppose is to understand how WMI is structured. To simplify, WMI is implemented on a host. On that host, there is a set of information that is organised with a hierarchical namespace which breaks up the information in a structured manner. In each Node of the WMI namespace, you’ll find a number of classes. Each class has a definition (what it should/can contain) and instances. Each instance of a class represents a real-world occurrence of that object. The class and hence the instance contains properties and methods. You can use the properties for reporting and can also update the values of these properties for any instance (and create and manipulate new instances). Instances (and the class) contain methods that you can call to get an instance to do something. The details of the namespaces, classes, properties and methods are described on MSDN.
With PowerShell, however the best place to start is with MOW’s most excellent WMI Explorer. This tool is incredibly cool. First, because it’s written all in PowerShell, but more importantly, because it’s the best browser I’ve seen. It’s a big PowerShell script – when you run it, you can open WMI on a system and browse the namespaces. In each namespace node you can look at the classes in that node. And for each class, you can simply see both the existing instances as well as the definition of that class. Here’s a screen shot of this tool running on one of my workstations:
As an IT Pro, you should download WMI Explorer and explore. I’ll be posting more on WMI and PowerShell coming up.
I saw an interesting item over on the PowerShell newsgroup today. The poster was using Get-Process on an X64 system and was seeing negative numbers in the Working Set column against the SQL Server. The answer was a simple one, as it turns out.
The Get-Process cmdlet returns [System.Diagnostics.Process] objects, but with some added members – the cmdlet in effect expands the objects for PowerShell. Specifically, the Cmdlet adds 6 Alias Properties that are aliased to other properties in the [System.Diagnoistics.Process] Class:
Handles = Handlecount
Name = ProcessName
NPM = NonpagedSystemMemorySize
PM = PagedMemorySize
VM = VirtualMemorySize
WS = WorkingSet
This makes life easier for the admin who can use the shorter Alias property names, et:
$process = “*SQL"*” GPS $process | ft name, ws -auto
The reason the poster was seeing negative numbers is fairly simple: the WS property is aliased to WorkingSet, but WorkingSet is a 32-bit value. In the poster’s case, the working set size overflowed the 32-bit value, resulting in a negative number being displayed. The solution is fairly simple if you look at the class’s Property details: use a different property which contains a 64- bit value. The class has several 64-bit properties:
NonpagedSystemMemorySize64
PagedMemorySize64
VirtualMemorySize64
WorkingSet64
So the solution was easy – just use:
$process = “*SQL"*” GPS $process | ft name, workingset64 –auto
The maximum size of an Int32 is 2**32, meaning the maximum size of the WS/WorkingSet property is 4GB. Thus this problem can never occur on an I386 system since on i386, processes have a maximum size of 4GB, But as x64 becomes more common, and from Server 2008 R2 becomes the norm, this problem will grow.
Interestingly, in the API documentation MIcrosoft now state that the 32-bit values are obsolete. You could argue this is a bug in PowerShell. For PowerShell V2, Microsoft really should change the WS and other AliasProperties to alias the 64-bit properties. For CTP2, this has not been done.
Microsoft as announced the availability of Open XML Document viewer plug-in for FireFox. This provides a light-weight way to view OOXML document (i.e. .docx, .xlsx, etc) documents from within FireFox.
These plugins are available from Codeplex at: http://www.codeplex.com/OpenXMLViewer. This page has a good description of the high level architecture, a cool-ish 4-minute video demo of the translation and the FireFox plugins. There’s also a link to the download, including viewers for Windows and Linux versions of FireFox.
The Windows download is fairly big – 3.5MB – indicating the complexity of the underlying code. To install the plugin, just expand the .ZIP download and drag/drop the XPI to FireFox, restarting FireFox to complete the installation. After installation, it looks like this:
The viewer is a CodePlex project (and not a formal Microsoft project), and the videos are YouTubed not available directly from Microsoft. An interesting approach – pragmatic to say the least (plus google gets to pay for the bandwidth used to view the videos).
Also, these viewers are at present just a Community technology Preview and not fully ready for release. Final release will come in the spring of 2009.
Buck Woody presented a session at the recent PASS conference on PowerShell and SQL. Entitled “Advanced PowerShell for SQL Server”, the session looked at using PowerShell with SQL Server 2008. The presentation also included a bunch of demos of how to integrate PowerShell with SQL Server 2008.
Buck has published a blog article about the talk, which includes a link to a download. The download contains the slides and two cool demo scripts. I’m going to try to get a SQL Server 2008 VM built to test these scripts out (and derive a few more).
In yesterday’s post, I described a cool Zip file Library from ICSharpCode and showed how you could use it within PowerShell. I noted it had a help file which would be of value when using this library. I spent some this morning playing with the Zip lib and wanted to see more details (i.e. from the help file).
However, when I started playing with the help file, I just got lots of blank pages and no content – like this:
It It took me a few minutes to work out that it was Windows “helping” me by not showing any content since the file had been obtained from the Internet! The file was downloaded by Firefox and FireFox (like IE) adds a NTFS stream to the file to indicate it had been downloaded from the Internet. Since the file had been downloaded, IE rendered nothing on security grounds. Thanks but…
With PowerShell, you can access the very wide range of objects from the .NET class libraries. This means you can access directly the functionality provided by the methods in these various objects. Dave Donaldson posted his discovery of this in his article Running .NET Code from PowerShell Scripts. Old PowerShell hands (and readers of my script blog are familiar with this. I find it pretty cool that you can reach into .NET to use it’s features directly in your PowerShell scripts.
With this library, you can easily create and manipulate zip files. I’ve used this in a script I’ve developed that zips up the script files in my PowerShell Script library and uploads them to http://www.reskit.net/powershell/scriptlib.zip). I’ll publish the full script once I finish it off!
To show the use of this external library here’s the basic bit of script I use to create the zip file:
# First, load the zip library[void] [System.Reflection.Assembly]::LoadFrom("C:\foo\bin\ICSharpCode.SharpZipLib.dll")
# Now create a new zip file object$zip= new-object ICSharpCode.SharpZipLib.Zip.FastZip
# Define what to zip and from where$zipfile="C:\Foo\PSScriptLib.Zip"$zipfrom="E:\PowerShellScriptLib"$recurse="true"$ziptoadd=".ps1"# Now create the zip file$zip.CreateZip($zipfile, $zipfrom, $recurse, $ziptoadd)
ls $zipfile
This script first loads the library using System.Reflection.Assembly. Once the assembly is loaded, we create a new object representing a zip file. The script then defines what to zip, and where we to put the zip file. Then we use the CreateZip method to add all the .PS1 files in E:\PowerShellScriptLib (and below) into the zip file that ends up in C:\Foo\PSScriptlib.Zip. The script finishes by performing a directory listing of the newly created zip file.
Running this bit of code produces something like this:
PS C:\foo> .\ZipScriptLib.ps1'
Directory: Microsoft.PowerShell.Core\FileSystem::C:\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 11/30/2008 11:37 AM 51816 PSScriptLib.ZIP
Of course, that’s only the first step. I’ll need to use the SharpZipLib to add a “readme” file to the archive and I’ll need to upload the zip file to my web site. I’ll cover these aspects in a later blog post!
As I noted in two recent blog articles (here and here), Network Protocol Specialists are running a series of WireShark Quick Start webcasts. The second session is to be held tomorrow, December 3 at 10:-00 PDT (Or 18:00 in the UK and 19:00 CET).
I am hoping that, like the last session, that this web cast is recorded for later download since I can’t make the webcast! To get the download link for the last session (and presumably the link for downloading the 2nd session), send email to: info@nps-llc.com.
In the recent UK TechNet Flash email, I see that Microsoft are promoting a PowerShell Webcast: Introduction to Windows PowerShell. It will take place on Monday December 8 at 11:30 PST, for 19:30 UK time. Sadly, I’ll be in India that week and am not likely to want to stay up late to watch it – hopefully it’ll be recorded for later download.
The event is billed as level 200, so will be fairly basic in terms of depth. The event overview is not clear on how much Version 2 will be discussed – but by the date of the webcast, we hopefully will have the next CTP of PowerShell V2 (so I hope the talk is V2 focused).
If you don’t now much about PowerShell, then try to watch the webcast live.