PowerShell Twitter Update [2013-02-24]

So it’s getting close the end of February, and it’s been several months since I’ve blogged anything new! For today’s post, let’s take a look at what’s going on, on Twitter in the PowerShell universe!

#ConEmu

@tphakala says that he’s discovered a project called #ConEmu. #ConEmu is a project hosted on Google Code and offers a PowerShell console replacement for Windows. Some of the features that #ConEmu includes are: tabbed console support, smooth / friendly window resizing, support for Windows 7 jump lists (cool!), and a lot more!

4Sysops by Jeff Hicks

@JeffHicks is working on Part 8 of his 4Sysops series for Microsoft Certified Professional (MCP) Magazine, which covers changing Windows service account credentials through WMI. This series covers several other topics within WMI that will certainly be of interest to a variety of Windows desktop and server administrators.

Infosec PowerShell Module

@nikhil_mitt is an information security expert, and mentioned on Twitter that he has a security toolkit known as Nishang. This project is hosted on Google Code similar to the #ConEmu project mentioned above. Nikhil was even kind enough to mention that he had used some of my code in this project, which I had no idea about before today (February 24th, 2013)! I’m quite honored to hear that he made good use of some code that I had written a while back. The code we’re talking about here is in the Remove-Update function, which removes Windows software updates from a particular system.

Using Get-Content like Cat

@proxb (Boe Prox) tweeted about an article written by @ScriptingGuys (Ed Wilson) that talks about how to use the Get-Content cmdlet in PowerShell v3 to track changes to text files in realtime. This command is similar to the “cat” command in *nix operating systems.

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: Measuring Download Speeds

    Have you ever downloaded a file from the Internet? Probably.

    Have you ever downloaded a file with PowerShell? Maybe.

    Have you ever wondered how fast your download was going? Sure.

    Have you ever wondered how to get that information when you’re downloading a file with PowerShell? Maybe, but you didn’t have a solution until now!

    Our web browsers calculate download speeds for us, somehow. Specifically how, I have no clue, but what I do know is that we are more than capable of calculating download speeds using PowerShell.
    Continue reading

    PowerShell: Updating an Azure Service Display Name

    If you’re like me, you probably like clarity, consistency, and conciseness. Given that, I like to ensure that names of hosted services in Windows Azure are named appropriately. Sometimes developers will give a service a quick name that they understand, but may not relay enough information to other team members, at a glance, as to what that service does.

    Thankfully, this is easily rectified using a simple PowerShell command. Assuming that you have already configured your Windows Azure PowerShell cmdlets according to my recent “Introduction to Azure PowerShell Module” article, you can simply run the following command to update the Label (aka. “friendly name”) of a Windows Azure hosted service.

    1
    2
    3
    4
    # Select the Windows Azure subscription that we are working with (must be configured using Set-AzureSubscription)
    Select-AzureSubscription -SubscriptionName Development;
    # Set the new friendly name (label) for the service
    Set-AzureService -ServiceName MyService -Label "This is my new service label";

    If you want to take it one step further, you can build a .NET [HashTable] of key-value mappings that link service names to their respective labels. Then, once you’ve got the mapping, you can simply iterate over it and call Set-AzureService for each entry. This method is a lot more flexible and efficient with writing code :)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # Select the Windows Azure subscription
    Select-AzureSubscription -SubscriptionName development;

    # Build a HashTable of service names and labels
    $ServiceList = @{
        'Service1' = 'My First Service';
        'Service2' = 'My Second Service';
        'Service3' = 'My Third Service';
    };

    # For each service entry in the HashTable, update the Label field
    foreach ($Service in $ServiceList.Keys) {
            Set-AzureService -ServiceName $Service -Label $ServiceList[$Service];
    };

    Pretty easy, isn’t it?

    “Why go through all that effort? I’ll just do it through the UI.”

    Did I happen to mention that the Windows Azure Silverlight user interface (UI) doesn’t even allow you to change the label / friendly name of a hosted service once it has been created? Yes, it’s true (as far as I know). The only option to re-label an Azure hosted service through the management UI, once it has already been defined, is to delete the existing service definition, and recreate it. That doesn’t sound like a viable option in a production environment now, does it? :)

    Until next time … enjoy scripting ALL the things in PowerShell!

    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 ISE v3: Keyboard Shortcut to Close Script Tab

    Background

    In the PowerShell Integrated Scripting Editor (ISE) v3, the common [Ctrl] + W keyboard shortcut is mapped to the “Close PowerShell Tab” action. Personally, I would like to see different behavior, whereby that shortcut is used to close the active script tab until there are none left, at which point it may then close the active PowerShell tab. Unfortunately that’s not how it works, and it probably won’t get changed for the final release of PowerShell v3. Either way, I did file a bug report for this issue on Microsoft Connect.

    There is, in fact, a keyboard shortcut mapped to the “Close Script Tab” action, however it’s a keyboard shortcut that I’m personally not very fond of. The [Ctrl] + [F4] shortcut is rather convoluted, and although it may have a legacy in the Microsoft world, I find it to be very uncomfortable.
    Continue reading

    Introducing Microsoft’s OFFICIAL Windows Azure PowerShell Module!

    Hello folks! Today, Microsoft has officially announced the availability of a new PowerShell module to help manage Windows Azure features! In order to obtain this module, you will need to download the Web Platform Installer 4.0 (x64, x86). Once you’ve installed the Web Platform Installer 4.0, you’ll need to search for “PowerShell” and install the “Windows Azure PowerShell” package from it.
    Continue reading

    PowerShell: Getting an access token from Instagram (oAuth 2.0)

    So I’ve recently been struggling with the first step of oAuth 1.0a, which is getting a “request token.” Twitter still uses oAuth 1.0a, and although they have fairly decent documentation on the authentication flow, I’m still having a rough time with it. I had read that supposedly oAuth 2.0 would be easier to work with than oAuth 1.0a, but that didn’t really matter to me since Twitter isn’t using oAuth 2.0 yet.

    When push came to shove, and oAuth 1.0a was still giving me headaches, I figured I would just try out oAuth 2.0, to see how easy it was to get an access token. As it turns out, it’s REALLY FREAKIN’ easy, and you don’t have to worry about giving out your application’s consumer secret key (aka. consumer key, client secret, etc.), which is sensitive information. Rather, all you need to do is pass in your callback URL (the one that you configure on your application registration), and the consumer ID (aka. client ID) that the service provides you with.
    Continue reading

    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