Hey, Scripting Guy! Tell Me About PowerShell Community Extensions

Hey, Scripting Guy! Tell Me About PowerShell Community Extensions

  • Comments 3
  • Likes

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! What can you tell me about PowerShell Community Extensions?

-- KH

 

Hey, Scripting Guy! Answer

Hello KH,

Microsoft Scripting Guy Ed Wilson here. Probably the best person to answer your question is Keith Hill, our guest blogger today.

Image of Keith Hill, today's guest blogger

About the guest blogger: Keith Hill is a five time Windows PowerShell MVP. He has a Master’s degree from the University of Colorado at Boulder in Electrical and Computer Engineering, and he has worked for Hewlett-Packard and the spinoff Agilent Technologies for 23 years. During the past 17 years, Keith has worked on various commercial software products including Agilent VEE, a "visual" data flow programming environment for scientists and engineers. Outside of work, Keith enjoys playing guitar, riding his dirt bike, and coordinating the open source project PowerShell Community Extensions on CodePlex. He also writes a Windows PowerShell blog.

Windows PowerShell has proven to be a very capable command-line shell and scripting engine for Microsoft Windows. However, given Windows PowerShell’s relatively recent arrival on the scene, it is missing functionality commonly found in other shells. The development team at Microsoft realized this would be the case and provided mechanisms by which the community and ISVs could extend Windows PowerShell to fill in some of the missing functionality.

PowerShell Community Extensions (PSCX) is one such project that provides utility functionality along the lines of Cygwin. That is, PSCX aims to provide general purpose commands for both system administrators and software developers. This post discusses the recent 2.0 release of PSCX, which targets Windows PowerShell 2.0. If you are still on Windows PowerShell 1.0, much of this functionality is available in the PSCX 1.2 release. Both versions of PSCX can be downloaded from CodePlex.


Installation

PSCX 2.0 is now module based and is deployed via an xcopy .zip file. Installation is as simple as:

1. Download the PSCX 2.0 .zip file.

2. Unblock the .zip file (open Windows Explorer, find and right-click the .zip file, click Properties, click Unblock, and then click OK).

3. Extract the .zip file to your Documents\WindowsPowerShell\Modules directory.

To load PSCX all you need to execute is:

PS C:\> Import-Module PSCX

And when you are done with PSCX, you can remove it just as easily:

PS C:\> Remove-Module PSCX

When PSCX was first introduced, the majority of our users were new to Windows PowerShell. As a result, PSCX provided a profile script as well as items like a prompt function. Over time, Windows PowerShell users have developed their own customized profiles and prompt functions. PSCX 2.0 has been updated to eliminate all modifications to the user’s profile. However, there are still a number of preferences that you can customize. If this something you want to do, copy the Pscx.UserPreferences.ps1 file from the installation directory to your home directory. Edit the preference settings as desired, and then pass the path to this file to Import-Module via the ArgumentList parameter, as shown here:

PS C:\> Import-Module PSCX –ArgumentList ~\Pscx.UserPreferences.ps1

However, we hope that you will find PSCX so useful that you will want it to always be available. In that case, all you need to do is add one of the variants of the “Import-Module PSCX” command to your profile script. One last point, the –Cmdlet, -Function and –Alias parameters to Import-Module give you even finer grain control over which commands and aliases are imported. However, once you use one of these three parameters, only those commands specified will be imported. For example, the following imports all of the PSCX cmdlets and functions but none of the aliases:

PS C:\> Import-Module PSCX –Cmdlet * -Function *


PSCX Cmdlets

PSCX provides 87 general purpose cmdlets, a small sample of them listed here:

  • Out-Clipboard (ocb)
  • Set-FileTime
  • Get-FileTail (tail)
  • New-Symlink
  • Remove-ReparsePoint
  • Format-Hex (fhex)
  • Format-Xml (fxml)
  • Convert-Xml (cvxml)
  • Test-Xml
  • Test-Assembly
  • Get-Hash
  • ConvertFrom-Base64
  • ConvertTo-Base64
  • ConvertTo-WindowsLineEnding
  • Expand-Archive
  • Read-Archive
  • Write-Tar
  • Write-Zip
  • Unblock-File

PSCX also provides 36 useful advanced functions, some of which are listed here:

  • Edit-file (e)
  • Invoke-BatchFile
  • Invoke-Elevated (su)
  • Invoke-GC (igc)
  • Resolve-ErrorRecord (rver)
  • Resolve-HResult (rvhr)
  • Resolve-WindowsError (rvwer)
  • Set-ReadOnly (sro)
  • Set-Writable (swr)
  • Show-Tree

Invoke-BatchFile is particularly useful for developers. This function executes the specified CMD batch file, but what makes it interesting is that it also copies any environment variable changes made by the batch file back to the Windows PowerShell session. This is very handy for batch files like those that ship with Visual Studio that configure your command-line environment to use the Visual Studio compilers and other development tools. I use this function in my profile so that my Windows PowerShell sessions are always configured to be able to compile, as shown here:

Import-Module PSCX

Invoke-BatchFile "${env:VS100COMNTOOLS}..\..\VC\vcvarsall.bat"

Also useful for developers are the Resolve-WindowsError and Resolve-HResult functions, which return descriptions for the error numbers provided:

PS C:\> Resolve-WindowsError 4
The system cannot open the file

PS C:\> Resolve-HResult 0x80004005
Error HRESULT E_FAIL has been returned from a call to a COM component.

Windows PowerShell allows various data structures, hierarchical or flat, to be represented via a Windows PowerShell provider. One issue with providers is that there is no easy way to visually explorer their structure with the notable exceptions of the FileSystem and Registry providers which can be visualized by the dedicated tools Windows Explorer and registery editor, respectively. Unfortunately, other providers like WSMan didn’t have an equivalent tool, until now. The Show-Tree function allows you to visualize the hierarchy of any Windows PowerShell provider. Here’s a view of the WSMan: drive. Note that in order to access the contents of this drive, you must run the following command from an elevated prompt:

PS C:\> Show-Tree wsman: -ShowLeaf

WSMan:\

└──localhost

├──MaxEnvelopeSizekb

├──MaxTimeoutms

├──MaxBatchItems

├──MaxProviderRequests

├──Client

│ ├──NetworkDelayms

│ ├──URLPrefix

│ ├──AllowUnencrypted

│ ├──Auth

│ │ ├──Basic

│ │ ├──Digest

│ │ ├──Kerberos

│ │ ├──Negotiate

│ │ ├──Certificate

│ │ └──CredSSP

│ ├──DefaultPorts

│ │ ├──HTTP

│ │ └──HTTPS

│ └──TrustedHosts

├──Service

│ ├──RootSDDL


Everyday Tools

One of the most handy and pervasive tools in the PSCX toolbox is the redefinition of the “cd” alias to an enhanced command that maintains backward and forward history of directory locations, much like a browser’s backward and forward history. The cd function can be invoked in the following ways:

PS C:\> cd # shows history
# Directory Stack:
--- ----------------
0 C:\Users\Keith
1 C:\Users
2 C:\Windows
-> 3 C:\
PS C:\> cd - # Moves back to 2 - C:\Windows
PS C:\Windows> cd + # Moves forward to 3 - C:\
PS C:\> cd -0 # Jumps directly to 0 - C:\Users\Keith
PS C:\Users\Keith>

Often we need to take output from Windows PowerShell and put it into an email or a report. The Out-Clipboard cmdlet (aliased to ocb) comes in very handy in this scenario, as it directs output to the clipboard for easy pasting into other applications such as Outlook or Word:

PS C:\> Get-ChildItem | Out-Clipboard

Another useful utility is the Format-Hex cmdlet (aliased to fhex). This cmdlet dumps the raw contents of a file to the screen. This can be very useful if you need to check for the existence of a byte order marker (BOM) or to simply see if the file is Unicode or ASCII. On UNIX you would use the utility od (octal dump) for this task. Note the UTF8 byte order mark (0xEF 0xBB 0xBF) present at the head of the file viewed by Format-Hex below:

PS C:\> Format-Hex .\Pscx-2.0.sln -Count 32
Address: 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII
-------- ----------------------------------------------- ----------------
00000000 EF BB BF 0D 0A 4D 69 63 72 6F 73 6F 66 74 20 56 .....Microsoft V
00000010 69 73 75 61 6C 20 53 74 75 64 69 6F 20 53 6F 6C isual Studio Sol

Both developers and system administrators find it necessary to edit XML files. The Test-Xml cmdlet provides a quick way to check if an XML file is well formed after editing. If you have access to the XML schema file, you can even verify the XML file against its schema:

PS C:\> Test-Xml .\Pscx.csproj -SchemaPath 'C:\Program Files (x86)\Microsoft Visual Studio 9.0\Xml\Schemas\1033\MSBuild\Microsoft.Build.Core.xsd'
True

Another issue you may run into with XML files is files consisting of a single line, often an extremely wide line that makes the XML very hard to read. Format-Xml (aliased to fxml) can be used to “pretty print” XML to enhance its readability:

PS C:\> '<Project><PropertyGroup><Property><Configuration>Debug</Configuration> </Property></PropertyGroup></Project>' | Format-Xml

<Project>
<PropertyGroup>
<Property>
<Configuration>Debug</Configuration>
</Property>
</PropertyGroup>
</Project>

If you deal with build scripts for .NET applications, you may find a need to disambiguate between native and managed executables. The Test-Assembly cmdlet provides this functionality. As an example, the following one-liner signs all the partially signed managed executables in a directory, skipping the native executables:

PS C:\> Get-ChildItem . -r *.dll | Where {Test-Assembly $_} |
Foreach {sn -R $_.Fullname .\pubprivkey.snk}

Sometimes you need to quickly set a bunch of files to read-only or make them writable. This is easily accomplished with the Set-Writable and Set-ReadOnly functions (aliased to swr and sro):

PS C:\> Get-ChildItem . -r *.cs | Set-Writable
PS C:\> Get-ChildItem . -r *.cs | Set-ReadOnly


Archives

PSCX 2.0 provides several cmdlets that wrap functionality of the popular 7-Zip API. These cmdlets allow you to create, read, and expand archives. You can even expand ISO files, which is handy when you want to install a piece of software without having to burn it to a CD or DVD first. For instance, the following command expands the contents of an ISO:

PS C:\Downloads> Expand-Archive .\en_expression_studio_4_ultimate_x86_dvd_537032.iso
-OutputPath ExpressionStudio4

If you want to list the contents of an archive, you can use Read-Archive:

PS C:\Downloads> Read-Archive .\en_expression_studio_4_ultimate_x86_dvd_537032.iso
ISO Folder: en_expression_studio_4_ultimate_x86_dvd_537032.iso#\Setup
Index LastWriteTime Size Ratio Name
----- ------------- ---- ----- ----
1 5/25/2010 8:24 PM 72949 100.00 % BlCas.cab
2 5/25/2010 8:24 PM 13473 100.00 % BlCasen.cab
3 5/25/2010 8:24 PM 6509952 100.00 % BlComn.cab

...

Creating archives is equally easy:

PS C:\Scripts> Write-Zip *.ps1 Scripts.zip


Applications

PSCX 2.0 comes with two executable applications. The first is less.exe (Less394). PSCX automatically redefines the Windows PowerShell more function to use less.exe to page output from the help system. Less is a much more capable paging application than the default—more.com. With less.exe, you can scroll using the up and down arrow keys as well as the Page Up and Page Down keys. You can search within the paged text by typing /[search_term]<enter>. Two other helpful commands are: “h” for help and “q” to exit the paging application. Occasionally, you may want to use more.com for paging; in this case, invoke help using the Get-Help cmdlet instead of using “man” or “help”.

The second application is a very simple application called echoargs.exe, which is extremely useful in debugging problems with passing complex parameters to a native executable. This particular issue usually crops up because a native executable might require unusual quoting or characters that are treated specially by Windows PowerShell. What echoargs does is echo to the console how the arguments look when they’re received by the native executable (after Windows PowerShell has parsed and interpreted the arguments). For example, the Microsoft Team Foundation tool, tf.exe, uses a semicolon to separate workspace name and user name. As a result, commands such as this one fail:

PS C:\> tf status . /r /workspace:*;oisin

To troubleshoot, substitute echoargs for the executable (tf) and run again:

PS C:\> echoargs status . /r /workspace:*; oisin
Arg 0 is <status>
Arg 1 is <.>
Arg 2 is </r>
Arg 3 is </workspace:*>

The term oisin is not recognized as the name of a cmdlet.

This makes it obvious that the executable never sees that part of the argument (in this case, ;oisin). That’s because the semicolon is a statement separator in Windows PowerShell, which means oisin is interpreted as a different command. In this case, the solution is to quote the argument like this:

PS C:\> echoargs status . /r '/workspace:*;oisin'
Arg 0 is <status>
Arg 1 is <.>
Arg 2 is </r>
Arg 3 is </workspace:*;oisin>


Conclusion

Windows PowerShell is a wonderfully powerful and productive command-line interface and scripting engine for Windows. Like many new products, Windows PowerShell has a few missing features. PSCX fills in a lot of the missing general purpose features. Over time, it is our hope that more and more PSCX functionality makes it into the base Windows PowerShell product, which is what happened with Get-Random, Select-Xml, and Start-Process in Windows PowerShell 2.0. In the meantime, we hope you find the features available in PSCX useful to you in your everyday use of Windows PowerShell.

KH, hope that answered your question thoroughly! Weekend Scripter is on deck for tomorrow when we will talk about…wait a minute.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • When a variable contains a semicolon, it looks like wrapping it up with a single quote won't work.

    For example, $stringwithsemi = "1234;456"

                .\somethingsomething.bat '$stringwithsemi'

    in this case, the value passed in will be "$stringwithsemi" not "1234;456". In side of the batch file, use echo to print out the argument value.

    any suggestions on how to pass in ";" to a batch file?

  • @Hak, generally quoting the argument containing the ';' will do the trick. However you also want PowerShell to expand the variable $stringwithsemi for you so you need to use double-quotes to do this (or in this case, no quotes at all) e.g.

    .\foo.bat $stringwithsemi

    Note that single-quotes in PowerShell does not expand variables.  This is handy when you need to provide a literal string and you don't want to worry about PowerShell accidentally substituting something it shouldn't.

  • This didn't work for me:

    C:\> import-module PSCX

    I had to get to the .psm1 file. Also, I had to create my Modules directory first: "C:\Documents and Settings\MyUsername\My Documents\WindowsPowerShell\Modules"

    C:\> Import-Module Pscx-2.1.1\Pscx.psm1