ConfigMgr: A Couple of Client Tweaks via PowerShell

Disable WINS Lookup via PowerShell & WMI

If you’re running Microsoft System Center Configuration Manager, you probably don’t need to be using the WINS lookup for Server Locator Points. Normally, you’d have to de-install the ConfigMgr client, and then re-install it with the SMSDIRECTORYLOOKUP=NOWINS MSI property. If you don’t want to do that, and want to disable the WINS lookup feature on your existing client base, you can use PowerShell to achieve this.

1
2
3
$DirectoryLookup = Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -Class CCM_DirectoryLookup_Configuration;
$DirectoryLookup.LookupFlags = 1;
$DirectoryLookup.Put();

Verification

After configuring this setting, you can restart the SMS Agent Host service by running the following command:

1
Restart-Service -Name ccmexec;

Open up the LocationServices.log client log file, and search for the text: Policy disallows failing over to WINS..

If you see that message showing up in the logs, then you should be all set!

Enabling Verbose Logging via PowerShell & WMI

Another post-installation trick you can do for Microsoft System Center Configuration Manager clients is enable verbose logging via the Windows Management Instrumentation (WMI) service. Check out this quick PowerShell script to achieve this:

1
2
3
$Logging = Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -Class CCM_Logging_GlobalConfiguration;
$Logging.LogLevel = 0;
$Logging.Put();

Important: You may need to restart the ConfigMgr client service (short name: ccmexec, display name: SMS Agent Host) in order for this change to take effect.

PowerShell Summit 2013 Videos

Don Jones (@concentrateddon) recently posted about some videos that Aaron Hoover recorded at PowerShell Summit 2013. Don is short on time and bandwidth, and didn’t have time to post click-able links, so I’m just reposting them here for convenience. All credit goes to Don and Aaron for the content below!

http://youtu.be/0NeEU3FHp8I Device Management With PowerShell – Ricardo Mendes – PowerShell Summit 2013
http://youtu.be/XsnE_OQGvdo Creating a Complex and Reusable HTML Reporting Structure – Alan Renouf – PowerShell Summit 2013
http://youtu.be/iV6cYsQDL0Y How Secure Can You Be – Jeff Hicks PowerShell Summit 2013
http://youtu.be/qSE06GkQWV4 Standards Based Hardware Management – Steve Lee – PowerShell Summit 2013
http://youtu.be/7C53pawPw3Y Workshop – Automating for DevOps – Kenneth Hansen and Hemant Mahawar – PowerShell Summit 2013
http://youtu.be/KFA-zSojxqw CIM Sessions – Richard Siddaway – PowerShell Summit 2013
http://youtu.be/EloMKpvfES8 PowerShell Web Access – Richard Siddaway – PowerShell Summit 2013
http://youtu.be/3deY6e6Npzo Sapien PowerShell Products – David Corrales – PowerShell Summit 2013
http://youtu.be/xZtapxf1ytI What I learned Judging 5000 Scripts – Ed Wilson – PowerShell Summit 2013
http://youtu.be/Ahvs1rGPk1s PowerShell Events – Richard Siddaway – PowerShell Summit 2013
http://youtu.be/U_niW85TtJE Write Modules, Not Scripts – Ed Wilson – PowerShell Summit 2013
http://youtu.be/Y8IbadEHoPg PoshMon – PowerShell Does Performance Counters – Ed Wilson – PowerShell Summit 2013
http://youtu.be/1XuB71tLNvg Configuring Your PowerShell Workflow Environment – Aleksandar Nikolic – PowerShell Summit 2013
http://youtu.be/msHGx-mxWJA Practical PowerShell Integration from Bare Metal to the Cloud – Alan Renouf – PowerShell Summit 2013
http://youtu.be/eAZ-agh182g Source Control for IT Pros – Andy Schneider – PowerShell Summit 2013
http://youtu.be/pL_Ry5LzX3w Creating HTML Reports with Style – Jeff Hicks – PowerShell Summit 2013
http://youtu.be/-ERyfmOmyoI Remoting Configuration Deep Dive – Don Jones – PowerShell Summit 2013
http://youtu.be/jMVBN5V0G4Y Advanced Network Scripting with PowerShell – Lee Holmes – PowerShell Summit 2013
http://youtu.be/GXkLtEOM-DM Build Your Demo Environment with Windows PowerShell – Aleksandar Nikolic – PowerShell Summit 2013

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 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