Creating Generic Types in PowerShell

[Edit 02/01/2012 - PowerShell added support for this in Version 2 via the following syntax:]

PS > $r = New-Object "System.Collections.Generic.List[Int]"
PS > $r.Add(10)
PS > $r.Add("Hello")
Cannot convert argument "item", with value: "Hello", for "Add" to type "System.Int32"
(...)
At line:1 char:1
+ $r.Add("Hello")
+ ~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

(Original Post)

Although the New-Object cmdlet is powerful, it doesn’t yet handle creating generic types very elegantly.  For a simple parameterized type, you can use the syntax that the .Net framework uses under the hood:  

Accepting Pipeline Input in PowerShell Scripts and Functions

This has been coming up a bunch in the last little while, and I realized that I haven’t had a very good resource to point people to when they ask how to make a script or a function deal with pipeline input.

Scripts, functions, and script blocks all have access to the $input variable, which provides an enumerator over the elements in the incoming pipeline.  When pipelining is a core scenario, though,  these constructs also support the cmdlet-style statement blocks of begin, process, and end.  In those blocks, the $_ variable represents the current input object.  Along this line, a Filter (get-help about_Filter) is just a shorthand representation of a function whose body is composed entirely of a process block.

Back – and Desperately Avoiding Jet Lag

After visiting 5 countries (Italy, Croatia, Greece, France, Spain,) 2 micro-states (Monaco, Vatican City,) and returning with a connection in Sweden, I’m back – and now 367% as worldly!

The vacation was truly eye-opening.  My only previous international experience (aside from growing up in Canada, and moving here to the United States) was a low-budget resort trip in the Dominican Republic.  That trip gave me a filtered taste of a different culture, but had nowhere near the impact of a Mediterranean cruise around Europe.

More P/Invoke in PowerShell

In my last post, I gave an example of how to use P/Invoke through PowerShell  to implement functionality not immediately available via the .Net framework.  My example was to get the owner of a process, and Abhishek wisely pointed out that  this is easier through WMI.

So here’s another example.  It’s actually the one I had written originally, but it didn’t give me an opportunity to illustrate [Ref] parameters, or [Out] parameters via P/Invoke.

Get the Owner of a Process in PowerShell – P/Invoke and Ref/Out Parameters

An often asked question in the Managed Code world is “How do I get the owner of a process?”  The same question is starting to come up around PowerShell, and the answer to both is:

The .Net Framework does not yet support this API, so the solution is to write the P/Invoke calls into the Win32 API yourself.

This gets a little more complicated with PowerShell, though, since we abstract the .Net framework one level even further. 

Set-Location, and [Environment]::CurrentDirectory

One question that comes up frequently is, “Why does PowerShell not change its [System.Environment]::CurrentDirectory as I navigate around the shell?

One of the difficult aspects of this comes from the fact that PowerShell supports multiple pipelines of execution.  Although it’s not directly exposed yet, users will soon be able to suspend jobs to the background, and other concurrent tasks.

The current directory affects the entire process, so if we change the directory as you navigate around the shell, you risk corrupting the environment of jobs you have running in the background.

PowerShell Solves a Mystery

One of Raymond Chen’s readers recently noticed that Google purchased AdWords for Raymond’s name.  The destination of the sponsored link?  http://www.google.com/jobs :)

This came up on our internal bloggers alias, so people started poking around to see what other bloggers / blog readership had outstanding “job offers.”  Not being one for repetitive, manual computer labour, I let PowerShell definitively answer the question.

In a temporary Outlook message, I expanded the alias so that it listed the names of all members.  I saved that into a text file, and ran the following script:

How Do I Search the Registry for a Value in PowerShell?

The question came up recently in an internal discussion list, “How do I search the Registry for a value in PowerShell?

In the FileSystem, we have the select-string cmdlet to do the hard work for you.  We don’t have the equivalent yet for other stores, so unfortunately the answer is to write ‘grep’ from scratch.  It’s manageable, though.

The key here is to think of registry key values like you would think of content in a file:

“Simple Where” as a Where-Object Shortcut

The Where-Object cmdlet is incredibly powerful, in that it allows you to filter your output based on arbitrary criteria.  For extremely simple filters (such as filtering based only on a comparison to a single property,) though the syntax can get a little ungainly:

get-process | where { $_.Handles -gt 1000 }

For this type of situation, it is easy to write a function to offload all of the syntax  to the function itself:

get-process | wheres Handles gt 1000
dir | wheres PsIsContainer

The following snippet implements the “simple where” functionality:

Current Working Directory with PowerShell and .Net Calls

A question that occasionally comes up is, “Why doesn’t PowerShell change the [Environment]::CurrentDirectory while I navigate around the shell?”  This is always in the context of using a relative file path while working with the .Net framework.

One of the difficult aspects of this comes from the fact that PowerShell supports multiple pipelines of execution.  Although it’s not directly exposed yet, users will soon be able to suspend jobs to the background, and other concurrent tasks.