Saturday, January 24, 2009

More on PowerShell’s #Requires Statement

I recall the moment of amusement when Jeffrey Snover revealed the #Requires PowerShell statement when the first release of PowerShell V2 occurred. It had been in PowerShell V1, but was a very tight secret. As it turns out, with V2’s beta, the #Requires statement had additional functionality, as I pointed out in a recent blog post.  With the release of V2 coming sooner rather than later, the question is whether this statement is rich enough (and whether it can get improved in V2). But let me explain what I mean by that.

The concept that a script or even a function/cmdlet requires some set of pre-requisites is obvious. If, for example, I have a script that relies on the Quest AD cmdlets, then I’d like to impose a rule that says the script needs those cmdlets. There’s no point me running any script that requires something not present on my system. I belive I should not only be able to describe this requirement, and that autohelp should provide that information.

The #Requires statement come some way towards meeting this general requirement. But I think it needs more than that. For me, the question becomes: what does a script need to ‘require’ and more importantly, how does it signal that need? As I see it, that means two separate questions: what do you NEED, distinct from how to express that requirement.

The second question taken first – I am not sure that just using the '#Requires statement is enough. As I think about it the need should be expressed in Powershell autohelp. Autohelp is that set of instructions that you can put at the start of a function, module or script that can leter provide help for users of your code. I realise that the intention of autohelp was to, oddly enough, help. It seems to me that this can also be used to express the need that chunk of functionality  might have a module/script/function for some pre-req. So I think that the should be a .REQUIRES statment in auto help, for example:

  1. <# 
  2. ... 
  3. .Requires 
  4.     VERSION 2 
  5.     MODULE Quest-ADTools 
  6.     DLL tfl.reallycoolDLL.dl
  7.     ELEVATION
  8.     ASSEMBLY globalknowledge.powershell.ocs2007r2
  9. ... 
  10. #> 

You should not only document the requirements but demand them in this Autohelp block (ie the autohelp block is more than just documentation). This would be a very elegant solution.

But separate to HOW you express the pre-reqs, I think V2 needs to expand what #Requires provides. Specially, I’d like to see the #REQUIRES statement expanded to allow you to specify:

  • A specific module
  • Elevation (should it need to run elevated)
  • A specific named DLL
  • A specify Assembly (i.e. in the GAC)
  • etc

I’d like to see the advanced function’s autohelp block be really useful!

Technorati Tags: ,


Glenn said...

I was with you 99% of the way... I agree that as you get more advanced and your script library matures. There is a painful need to proclaim and force dependencies for scripts.

You lost me in auto-help... Yes it is very handy especially when used in conjunction with <# #>, but that is for help documentation.

[CmdletBinding()] feels like a more natural location for such decelerations. While we're at it #requires in general should probably be their as well, but that would break v1...

Better or worse I think just getting the params added to #Requires would be a giant step!


aleksandar said...

Even more elegant would be to use just the #requires statement and, if you use inline script help, get automatically REQUIRES section when you do get-help.