Someone asked on the PowerShell Newsgroup about writing Advanced Functions, and specifically:
looking for a … guide to putting together an advanced function that is visible and usable every time I start Powershell. By visible I mean that when I do a ‘get-command’ I want my [advanced function]s to be listed alongside all the regular cmdlets. What makes that possible? ... what do I need to do to make that happen? Whats the difference between an [advanced function] and a module?
There are lots of articles on the Microsoft PowerShell team blog about both topics, but it seems there’s not really been any sort of step-by-step written, so I posted this to the newsgroup, and since the person who asked the original question said he found it useful, I figured I’d share it here…
Read the rest of this entry »Have I mentioned lately how much Oisin Grehan (a.k.a.: x0n) rocks? He discovered that in PowerShell 2 we can now define our own custom type accelerators. A “Type Accelerator” is the thing that lets you write [regex] instead of [System.Text.RegularExpressions.Regex], and they save a lot of typing, but in order to keep the name space clean, there aren’t very many of them predefined right now.
Thanks to Oisin’s discovery, I’ve written a module to make it trivially easy to create your own custom type accelerators in PowerShell 2. I’ll add a few more details here in the morning, and I’ll probably add a simulation of a “using” statement to the script (although you’ll practically never want to use it), but for now, here’s the script … the new CTP3 Get-Help will tell you everything you need to know.
Maybe I should try that New-CommandBlogPost thing that James has been hawking over on the PowerShell team blog…
I’ve updated the PoshCode script module to support CTP3, and added a -limit parameter to the Get-PoshCode cmdlet so you can specify how many items you want retrieved in the case where there are a lot of matches for your search terms — by default the limit is 25.
You’ve always been able to pass a LIST parameter to the API, and get more results by specifying a higher number. But it never worked with the “path” notation (until now).
That is, you used to be able to do:
To make the API a little easier to use I’ve enhanced it just now:
So, you can use any of these URLs:
There are a lot of search results for “start” ... feel free to play with enhancing the PoshCode module, or incorporating this into your apps, etc.
[new] I should add that you don’t have to specify the limit or page number. By default you’ll get the first 10 items, which should be enough.
By default Get-Command used to return only apps, scripts in your path, and cmdlets… The new CTP3 default invocation includes functions. This is mostly a recognition of the increased power of functions with the arrival of that advanced function features (formerly known as script cmdlets).
Advanced Functions is the new name for what was called “Script Cmdlets” in CTP2. Instead of adding a CMDLET keyword to the language, we now have a [CmdletBinding()] attribute which can be specified in your functions —just before the PARAM block— which will enable all of the features which were exclusive to CMDLETs in CTP2. NOTE: Unlike in C#, the parentheses in [CmdletBinding()] are REQUIRED to differentiate it from PowerShell’s type notation.
I will write an entire article about Advanced Functions soon, because there is a lot to write about, and after struggling with them for several hours today, it’s clear that the about * documentation for them is mostly wrong and misleading. The PowerShell team blog post about Advanced Functions has some working examples, so start there and in the release notes (none of the about_functions_advanced samples will run — I wrote a bug about this, please vote for it if you agree).
This is, without a doubt, my favorite feature so far. You can embed help for functions in comments inside the function block, and Get-Help will find and parse it. Not only that, but your functions get automatic implementation of the -? parameter, bringing script functions closer to equality with compiled cmdlets, in terms of user experience.
You can now have two snapins or modules loaded which export the same cmdlets (or different ones with the same name). PowerShell resolves to the last one loaded by default. You can run previously loaded ones that have been hidden by specifying the full namespace\cmdlet path.
There has been a complete refactoring of the module system such that the environment variable and default Module folders have been renamed, and the cmdlets as well (Add-Module becomes Import-Module and New-Module). The “Module Metadata” support has been finished, so you can create .psd1 metadata files which wrap modules and expose additional features. Thanks to the data in those Metadata files, Get-Module now returns much more information about modules, including the author’s name, copyright info, etc. This is another area where I’ll have a whole article about the new functionality up soon, as an update to my former article about modules.
It’s not my intention to rewrite the release notes here… I just wanted to call attention to some of the stuff that’s most interesting to me. You should definitely read the release notes
In a sense, we had PSEvents in CTP2. But in this release they’ve been beefed up, renamed a little, and are become a very useful way for cmdlet authors to expose functionality (you can create your own system-level events which users can write scripts to handle and target).
I’m not really sure this counts as improved over CTP2, but a lot of people seem to be unaware that PowerShell v2 now supports the C#-like try{ ... } catch { ... } finally { ... } block, and allows you to specify multiple exceptions to be trapped by a single catch statement (I wish C# would implement that).
There are two new parameters to PowerShell:
-WindowStyle This lets you execute PowerShell “Hidden” or at least “Minimized” so that your startup or scheduled tasks don’t need to pop up windows that interrupt the user! Hurray! In fact, not only can you launch PowerShell hidden, you can hide the running host window by just running a PowerShell instance in it (it stays hidden even after PowerShell exits — that might be considered a bug, but I’m not really sure what I think of it). This would be most useful if you were trying to do GUI stuff in your scripts, but I’m sure you can think of other uses… here’s an example (IAA= is just a space, encoded).
It even works in DOS:
-ExecutionPolicy You can override the ExecutionPolicy on the command line. This is very interesting (and rather worrying). It’s my opinion that this option completely breaks the Execution Policy system because you don’t have to be elevated/administrator to use the flag.
What I’m trying to say is that in a business environment, where users are not administrators on their own systems, this flag seems to allow users to ignore the administrator’s script execution policy, and even modify their default shortcuts to just start with whatever setting they prefer. Currently (in v1 and v2) the Set-ExecutionPolicy cmdlet requires administrative rights (and an elevated console, on Vista), but this commandline argument means that anyone can just run PowerShell -EP Unrestricted to get around that.
This seems to render the setting a lot less useful, since it only applies if the user doesn’t know they can override it, or if the setting is unrestricted enough that the user doesn’t feel constrained by it. My guess is that the ExecutionPolicy parameter should either disappear, or be constrained to making the policy more restrictive than the default. Here’s my scary batch/vbs script:
If you have an opinion, vote here
Formerly, comparisons of objects of type [char] (characters) were done as integers (against the unicode character value), but in CTP3 characters are supposed to behave as text, basically the same way strings do when it comes to case-insensitive comparison (except that, to keep them compatible, you must specify -IEQ to compare insensitive). This works fine in a case like: ([char]'a') -ieq 'A' but inexplicably fails for ([char]'a') -ieq ([char]'A') … which leads me to believe the team has simply hard-coded an exception for the CHAR-to-STRING comparison, and missed CHAR-to-CHAR. I wrote that up too, and hope you’ll take the time to agree or disagree (a couple of people in IRC mentioned that after this strangeness they just want it back the way it was).
I’m sure I’ll have more to write here tomorrow …
[new] EDIT: We found out this evening that it was suppose to ship tomorrow, but isn’t going to anymore because they heard about a (possible) bug and are delaying release to investigate (and fix it).
[new] Edit: Someone suggested I should link to the required PoshCode scripts:
Wouldn’t it be cool to be able to “require” those like a ruby GEM?