Just Released: Advanced Reporting PowerPack

I just published a brand new PowerPack to the PowerPack Library called the Advanced Reporting PowerPack.  If you’ve been keeping your eyes on the Virtualization EcoShell project as well as PowerGUI, you may have already come across this PowerPack because I released it there first.

The Advanced Reporting PowerPack allows you to generate HTML reports with collapsible nested groups for any set of data in PowerGUI.  Think VMs, Snapshots, AD Users or Groups…you name it.  If you can get the data into a grid in PowerGUI, you can generate a nice HTML report using this PowerPack.  The only UI element this PowerPack adds to PowerGUI is a common action called “Create report…”.  This action does all of the heavy lifting to generate a cool HTML report for the items you have selected.

Want to see what how to get started using this PowerPack?  Watch this screencast:

If you would prefer to watch a higher resolution version, you can watch the screencast in flash format here.

This is only the first release of advanced reporting functionality in PowerGUI and already it’s really powerful.  Still, there is room for improvement so if you have any feedback, please share it with me in my comments or on the PowerGUI Forums so that I can consider it for the next release!

Thanks and enjoy!

Kirk out.

Share this post:

Hanselminutes Show #162: PowerShell 2.0

While I was at tech·ed 2009 last week I ran into Hal while he was waiting for Scott Hanselman to finish up a game of Rock Band so that he could participate in a session for Scott’s popular podcast, HanselminutesHal asked me if I wanted to participate, to which I said absolutely yes, and the result is a 35 minute discussion with Hal, Scott and I about PowerShell 2.0.

Hal’s an IT pro, and while I work with IT pros a lot these days I have a developer background, so we were able to speak to both sides of the fence and talk about why you should pay attention to PowerShell whether you’re a software developer or an IT pro.

That recording is now live, so if you want to hear it head over to Hanselminutes Show #162: PowerShell 2.0, and let me know what you think afterwards.

Kirk out.

Share this post:

Create custom nodes easily with the Active Directory PowerPack and PowerGUI

Here’s a great question that someone just posted today on the PowerGUI forums:

I have the latest verions of the Quest AD cmdlets, PowerGUI and the Active Directory PowerPack.  Can I use PowerGUI to search for old computer accounts?  For example: computer accounts that haven’t had their machine account password reset for over three months?

The timing of this question is perfect because the update of the Active Directory PowerPack that I posted two weeks ago allows you to do this without having to write any scripts yourself.  For those of you who want to try this but don’t have the most recent versions of PowerGUI, the Quest AD cmdlets and the Active Directory PowerPack installed, follow those links and download and install those before continuing.  Installation instructions are on the appropriate web pages where necessary.

Once you all of the necessary software installed, here’s what you need to do.

Step 1: Add the attributes you need to the list of attributes retrieved from Active Directory.

There are In the PowerGUI Admin Console, expand the “Active Directory” node and click on “Configuration”.  This will show you the current domain that PowerGUI will gather data from.  You can change this if you like, however you don’t need to unless you want to use alternate credentials or connect to another domain.  With the configuration showing in the grid, click on the “Manage default attributes” link.  That will present you with a view something like this:

image

This shows you the current list of attributes that are retrieved for each individual Active Directory object.  This will be initially configured with the default attributes as defined by the Quest AD cmdlets plus a few attributes that are required for the Active Directory PowerPack.  You can add whatever attributes you want to gather here for any of the object types.  To help solve our immediate problem and be able to get a list of computer accounts that have not had their machine account password reset for over three months, we need to add the pwdLastSet attribute for computer objects.  To do this, simply click on the “Add attribute…” action, provide the name of the pwdLastSet attribute in the “Attribute name” field and set the “Retrieve attribute for computer objects” value to True.  When you click on OK, that attribute configuration will be saved and any computer objects retrieved using the Quest AD cmdlets will have that attribute retrieved with them.

Step 2: Retrieve the objects you want from Active Directory and optionally show the attributes you want to filter on.

Once you have configured PowerGUI so that it will retrieve the pwdLastSet attribute for computer objects, you need to get your computers.  You can do this by simply clicking on the “Computers” child node under the “Active Directory” node.  This will present you with a list of computer accounts, showing their Name, Type and DN by default.

With the list of computer objects showing, you can optionally add the pwdLastSet attribute to the view by right-clicking in the column headers and selecting “More…” from the menu that appears.  With the list of all attributes that can be added showing, scroll down until you find the pwdLastSet attribute and check the checkbox beside it.  Then click on OK to save that change and your pwdLastSet attribute will be retrieved with your computer objects from the Computers node.

Step 3: Create a client-side filter to filter out the objects you don’t care about.

With the list of all of your computer objects showing, you can create a filter to reduce the number of objects to those that you need to see.  To do this, click on the Filters button above the column headers.  This will make the filter panel visible.

image

You can use this panel to filter any collection based on the properties of the objects in that collection.  For our particular problem, we want to see computer objects whose password has not been changed in the last 3 months.  We can get that by selecting “pwdLastSet” in the “Property” field, “Less or equal” in the “Operator” field, and selecting the calendar date three months ago in the “Value” field using the calendar control.  Once that is set, click on the “Apply” button to apply the filter and your list of computer objects will be filtered to only show those whose machine passwords haven’t changed in the last 3 months.

Step 4: Make the newly filtered data set available in its own node.

Now that you have the data you’re looking after, your “Computers” node is now configured to always show you the filtered list because PowerGUI remembers the filters you apply to nodes.  You might not like this configuration, preferring to have a separate node to view the data that you want.  Fortunately, PowerGUI lets you do create that easily too, and you still don’t have to do any scripting.  To create a separate node that lets you get the same data set, simply click on the “Save As…” button in the filter panel.  This will allow you to save the script from the Computers node with the filter you have created automatically applied as a client-side filter for that script.  Simply give the new script node a name (something intuitive like “Computers with old passwords” will do), and click on OK to save the new child node.  Then you can click on the “Clear All” button in the filter panel for your “Computers” node because that filter will no longer be needed.  Now click on your new node and you’ll get the list of computers you are after, and it will look something like the screenshot below.

image

Step 5: Make your work reusable at any time by taking it one step further.

At this point you have successfully created a new node that gets specifically the data you were looking for and you didn’t have to do any scripting to get it, which is great!  You can make it a little better still though.  For our specific problem that we’re trying to solve, we created a new node that reports any computer object with a machine account password that hasn’t been changed within 3 months from today.  But tomorrow that will be come 3 months and 1 day.  The next day that will become 3 months and 2 days.  What if you want to customize the node so that it reports computers whose machine accounts have not had their passwords changed in the last 3 months, no matter what day you click on it?  For that to work you will have to do a minor script modification.

Right-click on your new “Computers with old passwords” node and select properties.  This will show you the script used to retrieve your computers and filter the list.  At the very end of that script, you will see something like the following:

func_Computers | Where-Object {
    $_.'pwdlastset' -le [System.DateTime]"2009-02-08"
}

The Where-Object cmdlet contains the filter that is excluding any computers whose pwdLastSet attribute is greater than 3 months from the day we did this (for me that that’s February 8, 2009 since I created the node on May 8, 2009).  To change that filter so that it always works using a date 3 months earlier than now, you simply need to replace [System.DateTime]”2009-02-08” with (Get-Date).AddMonths(-3).  That changes the end of our script to this:

func_Computers | Where-Object {
    $_.'pwdlastset' -le (Get-Date).AddMonths(-3)
}

That’s it!  A simple replacement of the filter condition and you’re off and running with a brand new node designed to meet your specific needs with PowerGUI, the Quest AD cmdlets and the Active Directory PowerPack!

In a future article I’ll show you just how simple it is for you to take a collection of extensions to PowerPacks that you have created like this and package them up in a PowerPack so that you can share them with other users in the Community as well!

Enjoy!

Kirk out.

 

Share this post:

The Active Directory PowerPack, the Quest AD cmdlets, and what can happen when you change public object interfaces or cmdlet parameter attributes in PowerShell

This is about what can happen when things go wrong and what not to do so that things don’t go wrong.

In case you didn’t know, I work at Quest Software on the PowerGUI Team.  My position is rather unique because I work exclusively with Windows PowerShell, and I don’t think there are too many jobs out there that offer that experience.  The main focus of my job is to create and extend PowerPacks, which are collections of PowerShell scripts that are packaged together to define an extension to the customizable PowerGUI Admin Console.  The scripts in the PowerPacks I create range anywhere from the extremely simple (one cmdlet or function call) to the very complicated (a script that calls into one or more functions that span many thousands of lines of PowerShell script).

Among others, one of the PowerPacks that I manage is the Active Directory PowerPack.  The Active Directory PowerPack provides a management interface to Active Directory, and it uses the Quest AD cmdlets in its PowerShell scripts to do the actual management of Active Directory.  For quite a few reasons1,  I need to explicitly indicate which connection should be used when you use that PowerPack to do something with Active Directory, regardless of what it is you are doing.  This means I am absolutely dependent on being able to determine what connection should be used in any script that is included in the PowerPack.  For scripts that are used at the beginning of a pipeline I look for the appropriate connection information that is stored globally.  For other scripts that are used later in a pipeline with Quest AD cmdlets I look at the Connection property that is attached to the objects coming down the pipeline.  This model has worked very well until recently when something unexpected happened.

Almost two weeks ago, just after version 1.2 of the Quest AD cmdlets was released, it came to my attention that the Connection property that I am so dependent on was not included on objects in that release.  For those of you who are not developers, this type of change (changing a public interface in an SDK) is very bad news.  It is called a breaking change, and the name is very fitting – the Active Directory PowerPack started breaking all over the place for users who upgraded their Quest AD cmdlets to version 1.2!

Amid a flurry of email discussions between myself and the Quest AD cmdlets team I spent the next week and a bit putting together an update to the Active Directory PowerPack so that it would work despite these changes, basically putting the Connection property there myself if it isn’t there.  At the same time, the Quest AD cmdlets team quickly started work on a 1.2.1 patch release to put the Connection property back in so that scripts outside of PowerGUI that use that property wouldn’t be affected either.  The patch for the Quest AD cmdlets is not available yet, but the updated Active Directory PowerPack, and the updated Network PowerPack which also used the Quest AD cmdlets a fair amount and was therefore susceptible to this change, are now posted in the PowerPack library and available for download.  If you use these PowerPacks, I strongly recommend you download and import the most recent releases of each of these PowerPacks.  Their document page in the PowerPack library contains all of the information you need to upgrade your PowerPacks and get started using the new versions.

Now that I have finished dealing with the impact of a breaking change like this one and the unpleasant work that ensues,  I thought it would be worthwhile to share with others what exactly consititutes a breaking change in a PowerShell cmdlet or advanced function.  The following is a list of 13 rules that you should adhere to when updating your cmdlets or advanced functions if you want to avoid introducing breaking changes:

  1. Do not remove any published parameters that are included in your published cmdlets or advanced functions.
  2. Do not rename any published parameters that are included in your published cmdlets or advanced functions unless you add an alias to the parameter that is the old parameter name.
  3. Do not reduce or remove pipeline support for any published parameters in your published cmdlets or advanced functions that support pipeline input.
  4. Do not remove support for $null input for any published parameters in your published cmdlets or advanced functions that support $null input.
  5. Do not modify the default value for any published parameters in your published cmdlets or advanced functions unless that modification will not change how the command functions in existing scripts.
  6. Do not add a required flag to any parameter in published parameter sets in your published cmdlets or advanced functions.
  7. Do not modify the position of any published parameters in published parameter sets in your published cmdlets or advanced functions.
  8. Do not replace the associated object type with an incompatible type for any published parameters in your published cmdlets or advanced functions.
  9. Do not remove wildcard support for any published parameters in your published cmdlets or advanced functions that have wildcard support.
  10. Do not remove support for building the value from the remaining arguments in any published parameters in your published cmdlets or advanced functions that support building the value in this manner.
  11. Do not remove any of your published parameters from published parameter sets in your published cmdlets or advanced functions.
  12. Do not increase validation restrictions for any of your published parameters in your published cmdlets or advanced functions that have validation restrictions.
  13. Do not modify or remove aliases for any published parameters in your published cmdlets or advanced functions.

Additionally you need to pay attention to the objects that are returned by your cmdlets or advanced functions so that you don’t introduce breaking changes on those either.  The following rules should be adhered to in order to avoid breaking changes on objects returned by your cmdlets or advanced functions:

  1. Do not remove a public property or method.
  2. Do not replace the types associated with a public property or method with incompatible types.
  3. Do not modify the order of the parameters in a public method.
  4. Do not add required parameters in a public method.

Not following these rules means risking breaking production scripts, risking making your customers unhappy, and many other potential undesirable consequences.  Please, if you are seriously trying to add value to the PowerShell ecosystem by extending it with additional commands, pay attention to these rules and don’t introduce breaking changes when you update them!

Thanks for listening!

Kirk out.

1 Reasons why the connection must be explicitly indicated in the Active Directory PowerPack:
1. The Quest AD cmdlets allow you to connect to many different directory services.
2. Opening a connection to a directory service with the Quest AD cmdlets changes a global variable that is used automatically by other cmdlets in the same snapin when you don’t explicitly indicate what connection to use.
3. In PowerGUI you can create or import other PowerPacks that may open their own connections to different directory services using the Quest AD cmdlets, Active Directory or otherwise.
4. In PowerShell, whether you are using the Quest AD cmdlets interactively or invoking a script that uses them, you are likely only working with one set of data from one directory service at a time in a logical manner.  Working in a user interface that is built on top of PowerShell is less restrictive, allowing you to move more freely between multiple data sets from multiple sources (directory services in this case) in what would be considered an illogical manner as far as script creation goes.

Share this post:

Virtualization EcoShell and the VMware Infrastructure PowerPack

Wow, have I been busy.  In case you hadn’t noticed from my blog posts late last year and early this year, I’ve been working very hard at putting together multiple back-to-back updates for the VMware Infrastructure Management PowerPack for the past several months.  This has involved working long hours with many thousands of lines of PowerShell script and figuring out how to do some really cool things with both PowerShell and VMware’s PowerCLI (formerly known as the VI Toolkit).  The end result is always fulfulling, and I’m usually pretty good at setting up the really cool functionality so that I can leverage it in any PowerPack so all my hard work pays off in the long run.

A few weeks ago I finished off yet another update with some really cool new features, however this update isn’t available for the PowerGUI admin console just yet.  That update is coming shortly after we release the next version of PowerGUI, which has some functionality that it is dependent on.  If you can’t wait until then though, you can take a look at the new functionality now as part of the first public beta release of the Virtualization EcoShell that came out on April 15th.

What is the Virtualization EcoShell?  The Virtualization EcoShell is a project started by Scott Herold that was designed to provide an administrative experience that is tailored for virtualization administrators.  It is powered by PowerGUI and comes with a script editor and an admin console just like PowerGUI.  The out of the box experience is different though because it doesn’t come with PowerPacks for Exchange and Active Directory.  Instead it includes functionality that virtualization administrators care most about.  At the moment this is simply the VMware Infrastructure Management PowerPack, but over time this will grow to include other virtualization-related administrative functionality (think: additional VMware features, functionality to work with virtualization platforms from other vendors, and capabilities to extend into important technologies surrounding virtualization such as storage).

If you want a preview of the next generation of the VMware Infrastructure Management PowerPack a little early as well as a look at a new virtualization administration platform, all you have to do is pop over to the Virtualization EcoShell site and download it.  You can install and use it side-by-side with PowerGUI, so you won’t need any secondary systems or a VM to run it on either.  Once you’ve taken a look, let us know what you think or what you would like to see next on the forums!  Your feedback directly influences the features we add, and we’re listening!

Kirk out.

Share this post:

VMware Infrastructure PowerPack 2.1.5 released

The PowerGUI VMware Infrastructure Management PowerPack seems to be really popular with people, so I’ve been spending a lot of time over the past four months significantly enhancing that PowerPack.  Some of the enhancements are things that we wanted to put in and others are things that community members had requested (note to the reader: if you like a particular PowerPack and would like to see it improved, speak up on the PowerGUI Forums…we really take your feedback very seriously! :)).  Today I just finished posting another release of the VMware Infrastructure Management PowerPack with a few more enhancements, and I’m particularly happy with this one.

This release greatly improves usability through the new icons that were added (and I mean *greatly* improves…the value the icons add is huge).  It’s also the first PowerPack release that takes advantage of some really cool Visio scripts that I’ve been working on.  The Visio scripts I’m referring to were largely inspired by Alan Renouf’s vDiagram script, although the Visio script I ended up with doesn’t look anything like the original.  I’m itching to talk more about those scripts, but I want to write a blog post specifically on that topic so watch for more on this soon.  For now I’ll simply point out that to use the Visio functionality, you have to download the additional VESI_Visio.zip file that was added to the VMware Infrastructure Management PowerPack document page and install it as per the instructions in that document (see the “How to enable vDiagram support” section).  Visio 2007 is required.

For those of you who were fortunate enough to attend VMworld Europe in Cannes at the end of February, this release contains the icons and Visio features that Scott Herold was showing off during that show.  You can see a live demo of the new features on Scott’s website, here.

If you want to learn more about this PowerPack, including version history and other details, you can go here.  You can download the PowerPack from that location as well.

Kirk out.

Share this post:

PowerShell Deep Dive: Understanding Get-Alias, wildcards, escape characters, quoting rules, literal vs. non-literal paths, and the timing of string evaluation

The following question recently came up on a mailing list I follow:

When I am trying to get the definition for the alias "?", I need to escape it because if not it works like a wildcard.  That is ok.

But why do I have to use SINGLE quotes, and why do DOUBLE quotes fail to escape?  I thought it should be the other way around.

For example, this works:

Get-Alias ‘`?’

This does not work:

Get-Alias "`?"

Why?

This question was prompted by Aleksandar’s blog post about the problem.  There are quite a few things to consider here to understand what is going on.

First, as the author of the question pointed out, in the Get-Alias cmdlet the question mark character is a wildcard character.  That means if you simply call Get-Alias with a question mark (Get-Alias ?), you will get all one-character aliases because the question mark will match any character.  That will happen regardless of whether you use single quotes, double quotes, or no quotes.  So the question mark must be escaped to tell Get-Alias to treat it as an actual question mark, and not a wildcard question mark.

Second, in PowerShell a single-quoted string is a literal string, so characters are taken as is.  A double-quoted string is a special string where the contents are evaluated to determine what the actual string is (see Get-Help about_quoting_rules for more details).  In a double-quoted string, any variables or subexpressions (identified by their prefix of $) are evaluated and the results are placed in the string.  Also, any escaped characters are evaluated and the results are placed in the string.  The standard way to escape a character is to precede it with a backtick (`).

Third, if you escape any non-escape character by preceding it with a backtick, the result is simply that non-escape character.  The backtick is discarded.

Fourth, there is a difference between escaping escape characters when evaluating a double-quoted string and escaping wildcard characters in cmdlet that accept strings containing wildcards.  Both are escaped the same way, but understanding the timing of their evaluation and knowing what characters they consider to be escape characters is very important.  Double-quoted string evaluation happens outside of a cmdlet, before it is called.  Wildcard string evaluation happens inside of a cmdlet, once it is called.

And lastly, Get-Alias works just like the Path parameter set variant of Get-Item (that is to say, it works just like Get-Item when you call Get-Item with the Path parameter), returning multiple results when unescaped wildcard characters are in the search string and there are multiple matching aliases.  Get-Alias is a little simpler to use on a general basis, but if it wasn’t there you could just use Get-Item instead.

Now that we’re armed with that knowledge, lets break down the command we’re having a hard time with.

Get-Alias "`?"

Here are the results of that command in PowerShell:

image

What’s happening here?  When this command is executed, the first thing PowerShell has to do is evaluate the double-quoted string and get the result string that comes out of that evaluation, before the cmdlet is called.  As I explained above, any non-escape character that is escaped in a double-quoted string is simply evaluated as the non-escape character.  In our string, the question mark is being escaped, but that isn’t an escape character when it comes to string parsing (use the command Get-Help about_escape_character to get the list of escape characters in double-quoted strings), so the result of the evaluation is simply ‘?’.  When that string is then passed to Get-Alias, the Get-Alias cmdlet thinks we’re looking for any single-character aliases, so that’s what it gives us in the output.

What we need to do is make sure that the results of the evaluation of the double-quoted string are such that the question mark is preceded by a backtick so that it is escaped when it is passed into the Get-Alias cmdlet (string evaluation timing is important, remember?).  To do that, we need to know how to generate a single backtick in the result returned from a double-quoted string evaluation.  The backtick is an escape character itself as well as the character used to escape other characters (we learned this when we looked at the about_escape_character helpfile, mentioned earlier), so we can create a backtick in a double-quoted string by escaping it with itself, like this: "“".

Now that we know how to escape the backtick so that it is passed into the Get-Alias cmdlet, we can change our problematic command we were using by escaping the backtick in the double-quotes and get the results we wanted in the first place:

image

It is important to note that a non-quoted string is treated as a double-quoted string in PowerShell when it is evaluating a command that it is about to run, so if you wanted to do this without quotes at all, you would still have to escape the backtick, like this:

image

The last thought I want to leave you with is about Get-Item.  I mentioned earlier that Get-Alias works just like the Path parameter set variant of Get-Item.  Both of these need to have wildcard characters escaped if you want to find an alias that contains a wildcard character.  What I didn’t mention is that Get-Item has something that Get-Alias does not: a LiteralPath parameter set variant.  The easiest way to retrieve an alias containing a wildcard without worrying about escaping any characters is to simply use Get-Item with the alias PSDrive, like this:

image 

This method requires the use of the LiteralPath parameter name and the alias PSDrive name, but it gives you exactly what you want, without having to worry about most of what I tried to show you here, and it’s easy.  Still, I had to show you the details first…a solid foundation in understanding how these things work goes a long way when writing and troubleshooting PowerShell scripts.  If you want it even easier, you could create a simple Get-LiteralAlias function that removes the need to use the Alias PSDrive name and calls Get-Item using the LiteralPath parameter set variant behind the scenes.  You could also create a Get-Alias function that has a Literal switch parameter so that you could simply indicate whether you wanted to call Get-Alias or Get-LiteralPath behind the scenes.  With PowerShell, there are definitely no shortage of options when you don’t have the functionality you are looking for the way you expect it to be there.  I’ll leave the exercise of creating the functions up to you, if you think it’s worth it (after all, there is only one default alias with a wildcard character in its name).

Armed with all of this knowledge, it becomes completely obvious why an unusual alias created with the New-Alias command (which doesn’t support wildcard characters) like this:

$foo = ‘bar’
New-Alias "“?$foo" ‘bar’

can be retrieved using either of the following Get-Alias commands:

Get-Alias "““?$foo"
Get-Alias "““`?$foo"

Right? 🙂

Kirk out.

Share this post:

PowerShell Quick Tip: Create aliases to facilitate invocation of PowerShell script (ps1) files

I was just reading Steve Murawski’s latest blog post which contains a script called ConvertTo-Function that allows you to generate a function from a script file.  The intent is to allow you to have scripts you don’t call as often, and therefore don’t load into your profile, but when you need them you can use this script to easily generate functions that wrap them so that you don’t need to think about the path beyond the initial call to the ConvertTo-Function script.  That’s one way to facilitate this, but I have something I use quite commonly in my own environment that works much better for me for this scenario: aliases.

Aliases can reference a path to a script file.

This capability is often overlooked because aliases are most commonly used and thought of as terse command names.  Using them to reference a path to a script file is quite useful because it allows you to keep all of your scripts, complete or in development, in a common location.  You can control which ones are loaded in your profile by only creating aliases for those scripts.  Alternatively, for scripts that you really don’t use very often, you could have a function in your profile to create the aliases to those scripts on an as needed basis (which sounds a little like the Add-Module capabilities in PowerShell v2).  In either case, using aliases to reference script files is very handy because you don’t need to worry about whether the scripts you want to invoke are in a folder in your path environment variable or not.  You simply need to create an alias to the full path and then you can use that alias to invoke your script.

For example, assuming you had a script with the path C:\MyScripts\Miscellaneous\Do-Something.ps1, you could invoke it using the absolute or relative path, or if C:\MyScripts\Miscellaneous happened to be in your path environment variable you could simply invoke it using the Do-Something command.  But if you don’t have your script path in your path environment variable and/or you don’t want to change that variable, aliases give you the same capability on a temporary basis for your current PowerShell session (and only in your current scope by default if you want it really temporary).  Using our example script path, all you would have to do is create a new alias with this command:

New-Alias Do-Something C:\MyScripts\Miscellaneous\Do-Something.ps1

That allows you to invoke your script any time you want to by simply using the Do-Something alias, as long as it is created and visible in the current scope.

Kirk out.

Share this post:

VMware Infrastructure PowerPack 2.1 released

Hot on the heels of the new release of the VMware VI Toolkit, I just finished uploading version 2.1 of the VMware Infrastructure Management PowerPack for PowerGUI.  This PowerPack facilitates management and automation of VMware Infrastructure servers using the VMware VI Toolkit with PowerGUI’s extendable administrative console.

Version 2.1 of the VMware Infrastructure Management PowerPack includes the following highlights:

  • Significant performance improvements when loading datacenters and clusters.
  • New top-level container nodes to facilitate viewing objects without having to browse into the Managed Hosts node.
  • Links allowing you to browse into log files from hosts.
  • Support for the VMware VI Toolkit 1.5 release.
  • VMotion support for virtual machines.

In addition to these changes, several links have been added and quite a few defects have been fixed.

You can learn more about this PowerPack, including version history and other details here.  You can download it from that location as well.

As always, feedback on this PowerPack and all others is welcome and appreciated.  If you want to see something in the PowerPack, just ask!  You can either contact me directly (see my about page), or you can post your request using the PowerGUI forums.  We’re listening!

Kirk out.

Share this post:

PowerShell Quick Tip: How to retrieve the current line number and file name in your PowerShell script

(aka How to add C-style __LINE__ and __FILE__ macros to PowerShell)

When troubleshooting PowerShell scripts, it can be useful to log, store or output the current line number and and file name position so that you know where your script was when something happened.  This information is given to you automatically when there is an error, however if you’re not facing a PowerShell error but you have a problem with the logic in your script, you need to manually retrieve it from PowerShell.

The MyInvocation variable was designed for this purpose, providing you with details about the invocation of the current script or function as well as details about the current command that you are executing.  The trouble is that when you use $MyInvocation directly in a script file, the details it provides are about the invocation of the script, meaning the command used to invoke the script, and not about the current line within the script.  Fortunately, though, as with many things PowerShell there is a way.  To be able to use $MyInvocation to retrieve details about the current line in a script, you need to wrap it in a function and call that function.  When you do this, $MyInvocation will give you details about the command used to call the function that contains it, and if that command is inside a script file the details will include the script file name as well as the line number of the command.

Armed with that knowledge, you can create a few useful functions in your profile, and they will allow you to retrieve the current file name and line number from within any script you use.  Here are my interpretations of those functions:

#region Script Diagnostic Functions

function Get-CurrentLineNumber {
    $MyInvocation.ScriptLineNumber
}

New-Alias -Name __LINE__ -Value Get-CurrentLineNumberDescription Returns the current line number in a PowerShell script file.

function Get-CurrentFileName {
    $MyInvocation.ScriptName
}

New-Alias -Name __FILE__ -Value Get-CurrentFileName -Description Returns the name of the current PowerShell script file.

#endregion

A few good uses for these functions might be:

  1. In complicated scripts where you want to verify the order of execution of certain lines of script.
  2. When you are returning a value in multiple locations and you would like to simply know which location you returned from while troubleshooting without stepping through any lines in your script.

I hope this is useful for you.  I just started using these functions and they are already coming in quite handy for me.

Enjoy!

Kirk out.

Share this post: