Keith's profileKeith Hill's BlogPhotosBlogListsMore ![]() | Help |
|
|
September 02 PowerShell Community Extensions Makes Hanselman’s 2009 Ultimate Developer Tools ListBoth Windows PowerShell and PSCX made it into Scott Hanselman’s 2009 Ultimate Developer and Power Users Tool List for Windows. w00t! August 06 PowerShell Community Extensions 1.2 ReleasedWe have released PSCX 1.2 just in time for Windows 7 RTM availability on MSDN and TechNet. Thanks to those folks who tried out the beta for the past three months! And a huge thanks goes to PowerShell MVP Oisin Grehan who put a lot of effort into 1.2 and is the reason you have Read-Archive and Expand-Archive cmdlets among other new features.
The big enhancements for 1.2 are:
Major New Cmdlets
New Scripts
I hope you find as much utility in these cmdlets as I have. I use them everyday - of course! If you have any feedback please log it on the CodePlex project site on either the discussion forum or issue tracker. And if you download PSCX and are passionate about it (one way or the other), please write a review on the download page for 1.2.
Next up for PSCX is 2.0 which will most likely target only PowerShell 2.0 and come in Module form. August 02 Tail-File Cmdlet Coming in PSCX 1.2Occasionally I need to tail some very large log files over the network. In this scenario, the standard PowerShell approach: PS> Get-ChildItem *.log | %{ Get-Content $_ | Select –Last 1 } just isn’t practical for performance reasons. So the final drop of PSCX 1.2 will have a new cmdlet called Tail-File that is optimized for tailing the end of large (even huge) log files. Here’s a performance comparison of the two approachs: 19# measure-command { tail-file \\Keith-PC\C\*.txt -count 1 } Days : 0 20# measure-command {Get-ChildItem \\Keith-PC\C\*.txt | %{ Get-Content $_ | Select -Last 1 }} Days : 0 Milliseconds : 656 That is a speed-up of approximately 2500x. That is pretty significant especially if you need to do this to a number of large log files. For reference, the above test tailed two medium size log files (total size: 37.4 MB): -a--- 5/23/2009 6:33 AM 4173558 dirlist.txt Tail-File handles ASCII and Unicode encoding as well UTF8 as long as it contains only ASCII characters i.e. it will not choke on the UTF8 byte order mark. Oh yeah, it also supports active tailing (tail –f) via the Wait parameter. Use Ctrl+C to return control back to the console. May 22 PSCX Tips Part 2This is a continuation of PSCX Tips Part 1. Here are some more things you can do with the PowerShell Community Extensions. If you do .NET software development and partially strong name your assemblies then you know that at some point in your official build process you need to finish the strong-naming process. When we have done this, we cycle through all the exes and dlls in a common output dir and apply the full strong name. Problem is that we have some native binaries mixed in with the managed binaries. So we need some quick way to test if a file is a managed assembly. This is where Test-Assembly comes in handy: PS> Get-ChildItem | Where {$_ –match '\.(dll|exe)$' –and (Test-Assembly $_)} | On 64-bit Windows you may want to know whether a binary is a 32-bit or 64-bit binary. That’s easy with Get-PEHeader: PS> Get-PEHeader .\wordpad.exe Type : PE64 Need to test if the current user is elevated on Vista or Windows 7? Use Test-UserGroupMembership e.g.: PS> Test-UserGroupMembership -GroupName Administrators Need to know what the 8.3 filename is for a file? Use Get-ShortPath e.g.: PS> Get-ShortPath '.\Windows Azure SDK' Need a touch like utility to change a file’s various time fields? Try Set-FileTime e.g.: PS> Set-FileTime .\test.csv -Modified (Get-Date).AddDays(-2) Need to compute the hash for a string or an entire file using various algorithms e.g.: PS> "hello world" | Get-Hash Algorithm: MD5 Path : PS> Get-Hash .\uszip.wsdl -Algorithm SHA1 Algorithm: SHA1 Path : C:\Users\Keith\uszip.wsdl Need to convert between different OS style line endings in files? Check out these cmdlets;
Need to convert from or to Base64? Try out the ConvertTo-Base64 and ConvertFrom-Base64 cmdlets e.g.: PS> [byte[]](1..255) | ConvertTo-Base64 When parsing legacy exe text, do you ever need to skip either the first couple of lines or perhaps the last line (or both)? Skip-Object is very convenient here because you don’t need to know the length of the sequence you are dealing with. Here’s an example: PS> 1..10 | Skip-Object -First 2 -Last 1 -Index 4,6 That’s enough for this post but there’s still plenty more in PSCX. Stay tuned. May 20 PSCX TipsWe recently released a beta of the PowerShell Community Extensions that supports PowerShell V2 in addition to V1. This version also supports 64-bit versions of Windows. The primary purpose of PSCX is to flesh out the functionality of PowerShell such that tools like cygwin and MKS Toolkit aren’t needed. We aren’t completely there with PSCX yet but there is quite a bit of useful functionality in PSCX. Here are some examples. Enhanced CD function has browser like backwards and forwards history: PS> cd $pshome;cd $pscx:home;cd $pscx:ScriptsDir;cd~ # Directory Stack: Sending PowerShell output to the clipboard: PS> Get-Process | Out-Clipboard Inspecting the contents of a file ala od.exe (octal dump): # View the first 16 bytes of powershell.exe Address: 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII # Using the fhex alias to inspect a text file to see if it has the UTF-8 BOM Address: 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII Formatting XML: # Ever have an XML string display as one long line, try this out Testing XML for well-formedness and against a schema: PS> "<a><b><c><d/></c></b></a>" | Test-Xml Applying a XSL transform to a file: PS> Convert-Xml My.xml –XsltPath My.xsl –EnableScript There is a lot more functionality in PSCX such as the ability to create, read and expand ZIP and TAR files. But that is enough of a teaser for this post. Stay tuned for more info on what’s in PSCX. May 14 PSCX 1.2 Beta AvailableLast night we released a beta of the PowerShell Community Extensions 1.2. The release supports Windows PowerShell V2 and has better support for 64-bit Windows. PowerShell MVP/Rockstar Oisin Grehan has added two very useful cmdlets to this release: Read-Archive and Expand-Archive which works not only on TAR and ZIP files but also on ISO files. Give it a spin. You can download it here. Be sure to let us know if you run into any problems either via the PSCX discussion forum or issue tracker. BTW, there are two known issues on x64 Windows. The cmdlets Get-PEHeader and Test-Assembly don’t work. After a week or so, we’ll look at officially releasing 1.2. March 16 Image File Resizing Using the PowerShell Community ExtensionsA reader asked me about using PowerShell to process image files. While PowerShell doesn’t natively support doing this you could perform this task by using PowerShell’s support for .NET which supports image resizing. However if you have the PowerShell Community Extensions (PSCX) installed you can do this pretty easily using cmdlets like so:
Can you feel the power?! psmdtag:cmdlet - Bitmap manipulation February 20 PowerShell Community Extensions - It's the Little ThingsToday I was posting about an issue I was having with Team Foundation Server 2008 HTML alert emails that get generated for check-ins. The second column in the details area of the email is way too narrow. I was able to copy/paste the HTML into Expression Web so I could get to the HTML. I wanted to post that HTML into the MSDN Forum post editor but, well, it doesn't like you putting in non-escaped HTML. Fortunately PowerShell and PSCX are at my beckon call. Here is all I had to do to escape my HTML so I could paste it into the HtmlView of the MSDN forum editor:
I just love tools that save me time! January 02 XPath Expressions and PSCX's Select-XmlMoW wrote up a nice post on invoking XPATH expressions. Check it out here. Just wanted to let the PSCX users out there know that the equivalent of MoW's PS I:\PowerShell> Function invoke-XpathExpression ([xml]$xml,$expression) {
>> $xn = $xml.PSBase.CreateNavigator()
>> $xn.Evaluate($expression)
>> }
>>
PS I:\PowerShell> # Example using the function
PS I:\PowerShell>
PS I:\PowerShell> invoke-XpathExpression -xml (type gl.xml) -exp "sum(GroceryList/Item/Price)"
29.15 in PSCX would be:
Note that the PSCX cmdlet Select-Xml is oriented towards "selecting" node-sets hence the name. Unfortunately xpath expressions that don't result in node-sets will error. No worries though because PowerShell's Measure-Object cmdlet (measure alias provided by PSCX) can compute the sum easily. OK so that was a bit shorter but what's the big deal. Here's the deal. If your XML uses XML namespaces then this all gets a good bit harder to deal with yourself. Not impossible mind you. I have written a number of posts on handling XML that uses XML namespaces but with Select-Xml it is pretty simple. For instance, let's tweak the XML ever so slightly: <GroceryList xmlns="tempuri.org"> Note the default namespace declaration on the root element. Now the previous XPath expressions won't work but here is all we need to do with Select-Xml to make this work:
All we needed to do was provide the namespace and a temp prefix (ns) to use in the xpath query. Note that the -Namespace parameter will take an array of strings that match this format: "<prefix>=<namespace>". October 03 Windows Powershell Virtual User Group PresentationHere are the slides that I presented at today's LiveMeeting. Thanks to Marco Shaw for setting up the group! June 23 New PSCX Eye Candy for VistaIf you are using PSCX 1.1.1 and are running on Vista and your not too attached to your own prompt function, I encourage you to try out EyeCandy.Vista.ps1. This works best if you are running the PSCX profile. If so, just modify the following lines like so: # --------------------------------------------------------------------------- With the EyeCandy.Vista settings there is no mistaking an elevated PowerShell session from a non-elevated session. :-) The elevated session turns the background color to the DarkRed. Now it turns out that in my humble opinion DarkRead isn't dark enough to get a good contrast between the background color and error output color. This can be easily fixed though. Fire up an elevated PowerShell. If you are using the PSCX profile, just execute "su". When the new PowerShell window appears it should have a dark red background. Select the system menu (upper left corner by the PowerShell icon) and then select Properties. Now select the Colors tab and then the Screen Background radio button. Select the DarkRed color and change the "Red:" value to 80 as shown below: This gives a pretty good contrast for error output and makes darn sure you know when you are in an elevated PowerShell session on Vista. June 22 Elevate function in PSCX 1.1.1Here's a useful function especially if you are on Vista and have left UAC enabled. If you install PSCX 1.1.1 and use the PSCX default profile you will get this function dot sourced in via the profile. However if you don't do either of those then here's the function posted here for your benefit:
# --------------------------------------------------------------------------- ### <Function name='Elevate'> ### <Author>Keith Hill</Author> ### <Description> ### Runs the specified command via an elevated PowerShell instance on Vista. ### To get debug info, set $DebugPreference temporarily to 'Continue'. ### </Description> ### <Usage> ### elevate ### elevate notepad c:\windows\system32\drivers\etc\hosts ### elevate gci c:\windows\temp ### elevate {gci c:\windows\temp | export-clixml tempdir.xml; exit} ### elevate {gci c:\windows\temp | export-clixml tempdir.xml; exit} | ### %{$_.WaitForExit(5000)} | %{Import-Clixml tempdir.xml} ### </Usage> ### </Function> # --------------------------------------------------------------------------- Set-Alias su Elevate -Option AllScope function Elevate { $ndx=0 if ($MyInvocation.PositionMessage -match 'char:(\d+)') { $ndx = [int]$matches[1] } $setDirCmd = "[Environment]::CurrentDirectory = (set-location -LiteralPath '$pwd' -PassThru).ProviderPath" $OFS = "," Write-Debug "`$MyInvocation.Line args index is $ndx; `$args are <$args>" if ($args[0] -is [Scriptblock]) { $script = $args[0] Write-Debug "Starting PowerShell with scriptblock: {$script}" start-process powershell.exe -verb runas -workingdir $pwd ` -arguments "-noexit -command & {$setDirCmd; $script}" } elseif ($args[0].length -gt 0) { $startProcessArgs = $MyInvocation.Line.Substring($ndx) $app = get-command $args[0] | select -first 1 | ? {$_.CommandType -eq 'Application'} if ($app) { $startProcessArgs = $startProcessArgs.Substring($args[0].Length).Trim() Write-Debug "Starting <$($app.Path)> with args: <$startProcessArgs>" start-process $app.Path -verb runas -workingdir $pwd -arguments $startProcessArgs } else { Write-Debug "Starting PowerShell with args: <$startProcessArgs>" start-process powershell.exe -verb runas -workingdir $pwd ` -arguments "-noexit -command & {$setDirCmd; $startProcessArgs}" } } else { Write-Debug "Starting Powershell without args" start-process powershell.exe -verb runas -workingdir $pwd ` -arguments "-noexit -command & {$setDirCmd}" } } PowerShell Community Extensions 1.1.1 Released!It took a little while but we finally got a lot of the issues resolved that you reported in PSCX 1.1. Tonight (well *early* this morning) I released PSCX 1.1.1. This release is a primarily a maintenance release. It fixes about 30 defects and adds five new features. You can download 1.1.1 from here. You will need to uninstall any previous version you have of PSCX before you can install 1.1.1. We really thought we had the VS 2005 Setup project configured to do an upgrade and it "seemed" to work. However further testing revealed that sometimes it would not re-register the updated PSCX snapin with PowerShell. Then PowerShell gets upset because the version number of the snapin doesn't match what has been registered with PowerShell.
Here is the final list of changes in 1.1.1:
NEW CMDLETS
NEW FUNCTIONS AND FILTERS
NEW SCRIPTS:
NEW VARIABLES
NEW ALIASES
Other changes include the new -PageSize parameter on Get-ADObject. Select-Xml now outputs XPathDocumentNavigator objects instead of strings. There is also a new elevate function (alias su) that will invoke the UAC elevation UI on Vista and the RunAs dialog box on XP. For example: elevate Also if you ever wonder what other views are available for a particular object, try this: 23> Get-ViewDefinition 'System.Diagnostics.Process' Name : StartTime Name : process On the download page for PSCX 1.1.1 you will be able to see the details on all the work items that went into this release. I would like to acknowledge and thank the following developers who helped out with the 1.1.1 release: Oisin Grehan, Richard Lehrbaum and Burt Harris! Please be sure to keep those work item submissions coming. I can't promise that we will get the next release out any sooner but we do take defects seriously. And we do appreciate all the folks out there that have been using PSCX and contributing by submitting work items and participating in the discussion forums on the PSCX CodePlex site. -- June 16 PowerShell Community Extensions 1.1.1 SoonThe PSCX team is getting real close to releasing PSCX 1.1.1. This is primarily a bug fix release where we have fixed the limitation of the ADSI provider stopping at 1000 objects plus ~30 other issues. There are a few new features: NEW CMDLETS NEW FUNCTIONS AND FILTERS NEW SCRIPTS: NEW VARIABLES NEW ALIASES Get-ViewDefinition is handy if you are curious if there are alternate views for an object. Right now the only way to find this out is via the help assuming the help covers this. With Get-ViewDefiniton you can find out easily: 6> get-process | select -first 1 | Get-ViewDefinition Name : Priority Name : StartTime Name : process We are testing right now. I hope to have this version released by the end of June (hopefully sooner). Unfortunately like the other PSCX instals, you will have to uninstall your current version of PSCX first. Too bad we don't have an MSI/installer guru on the PSCX team. I thought I had the VS Setup project beaten into submission so it would allow us to upgrade version 1.1 but alas when we tested this, the updated PSCX snapin doesn't get registered. PowerShell doesn't like it when the version info it has registered with it doesn't match the PSSnapin that gets loaded. Oh well, perhaps we can crack this nut when put out the release after 1.1.1. March 07 PowerShell Community Extensions 1.1 ReleasedIt's been quite the push to get the 1.1 version out but now it's done. Tonight I posted the 1.1 bits to CodePlex. Here's the announcement we made on the PowerShell Newsgroup:
PowerShell Community Extensions 1.1 has been released! This version adds significant new functionality that is documented in the attached About_Pscx.Help.txt file. I would like to thank Alex Angelopoulos, Oisin Grehan, Matt Hamilton, Reinhard Lehrbaum Mark Maier and especially Jachym Kouba for his major contributions to PSCX 1.1. You can download PSCX 1.1 from:
This release now supports installation on Vista and x64 editions of Windows. If you discover any issues please either post to the PSCX project discussion forum at:
or submit a work item at:
Some of my favorite additions are:
January 17 Select-Xml Cmldet for PSCX 1.1We have a new cmdlet coming in PSCX 1.1 (due out in mid February) that is pretty darn handy when you need to query some XML using XPath especially if that XML uses namespaces. In the past, I have blogged about how to do this. The PowerShell script looks like this:
PoSH> $lua = [xml](get-content app.exe.0.dat.xml)
PoSH> $nsmgr = new-object Xml.XmlNamespaceManager($lua.PSBase.NameTable)
PoSH> $nsmgr.AddNamespace("avrf", "Application Verifier")
PoSH> $errors = $lua.SelectNodes("//avrf:logEntry[@Severity = 'Error']", $nsmgr)
PoSH> $errors | Measure-Object However with this new cmdlet, courtesy of Mark Maier, you could simplify this to:
PoSH> Select-Xml add.exe.0.dat.xml -XPath "//avrf:logEntry[@Severity = 'Error']" -Namespace "avrf=Application Verifier"
Note that -Namespace actually takes an array of prefix;namespace strings. Also note that even for the default namespace you must supply a prefix (e.g. dns) and use that namespace prefix in your xpath queries (e.g. //dns:HintPath). I love tools that make me more productive! January 15 Get-PropertyValue in PowerShell Community ExtensionsGet-PropertyValue, alias gpv, is an easy way to get and/or display just the specified property of an object in the pipeline. Where this really comes in handy is when you are in discovery mode and just want to figure out how to solve a problem. For example, let's say you are learning about the Get-Process cmdlet and the Process objects returned by it. You know about type member discovery using Get-Member so you try this:
> Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ---------- Handles AliasProperty Handles = Handlecount Name AliasProperty Name = ProcessName NPM AliasProperty NPM = NonpagedSystemMemorySize PM AliasProperty PM = PagedMemorySize VM AliasProperty VM = VirtualMemorySize WS AliasProperty WS = WorkingSet add_Disposed Method System.Void add_Disposed(EventHandler value) <snip>
StartInfo Property System.Diagnostics.ProcessStartInfo StartInfo {get;set;}
<snip>
You spot an interesting property called StartInfo that you want to examine. You might think that you could do this:
> Get-Process | Select StartInfo | Get-Member
but that would return info on a PSCustomObject e.g.:
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ---------- Equals Method System.Boolean Equals(Object obj) GetHashCode Method System.Int32 GetHashCode() GetType Method System.Type GetType() ToString Method System.String ToString() StartInfo NoteProperty System.Diagnostics.ProcessStartInfo StartInfo=System.Diagnostics.ProcessStartInfo That is consistent with the intent of the Select-Object cmdlet which is to create a new object that is just a container object for the properties that we selected. So how do we get info on this StartInfo property? We could also do this:
> 19> (Get-Process)[0].StartInfo | Get-Member
TypeName: System.Diagnostics.ProcessStartInfo <snip>
This works OK but isn't exactly obvious. Then next approach suffers the same (isn't obvious):
> Get-Process | Get-Member -InputObject {$_.startinfo}
With PSCX installed, you can do this a bit more easily:
> Get-Process | gpv StartInfo | Get-Member January 09 Get-Clipboard and Out-Clipboard in PSCXPowerShell Community Extensions (PSCX) has a couple of handy cmdlets for dealing with clipboard text. Get-Clipboard alias gcb, gets the current clipboard text and sends it down the pipe. I find this useful when copying PowerShell scripts or other text from the clipboard that I want to quickly place in a file e.g.:
> Get-Clipboard > foo.ps1
Out-Clipboard alias ocb, is very use for placing PowerShell output onto the clipboard. Perhaps you want to mail your current process stats to a sysadmin e.g.:
> Get-Process | Sort PM -desc | select -f 20 | Out-Clipboard
One feature that Out-Clipboard provides is that it allows you to specify the formatting output width. For instance if you have text that is wrapping on your 120 character width console, then you can specify a larger width like so:
> gci "$Home\My Documents\My Music" -rec | %{$_.Fullname} | ocb -width 260
This will create output that doesn't wrap. Note also that by default Out-Clipboard trims whitespace at the end of each line. If for some reason you don't want that behavior you can use the -NoTrimEnd option.
Where things get really interesting is to use PowerShell to massage clipboard text before you paste it somewhere else. I use this example fairly often:
> gcb | %{$_ -replace '\t', ' '} | ocb
This little PowerShell command line gets the text on the clipboard and replaces all the tabs with four spaces and then places the modified text back on the clipboard. |
|
|