PowerShell: A first-timer’s perspective of PowerCLI

This blog post is a description of my first experience playing around with PowerCLI, which is VMware’s PowerShell module for managing vSphere servers. I haven’t really dealt with VMware much in my past, other than VMware Workstation, so I thought it was exciting to get the chance to play around with PowerShell & VMware together!

I won’t bore you with the installation details, and I’ll get right to firing it up. There’s a shortcut to launch PowerCLI in the Start Menu, and it’s got a custom icon on it, which makes it easily recognizable on the Windows Taskbar.

Continue reading

PowerShell: Update-Help via Scheduled Task in Group Policy Preferences

Introduction

If you’re like me, you probably like to ensure that all your computers have PowerShell updatable help updated on a regular basis. You can achieve this using a variety of methods, but since Group Policy Preferences are available out of the box using Windows 7 and later, I figured it would be the perfect tool to keep PowerShell help up-to-date! The following guide will show you how to implement a Windows Scheduled Task to update PowerShell version 3.0 help on a regular basis.

The following operating systems include Group Policy Preferences Client Side Extensions (GPP-CSE) out of the box:

  • Windows 7
  • Windows 8
  • Windows Server 2008 R2
  • Windows Server 2012

You can also deploy the Windows Management Framework Core 3.0, and Group Policy Preferences Client Side Extensions to Windows Server 2008 non-R2 systems, however the equivalent client operating system, Windows Vista, does not support WMF 3.0.

Continue reading

PowerShell: Creating Active Directory Managed Service Accounts

Hey folks,

I’ve recently been trying to learn more about Active Directory Managed Service Accounts (MSAs), which are basically self-managing service accounts. You don’t have to manage the Service Principal Name (SPN) or password for MSAs, which makes them very good choices for running applications. You can read more about MSAs on Microsoft Technet at this URL.

Similar to MSAs are local “virtual accounts.” These do not have password to manage, and they can automatically manage their SPNs. These are not within the scope of discussion, however there are some links in the References section, which might help you to get more information about them.

Creating a Group Managed Service Account with PowerShell

I’ve been trying to create a MSA using PowerShell using the command below, but I kept getting an error. There is a Technet discussion forum post that addresses this same issue. In my scenario, I was running the command on a Windows Server 2012 domain controller.
Continue reading

PowerShell: Generating functions with dynamic parameter auto-completion values

Download the GetDevice PowerShell Module

There is a PDF copy of this entire blog post inside of the attached zip file. It’s much more readable.

Introduction

The purpose of this document is to describe the goal and solution for creating dynamically-injected parameter auto-completion values into PowerShell function definitions. This is simply a proof of concept, and not a complete solution.

Problem

In PowerShell version 3.0, parameters can be configured to auto-complete values that can be passed in. In prior version of the product, auto-completion was limited to PowerShell provider paths (eg. any child node within a PSDrive).

Goal

The goal of this proof of concept is to dynamically inject auto-completion values into a PowerShell script function (aka. script cmdlet). As of right now, I do not believe that it is possible to inject auto-completion values into a parameter definition on a function; rather, the auto-completion values must be pre-defined in the parameter’s definition within the function definition.

Solution

The proposed solution is to create a function template, which will have values dynamically injected into it when a module is imported.

There are several parts to this solution, which is implemented as a module.

The module file

  • Imports / calls the “value retriever” script and stores values into an array
  • Joins the array of values into a string, on a comma
  • Replaces the placeholder in the template function with the validation string
  • Writes the resulting function to a file and imports it into the session
  • << You are now ready to use the dynamically generated function >>
  • Value retriever

  • Retrieves a list of valid values for the desired parameter in the template script
  • Returns the list of values to the module “installer” (item #1)
  • Template function

  • Serves as a template function that will have the values substituted into it
  • Final function definition

  • A copy of the template function that will contain the substituted values
  • Will be imported by the module “installer”
  • Can be called by the end user once
  • Example Solution

    Let us create a sample module, which will contain a single function that retrieves a Windows Management Instrumentation (WMI) device for a computer, based on its friendly name (Caption). We will call this function Get-Device. Normally, we could simply use the Get-CimInstance or Get-WmiObject cmdlets to enumerate the Win32_PnpEntity WMI class, but in order to retrieve a specific device by name, we would have to write a WMI filter, which can be a pain to write if you are not already familiar with them. An alternative would be to filter the entire result set using PowerShell’s Where-Object cmdlet, but that is not very performance-friendly.
    Instead, what our Get-Device function will do is use a WMI filter, but the end-user will pass in a value as a function parameter, instead of having to write a custom WMI filter. The WMI filter is pre-defined inside of the function.
    Let’s take a look at the example project files, and how to use them in the next couple sections.

    Example Project Files

    GetDevice.psm1

    This is the module “installer” file that helps PowerShell import the module into the current session (runspace). The logic to go out and grab the dynamic value list, and replace these values into the template function is implemented inside the module installer.

    Get-Device.ps1.template

    Defines the Get-Device function, but it not entirely valid PowerShell code. This file is not directly executed directly, but is instead used to generate the “real” Get-Device.ps1 file.

    Get-Device.ps1

    This file is dynamically generated based off of the Get-Device.ps1.template file when the module is imported. It is forcibly overwritten if it already exists by the module “installer” file (GetDevice.psm1).
    The Get-Device function is defined in this file, and has a single parameter: DeviceName. This parameter definition will contain all of the values returned by the Get-DeviceNames.ps1 function.

    Get-DeviceNames.ps1

    This is a function that retrieves the values that will be injected as auto-completion values into the Get-Device.ps1 file. Currently this function is exported as a function within the GetDevice module, but it is not intended to be called by the end user directly. See the “Known Issues” section for more information.

    Using the Example Module

    Installing

    To use the example module, simply extract it to a path on your filesystem, and import the fully qualified path to the GetDevice.psm1 file. You can also extract it to your PowerShell module path and import it by simply using the module’s name (GetDevice).
    # If the module is NOT in your $env:PSModulePath, use this
    Import-Module -Name c:\extract\GetDevice\GetDevice.psm1;

    # If the module is in your module path, use this
    Import-Module -Name GetDevice;

    Testing Auto-Completion on Get-Device

    When you imported the GetDevice module, a function called Get-Device was dynamically generated. You can test out the auto-completion by typing the following:
    Get-Device -DeviceName a&lt;tab&gt;

    That’s all there is to it!

    Known Issues

    Quotes around values

    Currently, if a parameter value requires quotes around it, they are not automatically added by the PowerShell console. Attempts to add quotes to the valid parameter values caused the values themselves to contain quotes, which meant that the first set of quotes around a value (when the Get-Device function is called) would get ignored, and validation would fail.

    Leftover public function definitions

    The “value retriever” function is currently exported as a public function when the GetDevice module is imported. This could be prevented in several different ways, but is beyond the scope of this proof of concept. For example, two potential solutions:

  • You could use “Remove-Item” to remove the function definition using the function: PSdrive
  • Use a PowerShell manifest file (.psd1) to limit which functions are exported from the module
  • Unique Values

    The “value retriever” function (Get-DeviceNames.ps1) does not return unique values. It returns ALL device names, even if there are duplicates. This could easily be restricted to prevent duplicate values from being returned.

    You must type at least one character to use tab-completion

    Although the built-in PowerShell parameter auto-completion allows you to simply hit “tab” to start cycling through auto-completion values, when you are writing custom functions using the [ValidateSet()] parameter, you must type at least one character to get auto-completion “started.” There is currently no known work-around or solution to this problem.

    PowerShell: Embed binary data in your script

    When writing automation scripts or modules, you might find that you frequently reference external binary data.

    Binary data? Well, that accounts for all data!” you might say.

    Yes, that’s true. But I’m talking about binary data as opposed to files containing simple ASCII or UTF-8 data. Maybe there’s some better terminology to describe that, but hey it works for now. Binary data could include things such as:

    • Word documents
    • Executable (Portable Executable format)
    • Code libraries (DLLs)
    • Registry files
    • etc.

    In the case of executables, oftentimes they provide useful functionality that would take many lines of PowerShell code to replicate. Some developers, for better or for worse, elect to use these utilities instead of going through the effort of writing the necessary code to handle the function natively in PowerShell. This creates an additional dependency when porting the PowerShell code, as the author must be sure to include the utility with their code, or otherwise ensure (via documentation, for example) that the target user will already have it available.

    Wouldn’t it be nice if you didn’t have to depend on the user having some executable pre-installed, just to get your script to work, though? Unfortunately the little topic of “software licensing” can sometimes prevent redistribution of software that you are not given explicit permission to copy, however there are also many cases where this is allowed (eg. open-source projects). The work-around in cases where redistribution is not allowed, is to either direct the user where to download the software from, or automate it for them.
    Continue reading

    PowerShell: Tracert or Trace-Route?

    UPDATE (2012-07-27): Justin Dearing (@zippy1981) sent me an updated version of the script, which improves on the following:

    * Has some comment-based help
    * Parameter checking

    Grab it here: Invoke-TraceRoute.ps1

    ——————————————————————–

    Any network or systems administrator is familiar with the good old tracert.exe utility that’s been included outof-the-box in Windows for years now. Tracert allows you to identify each “hop” (typically a router) between two IP endpoints on a network. Since this utility was developed long before PowerShell existed, and has been time-tested, it hasn’t been implemented yet as a PowerShell cmdlet. That being said, PowerShell folks often do not enjoy reliance on external dependencies, and prefer the flexibility of an API that can provide only the information that they want or need. To that end, I have developed a Trace-Route PowerShell advanced function (cmdlet) that emulates a limited set of functionality offered by tracert.exe.
    Continue reading

    PowerShell 3 RC: New Send-MailMessage Parameter for Port Number!

    Did you know that in previous versions of Windows PowerShell, there was no built-in way to specify a custom port to send an e-mail to a SMTP server? It’s true, Microsoft did not include that parameter until the release candidate (aka. release preview) version of PowerShell version 3.0. The release candidate of Windows Management Framework 3.0 was made available for download on May 31st, 2012. The cmdlet in question here is the Send-MailMessage cmdlet, and just today, I noticed a comment from someone at Microsoft, saying that the new -Port parameter was included in the PowerShell 3.0 RC.

    Upon closer, personal inspection, it’s true. The -Port parameter has been included! Here is the original bug filed on Microsoft Connect by Shay Levy:

    https://connect.microsoft.com/PowerShell/feedback/details/490141/add-port-parameter-to-send-mailmessage

    All we have to do to verify the availability of the parameter is issue the Get-Help Send-MailMessage command.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    NAME
        Send-MailMessage

    SYNOPSIS
        Sends an e-mail message.


    SYNTAX
        Send-MailMessage [-To] <String[]> [-Subject] <String> [[-Body] <String>]
        [[-SmtpServer] <String>] [-Attachments <String[]>] [-Bcc <String[]>]
        [-BodyAsHtml [<SwitchParameter>]] [-Cc <String[]>] [-Credential
        <PSCredential>] [-DeliveryNotificationOption
        <DeliveryNotificationOptions>] [-Encoding <Encoding>] [-Port <Int32>]
        [-Priority <MailPriority>] [-UseSsl [<SwitchParameter>]] -From <String>
        [<CommonParameters>]


    DESCRIPTION
        The Send-MailMessage cmdlet sends an e-mail message from within Windows
        PowerShell.

    PowerShell: Automate Windows Azure Service Bus queue creation

    One of the core services provided by the Windows Azure “cloud computing” platform is the ability to create first-in, first-out messaging queues. These queues are considered to be part of the Service Bus feature in Windows Azure. In some cases, it may be desirable to automate the creation of these queues, especially if there are a lot of them to create. By automating this process, rather than performing it manually, you can ensure consistency, repeatability, and speed.

    Starting out with Windows Azure automation might lead you to download the official Microsoft Windows Azure cmdlets, or even the third-party Cerebrata Windows Azure module for Windows PowerShell. The latter module appears to have cmdlets that support queue creation, however the former (Microsoft) module does not. If you’d rather not spend the money on the Cerebrata module, can’t get your company to buy it for you, or you’d rather just stick to native Microsoft stuff, you’re still in luck. The Windows Azure .NET SDK 1.6 allows C# developers, and PowerShell script writers, to create queues using the provided .NET types!
    Continue reading

    PowerShell: Twitter Folks

    Hey folks, here are some of the top tweeters on the topic of PowerShell! All of them come with my strong recommendation to follow them! You will be in good company, and will probably learn a LOT, if you keep in touch with these ridiculously smart folks.

    Jeffrey Snover – https://twitter.com/jsnover

    Don Jones – https://twitter.com/concentrateddon

    Jon Walz – https://twitter.com/jonwalz

    Hal Rottenbeg – https://twitter.com/halr9000

    Doug Finke – https://twitter.com/dfinke

    Boe Prox – https://twitter.com/proxb

    Adam Driscoll – https://twitter.com/adamdriscoll

    Ravikanth Chaganti – https://twitter.com/ravikanth
    Continue reading