Blogroll

Search

Did you know you can have “advanced functions” with filters too?

August 10th, 2011 by Karl

In PowerShell to make a function an advanced function you typically decorate it with [PSCmdletBinding()] or attach a [Parameter()] to it, and now you get the full features of cmdlets available to you. the $pscmdlet variable, ability to support –whatif and –confirm as well as the ability to have multiple parameter sets, and put validation conditions on parameters and various other “full featured citizen” cmdlet abilities.

I don’t know if you know but the standard cmdlet has 3 different blocks, Begin , Process and End, begin happens at the beginning, while Process every time the pipeline iterates, and end well at the end. To support pipelining you have to do everything in the process block. However instead of defining a function you can use the filter keyword which basically is an automatic function so instead of

function myfunc
{
  process { “hello pipeline object $_ “ }
}
1..10 | myfunc

you can simply do

filter myfilter
{
“hello pipeline object $_ “
}
1..10 | myfilter

well I wasn’t sure whether you could use “advanced functions” with the filter keyword but after a little experimenting apparently you can.

filter advancedfilter {
  param([parameter(valuefrompipeline=$true)]$InputObject)
  "hello from advanced filter pipeline object $InputObject"
   }
1..10 | advancedfilter

Posted in Powershell, PSV2 | No Comments »

H20 – hashtable from scriptblock to powershell Objects

April 21st, 2011 by Karl

Here is another function in my endless Quest at producing Helper functions that simplify doing complicated stuff in PowerShell and that keeps it in the pipeline.

function h20([scriptblock]$sb, [switch]$dontkeepreference = $false)
{
 begin {}
 process{ if ($sb -ne $null)
                {
                  $local:obj = $_;
                  $local:ht = &$sb;
                  if ($local:ht -is [hashtable])
                    {
                        if (!$dontkeepreference) { $local:ht.".." = $local:obj; }
                        New-Object PSObject -Property $local:ht
                    }
                 }
                  if ($local:ht -is [object[]])
                    {
                    $local:ht | where { $_ -is [hashtable]} | % {
                            if (!$dontkeepreference) {$_.".." = $local:obj}
                            New-Object PSObject -Property $_ }
                    }
                }

 end{}
}

Now this function processes the scriptblock for each item coming through the pipeline giving you the opportunity to create one or more Hashtables, and it will take whatever Hashtables you create and create nice PSCustomObjects and pop them out the other side of the pipeline.

Here are some examples

1..10 | h20 { @{karl = $_;dude = $_+1} }

modify the incoming data with an expression

gps | h20 { @{name = $_.processname; mem = $_.workingset / 1MB} }

easily flatten data with subexpressions

get-command -verb get | h20 { @{ name = $_.name;  type = $_.commandtype; synopsis = ($_ | get-help).synopsis ;   } }

don’t lose the incoming pipeline data when you don’t explicitly include it in the hashtable. Its automatically stored in the property “..”
below, while the expression just includes string properties from the get-help object, the actual commandinfo object is stored in “..”

 $a = get-command -verb ("get","set") | h20 { $_ | get-help | % { @{name = $_.name ; synopsis = $_.synopsis} } }
 a[0].".."

Posted in Powershell | No Comments »

Attaching Custom MetaData to Functions

February 1st, 2011 by Karl

One nice thing about object in dotnet, including ETS PowerShell objects is the ability to really store MetaData with a variety of techniques, then later you can walk up to an object programatically, and ask it about itself.

However there really isn’t a way to do this out of the box when it comes to Functions (other than finding out the intrinsic attributes of functions.

One common way is with DotnetAttributes. Most know that there were Certian Dotnet Attributes added to PowerShell V2, such as [Parameter()] and [CmdletBinding()]

A little known secret is that you can actually use ANY dotnet attribute. And as they aren’t really attached to objects like Attributes are on a real dotnet objects so they are totally benign, you just have to work out where to attach it and which attributes to use.

You can attach them to the Function’s ScriptBlock, or its parameters. I find for general MetaData storage the scriptblock is the best place to put it.

Next what attribute. Well you could make your own in C# and use add-type, or you could just pilfer some that are part of the dotnet framework that have agreeable names. Remember they are benign in this context so it really doesn’t matter.

function demo-attributes
{

[System.Configuration.SettingsDescription({
    @{something = 1;
      this = 'that';
      array = (1,2,3);
      sub = @{ sub1 = 1 ; sub2 =2 }
    }})]

[CmdletBinding(DefaultParameterSetName="noname")]
param (
 [Parameter(Position=1,mandatory = $true)]
  [string]$something 

)
1..10
}

So you’ll notice i choose a simple advanced function that already has some dotnetattributes on it, You don’t have to, it could be a simple function, or even an unnamed scriptblock.

in this case used the dotnet Attribute System.Configuration.SettingsDescription and passed in a scriptblock that returned a hashtable containing a complex object.

So this is all good, but the purpose of MetaData is to be able to read it later. My strategy involves

  • Find the attribute on the function’s scriptblock
  • Grab the string from it
  • Put it in a Powershell Data Language DATA section to ensure its content can only be benign
  • Evaluate it to get the complex objects back
$settingstext = ((dir function:\demo-attributes).scriptblock.attributes |Where-Object { $_.typeid -like '*settingsdescription*'  }).description
$settingsscriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("DATA {" + $settingstext + "}")
&$settingsscriptblock

Posted in Powershell | No Comments »

Run In Module

December 10th, 2010 by Karl

Have you even been working on a a module, call a function, but then get frustrated because you can’t get to that $script:something.

Well modules and scopes is an interesting problem. and when you something from the command prompt of a function OUTSIDE of the module, you can’t see things. This can make working and debugging on things (outside of breakpoints etc) difficult.

Well thankfully there is an undocumented feature on the & call operator

so instead of

& { … }

you can pass in a reference to a module and run a scriptblock

& (get-module somemodule) { … }

and the scriptblock will be run in the modules context..

Well that can be tedious so i’ve made a function called invoke-scriptblockinmodule , with the alias RIM
that allows you to do

rim somemodule { … }

and after you have specified the modulename once, it remembers it so you can just do

rim { … }

Enjoy,


function invoke-scriptblockinmodule
{
[CmdletBinding(DefaultParameterSetName="noname")]
param (
  [Parameter(ParameterSetName='noname', Position=1, mandatory = $true)]
  [Parameter(ParameterSetName='hasname', Position=2,mandatory = $true)]
  [scriptblock]$scriptblock ,

 [Parameter(ParameterSetName='hasname', Position=1)]
  [string] $modulename = $null

)
#TODO: do get-module first and make sure its valid before invoking with &

if (!$global:prossertools) { $global:prossertools = @{} }
 if ($modulename) {
                    $global:prossertools.invokescriptblockinmodulecachedname = $modulename;
                    $module = get-Module ($global:prossertools.invokescriptblockinmodulecachedname)
                    & $module $scriptblock;
                   }
    else {
         if (!$global:prossertools.invokescriptblockinmodulecachedname ) {
            write-host "no name provided or currently cached"
            }
         else {
         $module = get-Module ($global:prossertools.invokescriptblockinmodulecachedname)
            & $module $scriptblock;
        }
    }

}
set-Alias rim invoke-scriptblockinmodule

Posted in Powershell | No Comments »

Where-in and Where-Property-in

November 15th, 2010 by Karl

I’m back again in my quest for general purpose functions slicing and dicing objects and keeping it all in the pipeline.

So in PowerShell you often use the pattern in the pipeline of get-something | where { $_.property -eq $null }

However often you need something more complex. In one case you want to do something similar to to a SQL in.. like select * from mytable where mycolumn in (1,2,3) or such.

in powershell you can do this relatively easily with -CONTAINS but the semantics can be confusing as it seems backwards to us. Here is an example

get-process | where { ("svchost","outlook","powershell" ) -contains $_.processname }

but what if you want to express this differently, and you also want to be able to apply expressions

where-in and where-propertyin are filters that allow to pass through pipeline object that are in a specified array/collection, or that have a property that is in an array or collection. They also can take a scriptblock that can be used to implement a comparision when the relationship isn’t exact. in that scriptblock the variable $__ is created to represent the item in the collection being compared with the pipeline $_ object.

here are some examples

$a = (1..10) , (1..10) | % { $_ } #create some sample data
$a | Where-in (3,4,8)

and with properties

gps | where-propertyin ("powershell","svchost") processname

in hindsight the following would syntax would be a little more intuitive (but its not implemented in this function but could be )

gps | where-property processname -in ("powershell","svchost")

and if you want to graduate to actual expressions with scriptblocks, in adition to the usual PIPELINE object $_ , i added $__ which is the object from the IN list to compare with. Here are some examples.

gps | where-in  ("power","s")  { $_.processname.startswith($__) }

and with properties

gps | where-propertyin ("power","s") processname { $_.startswith($__) }

I also like to use ?. for the alias for this..

and now for the functions themselves

function where-in {
[cmdletbinding()]
param (
[parameter(mandatory = $true,position = 1)]
[system.Collections.IEnumerable]$collection,
[parameter(position = 2)]
[scriptblock]$predicate ,
[parameter(valuefrompipeline = $true)]
$pipelineobject
)
    process {
        if ($predicate) {
            foreach ($__ in $collection) {
                if(&$predicate) {
                    write-Output $pipelineobject
                    break;
                }
            }
        }
        else {
            if ($collection -contains $pipelineobject) {
            write-Output $pipelineobject }
        }
    }
}
set-alias ?in where-in

function where-propertyin {
[cmdletbinding()]
param (
[parameter(mandatory = $true,position = 1)]
[system.Collections.IEnumerable]$collection,
[parameter(mandatory = $true,position = 2)]
[string] $propertyname,
[parameter(position = 3)]
[scriptblock]$predicate ,
[parameter(valuefrompipeline = $true)]
$pipelineobject
)
    process {
        if ($predicate) {
            foreach ($__ in $collection) {
                $_ = $pipelineobject.$propertyname
                if(&$predicate) {
                    write-Output $pipelineobject
                    break;
                }
            }
        }
        else {
            if ($collection -contains $pipelineobject.$propertyname) {
            write-Output $pipelineobject }
        }
    }
}
set-alias ?.in where-propertyin

Posted in Powershell | No Comments »

Silverlight IDE possiblities for DekiScript, Javascript, PowerShell, Ironpython, Ironruby and above.

July 8th, 2010 by Karl

I’m a huge fan on Mindtouch, it’s awesome RESTful Web Orientated Architecture with Dream that makes REST a pleasure but also in a powerful and performant manner with a great async coroutine architecture, and their main product has a build in language Called Dekiscript and i wanted to through together a proof of concept editor for it and that is what is below, but read also afterwards about the possibilities beyond a niche language for one product albiet a great product.

Here is a Link to where i have the interactive demo

Here is a screenshot

and

Here is a Link to where i have the interactive demo
PowerShell

A PowerShell web front end that can talk to the backend using ShellTools PowerShell Job Server , or PoshBoard or PowerGui Pro. With intellisense data coming from your servers, as well as abilities to use Siverlight isolated storage for script repositories/snippets or get hook up to a web based service for that whether it be Evernote, google docs or such?

HTML
Imagine it as an altnerative editor for the SOURCE version, whether for your CMS, with CKeditor, WordPress or such? a nice editor, with rich features, and code completion?

Javascript
A javascript editor that runs real in the browser. where code completion is running against the real life objects you are working with. the ability to quickly run and prototype javascript right there and then, or maybe even include it as an optional interface inside a firefox plugin or firebug or such?

IronRuby , IronPython, Script for .Net , Jint and other DLR languages
With various techniques and gestalt bring other languages into the browser and actually enjoy the code sculpting process right there in the browser without a second class citizen experience typical of web editors. Also with IronRuby and the like you could have macros and all running right there and then and with

Here is a Link to where i have the interactive demo

Posted in Powershell | 3 Comments »

PowerShell running in Dotnet 4

June 26th, 2010 by Karl

Back in the Dotnet 4, VS.NET 2010 Beta days i threw together a PowerShell console host compiled against dotnet 4 but really didn’t do anything with it. It seems that there is a bit of demand for it. So here it is. You can download it and start using it.

It at least allows you to interact with dotnet 4 code in-process. Its not going to turn PowerShell into a dotnet 4.0 citizen as really PowerShell is in what I call “Dotnet 1.9″ style. Its going to be very awkward to interact with Dotnet 4 dynamic objects without some nice helpers but at least it IS possible.

Also I very much doubt that this will be able to be used as a remoting server. However you could have a dotnet 2, PS V2 runspace call this to do some processing. Tedious but at least possible.
Background jobs also aren’t going to run in Dotnet 4, though they possibly may if you manage to rename the original powershell.exe and put this one in its place. I know on windows 7 the ability to do is locked down, but it might be possible on other OSes.

All Command line options should work other than Console files.

Download NOW!!!

Notice the CLR version above?

Download NOW!!!

Just download it, and if with IE make sure you “unblock” the zip, then unzip it and run it anywhere you have PowerShell V2 installed. Enjoy.

Thanks to @jstangroome on twitter to helping motivate me get this out.

Karl Prosser / ShellTools LLC.

Posted in Powershell | 2 Comments »

Portable PowerShell with Portable PowerShell ISE.

June 16th, 2010 by Karl

After a long fight we finally conquered making PowerShell ISE portable also.

Portable ISE

A new Beta of Portable PowerShell should be out by the end of the week that has ISE support and to celebrate we will open up the Beta group to another 100 users.

Go to http://groups.google.com/group/portable-powershell-beta to sign up to the google group. However be aware that the introduction words contain old info , and some bug in google groups is preventing me from updating it, however we’ll send out emails with the relevant information in it.

Posted in Portable PowerShell, Powershell, Shell Tools | 1 Comment »

DSLs / DSVs in PowerShell – Presentation at LangNet 2009

May 14th, 2010 by Karl

At LangNet 2009 last year i presented on DSLs in PowerShell. I wrote up a couple example ones . One which the presentation is in a kind of mini PowerPoint and another where i automated the awesome MindManager mind mapping product with COM to dynamically produce Mind Maps with a PowerShell DSV. Also I presented fellow MVP Jaykul’s awesome and extensive PowerBoots DSL that is one of the best and pithy ways to produce powerful interactive UIs in a scripting language ever.

Here is a link to the Silverlight version of the Video, and to the WMV (95MB) version. The Video is about 12 minutes and audio doesn’t kick in for 30 seconds.

Would anybody like me to post the code to the examples i presented?

-Karl

Posted in Powershell | No Comments »

Passing true dotnet nulls for strings to APIs from powershell

May 7th, 2010 by Karl

There is an issue that can basically prevent you from calling certain dotnet apis.

Basically the trick is just to make a class that’s .tostring() returns a null, and then when you pass that to an api through powershell that takes a string powershell will convert the class to a string() thus calling your code that returns a null..

namespace testnullD
{
public class nulltest
{
public nulltest(){}
public override string ToString() {return null;}
}
}

Here is a complete example you can use.

$a = @"

using System;
namespace ClassLibrary1
{
#proof of concept
public static class Class1
{
public static string Foo(string value)
{
if (value == null)
    return "Special processing of null.";
else
    return "'" + value + "' has been processed.";
}
}
}
"@

$b = @"
using System;
namespace testnullD
{
public class nulltest
{
public nulltest(){}
public override string ToString() {return null;}
}
}
"@
add-type $a
add-type $b
$psnull = new-object testnullD.nulltest
add-type $a
[ClassLibrary1.Class1]::Foo($null)
[ClassLibrary1.Class1]::Foo($psnull)

Posted in Gotchas Etc, Powershell | 1 Comment »

« Previous Entries Next Entries »