PSCX 3.2.0 Available

A new version of the PowerShell Community Extensions was released this morning on CodePlex.  PSCX 3.2.0 is also available on the PowerShell Resource Gallery Preview site which means you can use the new Install-Module command in WMF 5.0 Preview and Windows 10 Preview to install the module e.g.:

C:\PS> Install-Module Pscx -Scope CurrentUser

This new version fixes a number of reported bugs including an issue with directory listings under PowerShell v5.  The Import-VisualStudioVars command has been updated to work with Visual Studio 14 CTP.  You can now import Visual Studio environment variables based on the Visual Studio “version number” e.g. 140 for VS 14 CTP or the name/year 2010, 2012, 2013 e.g.:

C:\PS> Import-VisualStudioVars 140 -Architecture x86

Another minor feature we exposed in this release is a convenient way to convert decimal numbers to hex.  Today you do the following to convert a decimal number to hex:

C:\PS> "0x{0:X}" -f 5123123

With the update, you can do the same a bit more easily:

C:\PS> [hex]5123123

The major new addition for this release is the Edit-File command.  This command allows you to interactively open a file for editing as well as automate the editing of a file.  Here is how you would open a file for interactive editing:

C:\PS> Edit-File $profile.CurrentUserAllHosts

This starts notepad.exe by default and loads your profile.ps1 file.  You can change the text editor that is used by setting $Pscx:Preferences.TextEditor = ‘notepad2.exe’ in your profile.

However the real power of Edit-File (alias e) is that can you use it to automate editing files.  Today, this is how you would automate editing a file in PowerShell:

C:\PS> (Get-Content .\scx.csproj) -replace '>\s*v3.5\s*<', '>v4.5.1' | 
           Out-File .\Pscx.csproj –Force

This works fine but has a couple of issues.  First, in order to write back to the same file PowerShell is reading from, you have to read the whole file into memory.  That is why the parentheses are around the Get-Content command.  This is no problem for most text files but if you have a huge file, it could be a problem.  The bigger issue is that Out-File by default writes the text file using Unicode encoding by default.  But this Visual Studio project file does not use Unicode encoding.  It is UTF-8 with no byte order mark or BOM.  You could certainly specify the encoding as a parameter to Out-File but that requires you to know the file’s encoding in the first place.  In addition, you may want to edit a series of files whose encoding varies.

Edit-File solves this problem by detecting the file’s encoding and using that same encoding when it writes back to the file.  Edit-File also solves the issue of editing large files by first, defaulting to “line-by-line” processing of the file.  If the file size is less than 84,000 the file is processed in memory.  If the file size is larger then a temp file is used to hold intermediate results.  These few small features make for a powerful command.  Here is the Edit-File equivalent of the previous command:

# Open text editor with no file
C:\PS> Edit-File 

# Opens foo.txt in text editor for interactive editing
C:\PS> Edit-File foo.txt 

# Edits the file, replacing instances of foo with bar
C:\PS> Edit-File foo.txt -Pattern foo -Replacment bar 

# If file is readonly, makes it writeable and then replaces foo with bar
C:\PS> Edit-File foo.txt foo bar -Force 

# Same as above but regex is now case-sensitive
C:\PS> Edit-File foo.txt foo bar -CaseSensitive 

# Can take array or patterns/replacements - array sizes must match
C:\PS> Edit-File foo.txt 'foo','ba(.)' 'oof','$1ab' 

# Edit-File takes pipeline input that it can PassThru
C:\PS> GCI . -r *.txt | Edit-File -Pattern foo -Replacement bar -PassThru | 
           Copy-Item -Dest {'E:\temp' + $_.FullName.Substring(2).Replace('\','_')}

# Uses -SingleString to eliminate script between PostBuildEvent tags
C:\PS> GCI . -r *.csproj | 
           Edit-File -Pattern '(?s)(<PostBuildEvent>).*?(</PostBuildEvent)' `
                     -Replacement '$1$2' -SingleString 

# Replaces any empty line with '#--'.
C:\PS> Edit-File foo.txt '(?m)^(?=\r$)' '#--' -SingleString 

One note on the SingleString parameter used in the last two examples above.  Using this parameter causes the whole file to be read into memory as a single string.  Therefore, you may not want to use this parameter on huge (GB) text files.  However, what this parameter enables is the Multiline and Singleline regular expressions modes.  This is crucial if your regular expression needs to span multiple lines.

The rest of the changes are outlined in the release notes.  This is the first release of Edit-File so there may be issues.  If you run into any, please file them on the PSCX CodePlex site.  Thanks for using PSCX and enjoy!

Posted in PowerShell, PowerShell 5.0, PSCX | Leave a comment

Windows PowerShell DSC Resource Kit Wave 5–xWindowsOptionalFeature

When PowerShell 4.0 shipped, the major new feature was DSC or Desired State Configuration – a very convenient and declarative way to manage the configuration of your Windows servers.  However as a developer whose IT department doesn’t really allow me anywhere near their servers, I’m interested in DSC from a purely Windows client SKU perspective.  I stand up new test machines and VMs all the time with various Windows client SKUs.  I was disappointed to find that the initial set of DSC resources for Windows clients was missing the equivalent of the WindowsFeature resource that is supported for Windows Server SKU configuration.  Without this resource, you can’t use DSC to configure your machine with features such as IIS, IIS-ASPNET45, etc. 

Well that all changes with the DSC Resource Kit Wave 5.  This version has an updated xPSDesiredStateConfiguration resource that includes xWindowsOptionalFeature.  Add to that the xOneGet resource for installing utilities like dotPeek, SysInternals, and Fiddler and now DSC is going further towards getting my test machines and VMs setup quickly for doing development work.

Here’s basically what I’m doing to configure, well at least start configure, my test machines and VMs.  I’m sure over time I will continue to add to this DSC configuration to automate more of the steps I’m currently doing manually.

First step is to go and grab the DSC Resource Kit Wave 5.  Second, you will need the July “experimental” version of PowerShell (WMF 5) to use these new resources.  You don’t want to install this on a production machine.  This would be a great excuse to spin up a Hyper-V image with Windows 8.1 on it to experiment with this.   To install the July version, go to the Requirements section of the website above and click on either the x64 MSU or x86 MSU links – depending on the bit-width of your OS installation.  Third, download the the resource kit ZIP file via the link at the top of the web page.  After you have downloaded it, be sure to “unblock” the zip before extracting any files from it.  Now fire up PowerShell “as administrator” and execute the following PowerShell commands. Note: the installation of xOneGet will prompt you to install nuget.exe.  Answer “y” to this to allow nuget to be installed. The new Install-Module cmdlets require nuget.

C:\> Set-ExecutionPolicy RemoteSigned –Force
C:\> Enable-PSRemoting –Force
C:\> Install-Module xOneGet

Now open the DSC Resource Kit Wave 5 zip you downloaded and unblocked.  Copy the directory xPSDesiredStateConfiguration to your C:\Program Files\WindowsPowerShell\Modules directory.  There should be two directories in there now: xOneGet and xPSDesiredStateConfiguration.

Now open up the 5.0 PowerShell_ISE and copy this script and save it as $home\DevPCConfig.ps1. The first section installs all the Windows optional features required to do ASP.NET development on .NET 4.5.  There is a section in there to modify settings of the console host for both x64 and x86 PowerShell.  Remove that or tweak to your satisfaction.  The last section installs some tools that I use all the time: dotPeek, Fiddler4 and PerfView.  To see what packages are available run:

C:\> Find-Package

Now, back to preparing to apply this configuration.  From the admin PowerShell console, cd to the same directory where you saved DevPCConfig.ps1 and execute the script.  Note: this doesn’t actually apply the configuration.  We will do that in the next step.

C:\Users\Keith> .\DevPCConfig.ps1

This will create the MOF file that drives the DSC engine.  You can see the file in .\DevPCConfig\localhost.mof.  Now let’s tell the DSC engine to apply this configuration to the machine by executing this command:

C:\Users\Keith> Start-DscConfiguration .\DevPCConfig –Wait –Verbose 

This will generate a lot of output but is informative the first time or two.  After that you can drop the –Verbose parameter. 

In an ideal world, I could use the community resource cPSGet to allow me to install my two favorite PowerShell modules but alas, bugs are preventing that from happening.  So as a manual step, I execute the following two commands to install these modules:

C:\> Install-Module Pscx –Scope CurrentUser 
C:\> Install-Module PSReadline –Scope CurrentUser

There is still plenty more I find myself tweaking on every new machine I set up.  Over time I’ll be able to “declare” more of that configuration in DevPCConfig.ps1 especially as more Microsoft and community resources become available.

Posted in PowerShell, PowerShell 5.0 | 2 Comments

How to Determine if a Process is 32 or 64 Bit

Your first instinct might be to check [IntPtr]::Size but that only works for the current PowerShell process.  In this scenario you want to check any arbitrary process running on the machine.  There doesn’t seem to be a .NET API for this but fortunately we can easily PInvoke to a Win32 API to get the functionality we need.  Here’s the script that does this:

Add-Type -MemberDefinition @' [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process( [In] System.IntPtr hProcess, [Out, MarshalAs(UnmanagedType.Bool)] out bool wow64Process); '@ -Name NativeMethods -Namespace Kernel32 Get-Process -Id $id | Foreach { $is32Bit=[int]0 if ([Kernel32.NativeMethods]::IsWow64Process($_.Handle, [ref]$is32Bit)) { "$($_.Name) $($_.Id) is $(if ($is32Bit) {'32-bit'} else {'64-bit'})" } else {"IsWow64Process call failed"} }

Posted in PowerShell | Leave a comment

PowerShell 4.0 Now Available

You can get PowerShell 4.0 for down level operating systems now via the WMF 4.0 download.  NOTE: Be sure you have .NET 4.5 installed *before* you install WMF 4.0.  For various reasons, the WMF 4.0 installer doesn’t alert you to this pre-requisite which can cause PowerShell to indicate it is still version 3.0 after installation i.e. you didn’t get a good install.

Posted in PowerShell, PowerShell 4.0 | 5 Comments

PowerShell Tidbit: Capturing a ScreenShot with PowerShell

This is a crude approach but works for capturing the main window of an application who’s process object you can find –typically via Get-Process.  If you run this script from PowerShell.exe or PowerShell_ISE.exe you will capture a screen shot of the host application’s main window which will get saved to your $home folder as screenshot.bmp.

$src = @'
using System;
using System.Runtime.InteropServices;

namespace PInvoke
public static class NativeMethods
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

public struct RECT
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner

Add-Type -TypeDefinition $src
Add-Type -AssemblyName System.Drawing

# Get a process object from which we will get the main window bounds
$iseProc = Get-Process -id $pid

$bmpScreenCap = $g = $null
try {
$rect = new-object PInvoke.RECT
if ([PInvoke.NativeMethods]::GetWindowRect($iseProc.MainWindowHandle, [ref]$rect))
$width = $rect.Right - $rect.Left + 1
$height = $rect.Bottom - $rect.Top + 1
$bmpScreenCap = new-object System.Drawing.Bitmap $width,$height
$g = [System.Drawing.Graphics]::FromImage($bmpScreenCap)
$g.CopyFromScreen($rect.Left, $rect.Top, 0, 0, $bmpScreenCap.Size,
finally {
if ($bmpScreenCap) { $bmpScreenCap.Dispose() }
if ($g) { $g.Dispose() }

Have fun.

Posted in PowerShell, PowerShell 3.0, PowerShell 4.0 | 3 Comments

PSReadLine: A Better Line Editing Experience for the PowerShell Console

When Windows PowerShell 3.0 shipped, the team created an extensibility mechanism to allow a third party to “take over” the line editing experience.  That hook is a function called PSConsoleHostReadline that PowerShell will call – if it exists – to read a line of text from the user.  The simplicity of this interface belies the potential complexity of what it needs to do.  Users expect to be able to do more than just type a command, mistake free and press enter.  No, they want editing features like cursor left/right, backspace, delete, kill to end of line, multiline editing, etc.

Fortunately for the community, one of the PowerShell team members – Jason Shirk – has implemented a very nice replacement line editor that uses this hook. It is called PSReadLine and you can get it here on GitHub.  There are no releases on GitHub at this point in time but you can just download the file from the master branch, be sure to unblock the ZIP file and then extract the module your Modules folder. Alternatively, if you have PsGet you can install PSReadLine using its Install-Module command e.g:

C:\PS> Install-Module PSReadLine

After installation, import the PSReadLine module to have it take over your command line editing experience.

C:\PS> Import-Module PSReadLine

Note: the PSReadLine module only works for the PowerShell.exe console. It does not work for the PowerShell ISE console pane.

You have now imported PSReadLine, so what does it get you?  If you use the default Windows (cmd) mode you get the standard CMD line editing  features:

  • Home/End navigation
  • Up/DownArrow history navigation
  • Right/Left Arrow single char navigation
  • Ctrl+Right/LeftArrow word navigation
  • Ctrl+Home to delete from cursor to beginning of line
  • Ctrl+End to delete from cursor to end of line
  • Esc to revert line
  • Delete to delete a char
  • Backspace to delete char before the cursor

You also get tab & shift+tab completion that you expect from the PowerShell console.  So what else does it buy you? Well syntax color for one thing:


And how about indicating when you have a syntax error:


Notice the red “>” in my prompt?  That is telling me I have a syntax error in this command.  If you look at the end, I’m missing a closing “}”.  Type  in that closing “}” and the red goes away.

How about being able to paste into the console using Ctrl+V like you can in ISE. PSReadLine has got that covered.  Ever deleted something accidentally in the line and wanted to get it back?  Try the handy Ctrl+Z/Ctrl+Y shortcuts for Undo and Redo.  Yes!!  This line editor has a full blown undo/redo stack.

Ever had a command go over a single line?  You know multiline commands are a pain in the PowerShell console because:

  1. You can’t go to a previous line to edit it. You have to completely start over. Pressing the UpArrow just cycles through history on the current line which means your current line edits get blown away.
  2. You can’t use Up/DownArrow history recall to recall the *whole* multiline command. You can only recall one line at a time which makes multiline commands a major PITA to recall & edit in the console.

Check this out with PSReadLine.  It doesn’t “look” much different than standard PowerShell e.g.:


But you can use the Right/LeftArrow keys to move the cursor between different lines and then edit those lines.  You still don’t want to use the Up/DownArrow keys for line navigation as these keys are still bound to history recall.  However, when you do need to recall this multiline command using the UpArrow, what you get is exactly what you see above.  All three lines included in that one history entry *AND* you can press LeftArrow to move up to the previous lines to edit them.

Last up is my favorite feature called PossibleCompletions.  If I type “Get-Process –<Ctrl+Space>” this is what PSReadLine gives me:


Seriously!  Is that cool or what!?  PSReadLine shows you all the parameters in this case.  If you had typed part of the parameter name, it would have shown all parameters that would have matched what you typed.  By the way, this also works for parameter argument values e.g.:


It also works for static and instance type members e.g.:


There are more capabilities in PSReadLine but most of those come with Emacs mode.  However you can create your own keybindings to do whatever command PSReadLine offers.  If you want to use the Emacs mode, execute this command:


If you like this new command line editing experience as much as I do you will want this in your profile script.  This is my section of profile script for PSReadLine:

if ($host.Name -eq 'ConsoleHost') {
    Import-Module PSReadline

    Set-PSReadlineKeyHandler -Key UpArrow   -Function HistorySearchBackward
    Set-PSReadlineKeyHandler –Key DownArrow -Function HistorySearchForward

Note that I’ve defined a few more keybindings that allow me to use the UpArrow and DownArrow keys to not only navigate backward and forward in history on an empty line but navigate based on a match as well.   That is, when I type the beginning of some command line, the UpArrow and DownArrow keys search history backward or forward respectively for command lines that match what’s been typed.

If you spend a lot of time at the PowerShell console you owe it yourself to give this module a try.  And if you run into issues, remember these are still somewhat early bits, the project developer has been responsive to fixing bugs.  You can post/view issues here on GitHub.  For more info on PSReadLine, check out the about_PSReadline topic after you have installed the module.

Update 12-29-2013:

Jason has delivered some new PSReadLine presents for the holidays.  Version supports some notable new features.  My favorite of which is that you can select text using just the keyboard.  As if you were in Notepad or VS, press Shift+Right/LeftArrow to select one character at a time or use Ctrl+Shift+Right/LeftArrow to select whole words at a time.

Once you have the desired text selected you can press Ctrl+x to cut or Ctrl+Shift+c to copy.  Before careful with the copy keyboard shortcut because if you forgot to press Shift, the resulting Ctrl+c will abort the current command line and you can’t get it back – not even with Ctrl+z (undo).  I wonder if perhaps the default copy shortcut should be something like Shift+Insert – old school – to avoid any potential mishaps with Ctrl+c?

You might find the following custom keyhandler handy for selecting the whole command line with Ctrl+A:

Set-PSReadlineKeyHandler -Chord Ctrl+A `
                         -BriefDescription SelectEntireCommandLine `
                         -Description "Selects the entire command line" `
                         -ScriptBlock {
    param($key, $arg)

    [PSConsoleUtilities.PSConsoleReadLine]::BeginningOfLine($key, $arg)

    $line = $null
    $cursor = $null
    [PSConsoleUtilities.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

    while ($cursor -lt $line.Length) {
        [PSConsoleUtilities.PSConsoleReadLine]::SelectForwardChar($key, $arg)
        [PSConsoleUtilities.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

Another feature that has been added is CharacterSearch and CharacterSearchBackward. By default these are mapped to F3 and Shift+F3.  Say you are at the beginning of the command line with multiple pipeline stages.  Press F3, then press Shift+\ to specify the “|” character.  PSReadLine will advance the cursor to the next “|” character.  This is cool.  But the next two custom keyhandlers pretty nifty:

Set-PSReadlineKeyHandler -Chord Ctrl+\ `
                         -BriefDescription SearchForwardPipeChar `
                         -Description "Searches forward for the next pipeline character" `
                         -ScriptBlock {
    param($key, $arg)
    [PSConsoleUtilities.PSConsoleReadLine]::CharacterSearch($key, '|')
Set-PSReadlineKeyHandler -Chord Ctrl+Shift+\ `
                         -BriefDescription SearchBackwardPipeChar `
                         -Description "Searches backward for the next pipeline character" `
                         -ScriptBlock {
    param($key, $arg)
    [PSConsoleUtilities.PSConsoleReadLine]::CharacterSearchBackward($key, '|')

These two keyhandlers will allow you to navigate around your command line by jumping forward and backward between pipeline stages.  They use CharacterSearch and CharacterSearchBackward to move around the command line by searching for “|” characters.  So Ctrl+\ moves forward to the next “|” character and Ctrl+Shift+\ moves backwards to the previous “|” character.

And finally, some help for quickly finding out what keyhandlers are mapped to which keyboard shortcuts, just press Ctrl+Alt+? which on a US keyboard is really Ctrl+Alt+Shift+/ and you get this information:

Key                  Function                 Description
---                  --------                 -----------
Enter                AcceptLine               Accept the input or move to the...
Shift+Enter          AddLine                  Move the cursor to the next lin...
Escape               RevertLine               Equivalent to undo all edits (c...
LeftArrow            BackwardChar             Move the cursor back one charac...
RightArrow           ForwardChar              Move the cursor forward one cha...
Ctrl+LeftArrow       BackwardWord             Move the cursor to the beginnin...
Ctrl+RightArrow      NextWord                 Move the cursor forward to the ...
Shift+LeftArrow      SelectBackwardChar       Adjust the current selection to...
Shift+RightArrow     SelectForwardChar        Adjust the current selection to...
Ctrl+Shift+LeftArrow SelectBackwardWord       Adjust the current selection to...
Ctrl+Shift+RightArrow SelectNextWord          Adjust the current selection to...
UpArrow              PreviousHistory          Replace the input with the prev...
DownArrow            NextHistory              Replace the input with the next...
Home                 BeginningOfLine          Move the cursor to the beginnin...
End                  EndOfLine                Move the cursor to the end of t...
Delete               DeleteChar               Delete the character under the ...
Backspace            BackwardDeleteChar       Delete the charcter before the ...
Ctrl+Spacebar        PossibleCompletions      Display the possible completion...
Tab                  TabCompleteNext          Complete the input using the ne...
Shift+Tab            TabCompletePrevious      Complete the input using the pr...
Ctrl+v               Paste                    Paste text from the system clip...
Ctrl+c               CancelLine               Abort editing the current line ...
Ctrl+C               Copy                     Copy selected region to the sys...
Ctrl+l               ClearScreen              Clear the screen and redraw the...
Ctrl+x               Cut                      Delete selected region placing ...
Ctrl+y               Redo                     Redo an undo
Ctrl+z               Undo                     Undo a previous edit
Ctrl+Backspace       BackwardKillWord         Move the text from the start of...
Ctrl+Delete          KillWord                 Move the text from the cursor t...
Ctrl+End             ForwardDeleteLine        Delete text from the cursor to ...
Ctrl+Home            BackwardDeleteLine       Delete text from the cursor to ...
Ctrl+]               GotoBrace                Go to matching brace
Ctrl+Alt+?           ShowKeyBindings          Show all key bindings
Alt+?                WhatIsKey                Show the key binding for the ne...
F3                   CharacterSearch          Read a character and move the c...
Shift+F3             CharacterSearchBackward  Read a character and move the c...


And to find out what a specify keyboard shortcut is mapped to, pres Alt+? (or on a US keyboard Alt+Shift+/) and then the keyboard shortcut.  For example, if I press Alt+Shift+/ and then Ctrl+Shift+LeftArrow I get this information:

Ctrl+Shift+LeftArrow: SelectBackwardWord - Adjust the current selection to inclu
de the previous word

Major kudos to Jason and this awesome module.  It is funny how quickly you just get used to it and then when you’re on someone else’s PC without this module – well – you convince them pretty quickly that they need PSReadLine.  Smile

In closing, I’ll leave you with two more custom keyhandlers I have in my profile. The first creates a pair of single or double quotes and puts the cursor in the middle:

Set-PSReadlineKeyHandler -Chord "Ctrl+'","Ctrl+Shift+'" `
                         -BriefDescription SmartInsertQuote `
                         -Description "Insert paired quotes if not already on a quote" `
                         -ScriptBlock {
    param($key, $arg)

    $line = $null
    $cursor = $null
    [PSConsoleUtilities.PSConsoleReadline]::GetBufferState([ref]$line, [ref]$cursor)

    $keyChar = $key.KeyChar
    if ($key.Key -eq 'Oem7') {
        if ($key.Modifiers -eq 'Control') {
            $keyChar = "`'"
        elseif ($key.Modifiers -eq 'Shift','Control') {
            $keyChar = '"'
    if ($line[$cursor] -eq $keyChar) {
        # Just move the cursor
        [PSConsoleUtilities.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
    else {
        # Insert matching quotes, move cursor to be in between the quotes
        [PSConsoleUtilities.PSConsoleReadLine]::Insert("$keyChar" * 2)
        [PSConsoleUtilities.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
        [PSConsoleUtilities.PSConsoleReadLine]::SetCursorPosition($cursor - 1)

The second handler was inspired by mjolinor’s Clip-ToArray ISE add-on.  It is a more basic version of his function which I call – PasteAsHereString.  It is indeed handy and could be easily modified to do all that the original Clip-ToArray function does.

Set-PSReadlineKeyHandler -Chord Ctrl+Shift+v `
   -BriefDescription PasteAsHereString `
   -Description "Pastes the clipboard text as a here string" `
   -ScriptBlock {
    param($key, $arg)

    Add-Type -AssemblyName System.Windows.Forms
    $str = [windows.forms.clipboard]::GetText() -replace '(?m)[`n\s*]+$',''
Posted in PowerShell, PowerShell 3.0, PowerShell 4.0 | 8 Comments

PowerShell Community Extensions 3.1.0 Released

We released a minor update to PSCX that adds support for Windows PowerShell 4.0 in addition to its support for PowerShell 3.0.  You can grab the updated bits for your shiny new Windows 8.1 or WMF 4.0 install here.

Posted in PowerShell, PowerShell 3.0, PowerShell 4.0 | 3 Comments