One of the first question on the microsoft.public.windows.powershell newsgroup was "What is Windows PowerShell?".

Windows PowerShell is a new Windows command shell, designed to provide a new, more flexible, more powerful command shell than the current Windows command shell based on CMD.exe. It is designed to produce a more efficient command line experience for Windows administrators and power users.

Windows PowerShell is based on the .NET Framework. It uses object-based pipelines to allow you to combine commands to produce useful results.

Windows PowerShell is also a powerful scripting language. It uses cmdlets (pronounced command-lets) which can be composed in pipelines. Each step in a pipeline is separated by the | character. For example, to find all running services on your machine use the following command:

get-service | where-object {$_.status -eq "running"}

This pipeline has two steps. In the first step you use the get-service cmdlet to retrieve information about all services on the local machine. In the second step you use the where-object cmdlet to filter the objects from the first pipeline step. The code in the curly brackets, {$_.status -eq "running"}, tests whether the value of the status property of the current object, $_, equals running. If it does then the object is passed to an implicit third step in the pipeline which displays the results. Objects whose status property does not equal running are discarded.
Pipelines can have many steps to, for example, allow you to filter, sort, group objects.

Results can be displayed using the default formatter or you can take more control of how output is displayed by using formatting cmdlets such as the format-table and format-list cmdlets.

There is now a functioning Windows PowerShell public newsgroup.

It's called microsoft.public.windows.powershell.

It's on the msnews.microsoft.com news server.

Point your newsreader and start reading and posting!

Naming clashes are something I expect to increase in frequency when PowerShell starts to be used more widely. I thought I would show you how to solve some categories of naming clashes. I will deal here with some of the situations that can arise when naming functions using names similar to cmdlets, that is verb-noun.

The situation can, potentially, become really complex so I will deal in this post only with some simple situations.

The name of a function can clash with an existing alias or cmdlet name. As an example consider what happens if you have written a function called rename-item. If you've been reading recent posts on this blog you will know that PowerShell has a rename-item cmdlet.

Assume that you have opened a fresh PowerShell console window.

If you type rename-item at the command line then you see a prompt

PS C:\> rename-item

cmdlet rename-item at command pipeline position 1
Supply values for the following parameters:
Path:

PowerShell prompts you to supply a value for the Path parameter.

Press Ctrl+C to stop this.

At the command line type the following to create the rename-item function:

function rename-item{

write-host "This output is from the rename-item function"

}

Then type at the command line:

rename-item

You will see an appearance like this:

PS C:\> rename-item
This output is from the rename-item function
PS C:\>

By creating a function called rename-item you have, effectively, blocked execution of the rename-item cmdlet at the command line.

Why does this happen? PowerShell attempts to find an executable to match a command in the following order:

  1. Aliases
  2. Functions
  3. Cmdlets
  4. Executables
  5. Scripts
  6. Normal files

So when you created the rename-item function it takes precedence over the rename-item cmdlet.

If you want to be sure to have access to the rename-item cmdlet avoid creating a global function with that name since the function will always have higher priority than the cmdlet.

If you've been using Monad betas before the release of PowerShell RC1 you quite possibly have a significant number of scripts that you wrote using the Monad betas. Those files will have a .msh file extension. When you upgrade to PowerShell, apart from any changes you need to make to the content, you need to change the file extension to .ps1.

In the good old Windows command shell, doing that is straightforward. Simply navigate to the folder holding the scripts. Then use the following command:

ren *.msh *.ps1

If you try that with Monad you receive the following error:

PS C:\PowerShellScripts> ren *.msh *.ps1
Rename-Item : Cannot process argument because the value of argument "path" is invalid. At line:1 char:4
+ ren <<<< *.msh *.ps1

So, what's wrong with the path? To figure that out I will show the command in a full form:

ren -Path *.msh -NewName *.ps1

The error relates to the value of the Path parameter. It accepts wildcards in the path but it must resolve to a single file.

So how do you use PowerShell to rename multiple files?

PowerShell is designed to use pipelines. And you need a two step pipeline to get the job done. Assuming you are in the directory that contains the files that you want to rename, use the following command:

get-childitem -Path *.msh |

rename-item -NewName {$_.name -replace ".msh",".ps1"} -whatif

As you can see it's a pipeline with two steps. The first step uses the get-childitem cmdlet to retrieve information about all files in the current folder with a .msh file extension. The second step uses the rename-item cmdlet to process each object passed on from the first step. Each object is a FileInfo object. The value of the Extension property of each FileInfo object is .msh, as you can see by using the following command:

get-childitem *.msh |

format-table Name, Extension

The value of the NewName parameter is {$_.name -replace ".msh",".ps1"}. Any occurrence of .msh in the value of the Name property of the current object is replaced by .ps1.

To put it more succinctly, all files with a file extension of .msh are renamed to have a file extension of .ps1.

In Windows Explorer you can rename the current folder. The rename-item cmdlet doesn't allow you to rename any folder.

The example I showed used the FileSystem provider. You can use the rename-item cmdlet to rename items in other providers, for example the alias and variable providers. To display available providers use this command:

get-PSDrive

The get-PSDrive cmdlet has replaced the get-drive cmdlet which was found in public builds before RC1.

The core release of Windows PowerShell, currently available as Release Candidate 1, has 129 cmdlets.

Exchange Server 2007 due for release in the fourth quarter of 2006 has about 350 cmdlets specific to its needs.

The Exchange team has given lots of useful introductory information about PowerShell in Exchange 2007 in two webcasts.

In the first webcast Brad Clark covered The Improved Exchange System Manager for Exchange “12”.

In the second Vivek Sharma described Exchange Server 2007 Management Shell and Scripting.

You will need a Microsoft Passport account or Live ID to register to view or download the recorded webcasts.

Note: The webcasts refer to PowerShell by its old code name "Monad".

When you use the get-wmiobject cmdlet to retrieve properties of a Windows Management Instrumentation, WMI, class you can be overwhelmed by the number of properties displayed. Among the properties displayed when you use an asterisk wildcard with the format-list cmdlet,

get-wmiobject -Class Win32_BIOS |

format-list *

are the WMI system properties which you probably don't want to see. You can use a more specific wildcard with the format-list cmdlet to filter the properties displayed.

If you want to display properties about the BIOS of your machine you might use the command but exclude the WMI system properties use this command:

get-wmiobject -Class Win32_BIOS |

format-list [a-z]*

How does this work? The first step of the pipeline uses the Win32_BIOS WMI class to pass its properties to the second step of the pipeline. The format-list cmdlet formats the output as a list, but which properties are to be displayed?

The [a-z]* is an extended wildcard. It's partly a traditional wildcard and partly like a regular expression. The [a-z] is a character class. It matches any lower case alphabetic character between a and z. The * matches zero or more characters. Taken together the wildcard means "Match any sequence of characters that begins with an alphabetic character".

You can use more focussed wilcards. To retrieve the properties beginning with s use this command:

get-wmiobject -Class Win32_BIOS |

format-list s*

The pattern s* matches any sequence of characters where the first character is s.
Technorati Profile

Newsgroups are a great way of staying up to date about many Microsoft topics. There are about 2,000 public newsgroups on the microsoft.com servers.
At the moment, discussion of Windows PowerShell takes place on the microsoft.public.windows.server.scripting newsgroup.

The news server is news.microsoft.com.

If you haven't used newsgroups before you can use Outlook Express which is installed with many flavours of Windows. There are many other newsreaders, such as Thunderbird and Agent.

A new newsgroup, specific for Windows PowerShell, is likely to be available later this month or next month. Once the new newsgroup is up and running I will post a pointer to its location.

Follow

Get every new post delivered to your Inbox.