PowerShell Cookbook

Search

Categories

 

On this page

Archive

Blogroll

Disclaimer
I work for Microsoft.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 222
This Year: 0
This Month: 0
This Week: 0
Comments: 536

Sign In

 Friday, March 28, 2008
Friday, March 28, 2008 7:33:12 AM (Pacific Daylight Time, UTC-07:00) ( )

[Download: BgShell.zip]

BgShell is a proof of concept PowerShell host that explores the idea of "PowerShell Everywhere."

What if PowerShell was always at your fingertips – making quick calculations easier than launching Windows Calculator? Or, making a “quick ipconfig” with PowerShell just a keystroke away? BgShell offers PowerShell Everywhere, and instant gratification. Simply press Control-Alt-B, and the BgShell interface appears immediately. Press Control-Alt-B again to hide the shell. Closing the window only hides the shell, keeping it instantly available for your next command.

The concept of “PowerShell Everywhere” goes further than that, though. What if you could bind PowerShell script blocks to arbitrary keystrokes? BgShell supports that, too. If you use any keyboard Macro programs, BgShell can likely replace them -- and with a more powerful engine and scripting language, at that.

BgShell lets you define these in a host-specific profile. If you tend to write the same thing over and over, just define a hotkey for it:

## Boy, I type this a lot.
$keyMapping['Control,Alt,Q'] = @{ 
    Action = { SendString 'PowerShell Rocks!'
}

 

Or, rather than batting the mouse cursor out of the way when it obscures your typing, just press a hotkey:

## Move the annoying mouse pointer out of your way
$keyMapping['Control,Alt,Z'] = @{ 
    Action = {
        [Windows.Forms.Cursor]::Position = (New-Object System.Drawing.Point 0,0
    }
}

 

Or even bring some of your old Unix habits to the Win32 console:

$keyMapping['Control,L'] = @{
    KeypressHandled = { IsClassActive 'ConsoleWindowClass' };

    ## Console clear
    Action =  { SendKeys '{ESC}cls{ENTER}' }
}


 

At the same time, you’ve been building new habits in PowerShell. Why not cater to them?

$keyMapping['Control,F'] = @{
    KeypressHandled = { IsClassActive 'ConsoleWindowClass' };

    ## Console foreach-object
    Action =  { SendString '| foreach { $_. }'; SendKeys '{LEFT}{LEFT}' }
}

 

Keystroke automation of other programs opens up entire new realms of interactive management potential:

## Control,Alt,C -- Convert selected text in an Outlook Message
## into a code sample
$keyMapping['Control,Alt,C'] = @{
    KeypressHandled = { IsClassActive '_WwG' };
    Action =  { 
        Start-Sleep -m 100
        SendKeys "%o"
        Start-Sleep -m 500
        SendString "ff"
        Start-Sleep -m 500
        SendString "Courier New"
        SendKeys "{ENTER}"
        Start-Sleep -m 500
        SendKeys "%o"
        Start-Sleep -m 500
        SendString "fs"
        Start-Sleep -m 500
        SendString "9"
        SendKeys "{ENTER}"
        Start-Sleep -m 500
    }
}

 

Of course, your brain starts to hurt with so many hotkeys. In that case, maybe a memorable phrase is better?

## Get the current date

$stringMapping[ "**date" ] = { SendString (Get-Date) }

 

How about saving yourself from the tedium of template code?

## Get some input from the user
function Get-Input 
{ 
  param ($message = "Input : ", 
         $title = "Inputbox")

  $vbs = New-Object -com MSScriptControl.ScriptControl 
  $vbs.language = 'vbscript' 
  $vbs.addcode("function getInput() getInput = inputbox(`"$message`",`"$title`") end function") 
  $result = $vbs.Eval('getInput') 
  $result 
}

## Generate a C# property
$stringMapping[ "**prop " ] = 
{
    $template = @"
        /// <summary>
        /// Summary of what this property does
        /// </summary>
        public __TYPE__ __NAME__
        {
            get
            {
                return __NAMELOWER__;
            }
            set
            {
                __NAMELOWER__ = value;
            }
        }
        private __TYPE__ __NAMELOWER__;
"@

    $type,$name = (Get-Input -Message "Property type and name, such as 'String Foo': ") -split " "
    
    $template = $template.Replace("__TYPE__", $type)
    $template = $template.Replace("__NAME__", $name)
    $template = $template.Replace("__NAMELOWER__", ($name.Substring(0,1).ToLower() + $name.Substring(1)))

    $autoIt.ClipPut($template)
}

 

The sky really is the limit.

For more examples, see the example profile. Place it in the same directory as your regular PowerShell profile. BgShell surfaces this profile location through the standard $profile variable.

 

Note

·         Vista introduces security enhancements that prevent low-privilege applications from being notified of keystrokes in (or sending keystrokes to) high-privilege applications. BgShell is marked to run as administrator so that it can respond in elevated windows.

Comments [5] | | # 
Friday, March 28, 2008 1:39:36 PM (Pacific Daylight Time, UTC-07:00)
Thanks Lee!

I had one problem getting it to run on V1.0. I had to change the -split operator on line 368 of the sample profile to

$type,$name = (Get-Input -Message "Property type and name: ").split(" ")

from

$type,$name = (Get-Input -Message "Property type and name: ") -split " "

because -split is only available in the CTP.
Friday, March 28, 2008 5:16:48 PM (Pacific Daylight Time, UTC-07:00)
One more thing, the History Search uses a script from your book, which people might not have - Select-FilteredObject.
Tuesday, April 01, 2008 12:07:29 PM (Pacific Daylight Time, UTC-07:00)
Hi Lee,
I love the idea, but bgShell isn't working for me. I'm running Vista 64-bit with SP1 and it's a very new/clean machine that I just built last week.

When I start bgShell it looks like it's going to work, but as soon as I do something (i.e. type and hit enter) it crashes with the following error:

Problem signature:
Problem Event Name: APPCRASH
Application Name: BgShell.exe
Application Version: 1.0.0.0
Application Timestamp: 47f02fd6
Fault Module Name: ntdll.dll
Fault Module Version: 6.0.6001.18000
Fault Module Timestamp: 4791adec
Exception Code: c0000005
Exception Offset: 0000000000047960
OS Version: 6.0.6001.2.1.0.256.6
Locale ID: 1033
Additional Information 1: d169
Additional Information 2: 274489c7e8c7856a0e4ae0b817e3eb56
Additional Information 3: 7f6a
Additional Information 4: b758d997a347ee4da2d613b4934d7e80

Read our privacy statement:
http://go.microsoft.com/fwlink/?linkid=50163&clcid=0x0409

Any ideas?

Thanks,
Chris
Thursday, April 24, 2008 10:11:46 AM (Pacific Daylight Time, UTC-07:00)
sorry to be stupid, but how do I get going with this?
I've copied the autoit dll to my windows dir and it's registered. I've put the Microsoft.BgShell_profile.ps1 in my powershell profile dir. If I execute it from a PS session I don't get an error.
Now what?
If I run BgShell.exe from PS or double-click in Explorer, I just get "BgShell has encountered a problm and need to close"
am I missing something obvious?
OS in Windows Server 2003, running as a local admin.
moff
Monday, April 28, 2008 8:27:45 PM (Pacific Daylight Time, UTC-07:00)
Hmm, there seems to be an issue on some systems. I haven't had any luck tracking it down yet, though. I'll keep on looking.
Name
E-mail
Home page

Comment (Some html is allowed: b, blockquote@cite, em, i, strike, strong, sub, super, u)  

Enter the code shown (prevents robots):