Windows Server 2016 Automation with PowerShell Cookbook - Second Edition

4.7 (3 reviews total)
By Thomas Lee
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. What's New in PowerShell and Windows Server

About this book

This book showcases several ways that Windows administrators can use to automate and streamline their job. You'll start with the PowerShell and Windows Server fundamentals, where you'll become well versed with PowerShell and Windows Server features.

In the next module, Core Windows Server 2016, you'll implement Nano Server, manage Windows updates, and implement troubleshooting and server inventories. You'll then move on to the Networking module, where you'll manage Windows network services and network shares.

The last module covers Azure and DSC, where you will use Azure on PowerShell and DSC to easily maintain Windows servers.

Publication date:
September 2017


Chapter 1. What's New in PowerShell and Windows Server

 This chapter covers the following recipes:

  • Exploring Remote Server Administration Tools (RSAT)
  • Discovering new cmdlets in PowerShell 4 and Windows Server 2012 R2
  • Discovering new cmdlets in PowerShell 5/5.1 and Windows Server 2016
  • Exploring PowerShellGet
  • Exploring PackageManagement
  • Creating an internal PowerShell repository


Windows Server changes quickly, with a new release about every two years. Since the publication of the last edition of this book, Microsoft has delivered both Windows Server 2012 R2 and Windows Server 2016 (as well as client OS versions: Windows 8.1 and Windows 10).

PowerShell evolved alongside the server OS with a release of both PowerShell version 4, version 5, and version 5.1. This chapter reviews the changes in both the OS and PowerShell and highlights the biggest and most useful changes and new cmdlets.

This chapter also explores PowerShellGet and PackageManagement modules, perhaps the most interesting and useful new features released in PowerShell 5 and PowerShell 5.1.


Exploring Remote Server Administration Tools (RSAT)

Remote Server Administration Tools (RSAT) are tools available on both servers and client systems to manage server services. RSAT tools are available in Windows desktop and server versions. Most of the RSAT tools are not installed by default but are easily added.

RSAT includes GUI tools, like Microsoft Management Console (MMC) and MMC snap-ins (for example the DNS or DHCP MMC snap-ins) as well as command-line tools and additional PowerShell modules. You have the option of installing the Windows feature including the tools (most useful on a server), or just the tools to manage the feature (most useful on a workstation).

The recipe that follows is run from DC1, a Windows Server 2016 with Desktop Experience installation. If you try to use Server Core for this recipe, note that Out-GridView, for example in step 3, is not available in the Server Core version, as it lacks the graphical user interface. For Server Core installations, use Format-Table instead.)

How to do it...

  1. You use the Get-Command, and Tee-Object cmdlets to retrieve both the collection of PowerShell commands and the number of cmdlets into PowerShellvariables before installing the RSAT:
  $CountOfCommandsBeforeRSAT = Get-Command |      Tee-Object -Variable 'CommandsBeforeRSAT' |          Measure-Object  '{0} commands' -f $CountOfCommandsBeforeRSAT.count
  1. Examine the objects returned by Get-Command:
  $CommandsBeforeRSAT |Get-Member |   Select-Object -ExpandProperty TypeName -Unique
  1. View commands in Out-GridView:
  $CommandsBeforeRSAT |   Select-Object -Property Name, Source, CommandType |   Sort-Object -Property Source, Name |   Out-GridView


Out-GridView is not available in the Server Core version, as it lacks the graphical user interface. For Server Core installations, use Format-Table instead.

  1. Store the collection of PowerShell modules and a count into variables as well:
  $CountOfModulesBeforeRSAT = Get-Module -ListAvailable |     Tee-Object -Variable 'ModulesBeforeRSAT' |         Measure-Object             '{0} commands' -f $CountOfModulesBeforeRSAT.count
  1. View modules in Out-GridView:
 $ModulesBeforeRSAT |      Select-Object -Property Name -Unique |         Sort-Object -Property Name |            Out-GridView
  1. Review the RSAT Windows Features available and their installation status:
   Get-WindowsFeature -Name RSAT*


Get-WindowsFeature only works on Windows Server operating systems.

  1. Install RSAT with sub features and management tools:
   Install-WindowsFeature -Name RSAT -IncludeAllSubFeature `
  1. Now that RSAT features are installed, see what commands are available:
  $CountOfCommandsAfterRSAT = Get-Command |      Tee-Object -Variable 'CommandsAfterRSAT' |         Measure-Object    '{0} commands' -f $CountOfCommandsAfterRSAT.count
  1. View commands in Out-GridView:
 $CommandsAfterRSAT |    Select-Object -Property Name, Source, CommandType |  Sort-Object -Property Source, Name |  Out-GridView
  1. Now check how many modules are available:
  $CountOfModulesAfterRSAT = Get-Module -ListAvailable |     Tee-Object -Variable 'ModulesAfterRSAT' |         Measure-Object  '{0} commands' -f $CountOfModulesAfterRSAT.count
  1. View modules in Out-GridView:
      $ModulesAfterRSAT | Select-Object -Property Name -Unique |
         Sort-Object -Property Name |
  1. Store the list of commands into an XML file for later research:
      $CommandsAfterRSAT |
         Export-Clixml `
            -Path $env:HOMEPATH\Documents\WS2016Commands.XML"

How it works...

In step 1, you use Get-Command to enumerate all the commands available in PowerShell. This includes functions and aliases. It is useful to store the result of such commands into a variable, $CommandsBeforeRSAT in this case, so you are able to investigate the commands without making the request again. Using Tee-Object, you store the array of commands in that variable while continuing to use the pipeline to Measure-Object to store the count of commands, then display the result using the PowerShell string formatting function: '{0} commands' -f $CountOfCommandsBeforeRSAT

In step 2, you pipe the $CommandsBeforeRSAT variable to Get-Member to examine the TypeName of the objects returned, as shown in the following screenshot:

As you see, these commands are objects of the AliasInfo, FunctionInfo, and CmdletInfo types in the System.Management.Automation namespace (plus a FilterInfo type, which provides information about a filter that is stored in the session state.) PowerShell commands returned by Get-Command include aliases, functions, and cmdlets.

In step 3, you use Select-Object to show the useful properties, and pipe that to a Sort-Object, then pipe to Out-GridView to search and filter the PowerShell commands, as you see in the following screenshot:

In step 4, you use Get-Module just like Get-Command, but use the -ListAvailable parameter to see all the installed modules, not just those loaded into the current session. Again you use Tee-Object to store the array of modules into a variable, $ModulesBeforeRSAT, while passing the result down the pipeline to Measure-Object to calculate the count which you then display.

In step 5, you pipe the variable to a Select-Object for the interesting columns, Sort-Object, then pipe that to Out-GridView again to review the available modules as shown here:

In step 6, you view the RSAT features available in your server with Get-WindowsFeature -Name RSAT*, as shown in the following screenshot:

Get-WindowsFeature presents an information dense tree view of the RSAT tools available. Note the many sub-features under Remote Server Admin Tools and under Role Administration Tools. Each feature may be installed individually by name, or all features installed with one command as in this example.

In step 7, install all the RSAT features with the -IncludeAllSubFeature and-IncludeManagementTools parameters. You may limit what is installed by changing the first parameter to a comma separated list of desired feature names.

In steps 8-11, once the RSAT features are installed, repeat the Get-Command and Get-Modules code to see all the additional cmdlets and modules.

In step 12 you use Export-CliXML to store the array to an XML file. If you want to compare what is available in different OS and PowerShell versions, you use the array of objects saved to this file and compare it with an XML file generated under some other PowerShell or Windows versions.

There's more...

Jose Barreto, a Principal Program Manager, Applications and Services Group at Microsoft, reviewed the new Windows Server 2016 cmdlets (based on Windows Server 2016 CTP). This post shows you how to use Export-CliXML to see what has changed between PowerShell versions:


Discovering new cmdlets in PowerShell 4 and Windows Server 2012 R2

PowerShell V4 and Server 2012 R2 added many new features to existing cmdlets but did not add many new cmdlets. A notable exception is Desired State Configuration (DSC) feature that debuted in PowerShell V4.

DSC is a set of language extensions that enable you to define computer configurations in a declarative fashion then apply that configuration to managed computers. DSC is a tool to provision or manage servers and to ensure those systems stay configured correctly. DSC provides a solution to the problem of configuration drift—computer configurations that change, often incorrectly, over time.

Get more information on DSC in Chapter 13, Using Desired State Configuration.

New cmdlets

Two other useful cmdlets included in PowerShell V4 are:

  • Get-FileHash: Creates a hash value from a given file or binary value. This is useful for quickly determining whether files have changed or for finding duplicate files (that have different file names)
  • Test-NetConnection: Diagnoses a network connection and provides helpful troubleshooting information. This cmdlet is described in more detail in Chapter 8, Managing Windows Network Services.

How to do it...

  1. You use the Show-Command to investigate the Get-FileHash cmdlet:
  Show-Command -Name Get-FileHash


Show0-Command is not available in the Server Core version, as it lacks the graphical user interface.

  1. In the dialog that pops up, the Path tab corresponds to one of three parameter sets for this command. For the Path tab, enter $Env:windirnotepad.exe or any other valid file path.
  2. Choose an algorithm like SHA512 from the drop-down menu.
  3. Click the Copy button then paste the command into your PowerShell ISE and press Enter to run it. Note the hash value that is returned.
  4. Use Show-Command to investigate Test-NetConnection:
  Show-Command -Name Test-NetConnection
  1. In the dialog box, the CommonTCPPort tab corresponds to the default parameter set, the first of four. Choose HTTP from the CommonTCPPort drop-down, and choose Detailed for InformationLevel. Then click Copy, and paste the script into your editor below the Show-Command line, then close the Show-Command window. Select this line and press F8 to run this line.
  1. Repeat your call to Show-Command -Name Test-NetConnection. Choose the ICMP tab and enter a valid internet hostname like Windows.Com in the ComputerName field, or leave it blank, and choose Detailed for InformationLevel.
  2. Click the Copy button then paste the command into your PowerShell ISE below the previous command, then close the Show-Command window and select the line and press F8 to run it.
  3. Repeat your call to Show-Command Name Test-NetConnection. Choose the NetRouteDiagnostics tab, check the box for DiagnoseRouting, and click Run.
  4. Repeat your call to Show-Command -Name Test-NetConnection. Choose the RemotePort tab, enter 443 for the Port, and choose Detailed for InformationLevel, and click Run.

How it works...

In step 1, you use Show-Command to provide a graphical interface to explore new commands like Get-FileHash or new ways to use commands you know. It is the same interface that displays in the Commands tab in PowerShell ISE, and the interface is programmatically generated from the parameter definitions in the cmdlet or function, so it works with commands you create or install from outside sources.

In steps 2 and 3, choosing the Path tab corresponds to a parameter set defined in the command; each parameter set may have different required and optional parameters, represented by check boxes, drop-down menus, or text fields. This parameter set requires the Path and Algorithm parameters.

In step 4, the Copy button puts a syntax-correct command on our clipboard, either to be run as is or added to a script and modified. This is a very useful feature for new PowerShell scripters or those working with unfamiliar commands. The result of the command displays in the console, but it could be stored into a variable for comparison with other hash values to look for duplicate or changed files:

In steps 5 and 6, you use Show-Command to explore the Test-NetConnection cmdlet. This is a flexible and useful troubleshooting command with four parameter sets to use. First, test the connection to a web host over HTTP port 80. Note the -InformationLevel Detailed parameter provides additional troubleshooting information on the connectivity.

In steps 7 and 8, you use the ICMP parameter set with the -InformationLevel Detailed parameter to ping, using ICMP echo request, a web server. This is different to the earlier steps—here you are just determining whether the target server is responding to echo requests. Some web servers turn off returning of pings, so you may see a server that doesn't respond to a ping but does allow a port 80 HTTP connection.

In step 9, you use the NetRouteDiagnostics parameter set with the -DiagnoseRouting parameter, which was introduced in PowerShell 5.1, to get routing information. Here when you click the Run button, the result displays in the console window.

In step 10, you specify a RemotePort parameter set with a specified Port and ComputerName to test:

There's more...

Both Server 2012 R2 and PowerShell V4 introduced many new features and added enhancements to existing features. This included the Hyper-V, SmbShare, and BranchCache features, all of which were improved. These features came with PowerShell modules that enable you to leverage these features using PowerShell. Get more information on the modules that support the 2012 R2 features at


Discovering new cmdlets in PowerShell 5/5.1 and Windows Server 2016

PowerShell V5, PowerShell V5.1, and Windows Server 2016 also added new features.

Getting ready

Run the commands in the following recipe on a Windows Server 2016 with Desktop Experience version.

PowerShellGet module

PowerShellGet, formerly known as OneGet, is a module that provides you with a simple way to discover, install, and update PowerShell modules and scripts. It has dependencies on the PackageManagement module, which relies on NuGet. It is an open source project, located at

Refer to Explore PowerShellGet recipe.

PackageManagement module

The cmdlets in the PackageManagement module provide a single interface for software publication, discovery, installation, and inventory.

Refer to the following recipe:

  • Explore PackageManagement
  • Create a PackageManagement repository

Microsoft.PowerShell.Archive module

The Microsoft.Powershell.Archive module contains two useful functions: Compress-Archive and Expand-Archive. These enable you to create and extract ZIP files. With previous versions of PowerShell versions, you managed archives by using the System.IO.Compression namespace from the .Net framework, the Shell.Application com object or software like 7-Zip.

Microsoft.PowerShell.Utility module

The Microsoft.PowerShell.Utility module contains several new cmdlets useful for debugging interactively and within runspaces.

Debugging and runspace Cmdlets include: Get-Runspace, Debug-Runspace, Get-RunspaceDebug, Enable-RunspaceDebug, and Disable-RunspaceDebug, Wait-Debugger, Debug-Job.

These cmdlets enable debugging PowerShell scripts within runspaces and jobs and add additional debugging features for debugging production PowerShell interactively.

Other new modules

Other new modules in this version of PowerShell (and where to find more information about each module) include:





Manage the configurable code integrity policy for Windows


Manage Windows defender


Manage event tracing for Windows providers and sessions

HgsClient, ShieldedVMDataFile, and ShieldedVMTemplate

Manage the host guardian service, for shielded Hyper-V guest machines.


Manage IIS replaces WebAdministration cmdlets


Manage the new network controller role in Server 2016


Manage supported network switches in Server 2016


Manage unit tests for PowerShell modules and cmdlets


Cmdlets for managing plug and play devices

StorageQoS and StorageReplica

Support new storage functionality in Server 2016.

Other new cmdlets

Some other useful cmdlets included are:

Explore some of these cmdlets here and in later chapters as well.

How to do it...

  1. Investigate Write-Information by looking at the Write-* commands, and help for the about_Redirection topic:
  Get-Command -Verb Write -Module *Utility  Get-Help about_Redirection -ShowWindow
  1. Use Write-Information:
  Write-Information "Test"
  1. This produces no output. To resolve, you should inspect and change the $InformationPreference variable:
  Get-Variable "InformationPreference"  Set-Variable -Name "InformationPreference" -Value "Continue"
  1. Use Write-Information again:
  Write-Information "Test"
  1. Next, set $InformationPreference back to default value:
  $InformationPreference = "SilentlyContinue"
  1. Review the information-related options in the CommonParameters of each command:
  Show-Command Get-Item
  1. Use ConvertFrom-String to get objects from strings; NoteProperties are created with default names:
  "Here is a sentence!" | ConvertFrom-String  "Here is a sentence!" | ConvertFrom-String | Get-Member
  1. Use -PropertyNames to control the names:
  "Here is a sentence!" | 
         ConvertFrom-String -PropertyNames First,Second,
  1. Use -Delimiter to get items from a list:
      "Here,is,a,list!" | 
         ConvertFrom-String -PropertyNames First,Second,
                                       Third,Fourth `
                            -Delimiter ','
  1. You next test the template capabilities of ConvertFrom-String:
      $TextToParse = @'
      Animal, Bird
      Shape like Square
      Number is 42
      Person named Bob
      '@$Template1 = @'
      {[string]Category*:Animal}, {[string]Example:Bird}
      '@ConvertFrom-String -TemplateContent $Template1 `
                           -InputObject $TextToParse
  1. ConvertFrom-String recognizes only one line from the text—the template needs more examples to train the function, so add a second example to the template and test:
      $Template2 = @'
      {[string]Category*:Animal}, {[string]Example:Bird}
      {[string]Category*:Country} like {[string]Example:Italy} 
      ConvertFrom-String -TemplateContent $Template2 `
                         -InputObject $TextToParse
  1. Note three lines are recognized, even the last line that is unusual. Adding another example to our template trains the function enough to recognize all four lines:
      $Template3 = @'
      {[string]Category*:Animal}, {[string]Example:Bird}
      {[string]Category*:Country} like {[string]Example:Italy}
      {[string]Category*:Number} like {[int]Example:99}
      ConvertFrom-String -TemplateContent $Template3 `
                         -InputObject $TextToParse
  1. Experiment with Format-Hex to output values in hexadecimal:
  $TestValue =   @"  This is line 1  and line 2  "@  $TestValue | Format-Hex
  1. Experiment with Get-ClipBoard and Set-Clipboard by selecting some text, then press Ctrl+C to copy to clipboard, then inspect the clipboard:
  #Select this line and press Control-C to copy to clipboard  $Value = Get-Clipboard  $Value
  1. Use Set-Clipboard to replace the clipboard value, then Ctrl+V to paste that new value:
  $NewValue = "#Paste This!"  $NewValue | Set-Clipboard  #Press Control-V to paste!

How it works...

In step 1, you get the commands with the Write verb in the Microsoft.PowerShell.Utility module. Write-Information is an addition to this module that writes out to a new information stream, which the about_Redirection help topic describes in detail:

In steps 2-5, note that messages from Write-Information are not displayed by default. The $InformationPreference variable controls this behaviour within your PowerShell session.

In step 6, you'll see the CommonParameters now include InformationAction and InformationVariable

More information is available in Get-Help about_CommonParameters:

In step 7 you create a PSCustomObject using ConvertFrom-String with NoteProperties named P1, P2, P3, and P4 that correspond to words separated by whitespace from the input text, with string or char data types:

In step 8, you control the names of the NoteProperties. In step 9 you change the delimiter from the default of whitespace to a comma, thus parsing a comma separated list:

In step 10, you investigate the -TemplateObject parameter to parse inconsistently formatted data. Here you provide one or more patterns by example in the TemplateObject and provide the template along with the text to parse. The template starts with one line as an example, and initially recognizes only one line out of four in the text to match:

In steps 11 and steps 12, you improve the template with each attempt, achieving complete matching results from the Convert-FromString:

In step 13, you use Format-Hex on a here string that contains two lines of text. Note the 0D 0A bytes corresponding to carriage return and line feed (CRLF) between lines:

In step 14 and step 15, you work with Set-Clipboard and Get-Clipboard. By copying any text with Ctrl+C, you then capture that value into a variable with Get-Clipboard. You use Set-Clipboard to change that value, and use Ctrl+V to verify the change.

There's more...

Each PowerShell release comes with release notes that dive into the details of changes introduced with that version. These pages are updated with community contributions, as PowerShell is now partially open source:

The documentation is published on GitHub and accepts contributions from users via pull-requests so users may help improve the documentation. You'll find PowerShell documentation on GitHub at

Complete documentation is available on TechNet, see the Windows 10 and Server 2016 PowerShell module reference at


Exploring PowerShellGet

The PowerShellGet module enables you to work with repositories, sites which contain scripts and modules to download and use. If you have a Linux background, you are familiar with repositories and tools like apt-get (On Ubuntu Linux) and RPM (on Red Hat Linux). PowerShellGet delivers similar functionality within PowerShell.


Ensure you're running with administrator privileges so you can update PowerShellGet to the latest version.

How to do it...

  1. You begin by reviewing the commands available in the PowerShellGet module:
  Get-Command -Module PowerShellGet
  1. Before moving on, you should update to the latest NuGet to get the PackageManagement module current, then update the PowerShellGet module per the GitHub instructions at has a dependency on PackageManagement, which in turn relies on NuGet. PowerShellGet and PackageMangagement both come within Windows 10 and Server 2016, but Windows updates are less frequent than releases at the PowerShell gallery. Updating ensures you have the latest versions of all the dependencies. To update NuGet:
   Install-PackageProvider -Name NuGet -Force -Verbose
  1. Close your PowerShell session by running Exit and open a new PowerShell session.
  2. Check the version of the NuGetPackageProvider:
  Get-PackageProvider -Name NuGet |      Select-Object Version
  1. Update PowerShellGet:
  Install-Module -Name PowerShellGet -Force
  1. Close your PowerShell session by running Exit and reopen it again.
  2. Check the version of PowerShellGet:
  Get-Module -Name PowerShellGet |      Select-Object -ExpandProperty Version
  1. View the default PSGallery repository for PowerShellGet:
  1. Review the various providers in the repository:
  Find-PackageProvider |    Select-Object -Property Name, Source, Summary |     Format-Table -Wrap -AutoSize
  1. View available providers with packages in PSGallery:
  Find-PackageProvider -Source PSGallery |      Select-Object -Property Name, Summary |          Format-Table -Wrap -AutoSize
  1. Use the Get-Command cmdlet to find cmdlets in PowerShellGet:
  Get-Command -Module PowerShellGet -Verb Find
  1. Request all the commands in the PowerShellGet module, store them in a variable, and store the count as well:
      $CommandCount = Find-Command |
         Tee-Object -Variable 'Commands' |
      "{0} commands available in PowerShellGet" `
                              -f $CommandCount.Count
  1. Review the commands in Out-GridView and note the module names:
  $Commands | Out-GridView
  1. Request all the available PowerShellGet modules, store them in a variable and store the count as well:
      $ModuleCount = Find-Module |
         Tee-Object -Variable 'Modules' |
      "{0} Modules available in PowerShellGet" -f $ModuleCount.Count
  1. Review the modules in Out-GridView:
  $Modules | Out-GridView
  1. Request all available DSC resources, store them in a variable, and view them in Out-GridView:
    $DSCResourceCount = Find-DSCResource |
         Tee-Object -Variable 'DSCResources' |
      "{0} DSCResources available in PowerShellGet" -f `
      $DSCResources | Out-GridView
  1. Find the available scripts and store them in a variable. Then view them using Out-GridView:
      $ScriptCount = Find-Script |
         Tee-Object -Variable 'Scripts' |
      "{0} Scripts available in PowerShellGet" -f $ScriptCount.Count
       $Scripts | Out-GridView
  1. When you discover a module you would like to simply install the module. This functionality is similar for Scripts, DSCResources, and so on:
  Get-Command -Module PowerShellGet -Verb Install
  1. Install the TreeSize module, as an example, or choose your own. As this is a public repository, Windows does not trust it by default, so you must approve the installation:
  Install-Module -Name TreeSize -Verbose
  1. If you choose to trust this repository, set the InstallationPolicy to Trusted, and you'll no longer need to confirm each installation: Use at your own risk, you are responsible for all software you install on servers you manage:
  Set-PSRepository -Name PSGallery  -InstallationPolicy Trusted
  1. Review and test the commands in the module:
  Get-Command -Module TreeSize  Get-Help Get-TreeSize -Examples  Get-TreeSize -Path $env:TEMP -Depth 1
  1. Remove the module just as easily:
  Uninstall-Module -Name TreeSize -Verbose
  1. If you would like to inspect the code before installation, download and review the module code:
      New-Item -ItemType Directory `
               -Path $env:HOMEDRIVE\downloadedModules
      Save-Module -Name TreeSize `
               -Path $env:HOMEDRIVE\downloadedModules” +
  1. Import the downloaded module:
      $ModuleFolder = "$env:HOMEDRIVE\downloadedModules\TreeSize"
      Get-ChildItem -Path $ModuleFolder -Filter *.psm1 -Recurse |
         Select-Object -ExpandProperty FullName -First 1 |
            Import-Module -Verbose
  1. When you are done with discovering the new module, you can remove it from your system:
  Remove-Module -Name TreeSize  $ModuleFolder | Remove-Item -Recurse -Force

How it works...

In step 1, you start by reviewing the cmdlets in the PowerShellGet module:

In steps 2-7, you ensure PowerShellGet and its dependency PackageManagement are up to date by updating the NuGet provider, verifying the version, then restarting your PowerShell session and updating PowerShellGet and verifying its version.

The -Verbose flag gives you more details on the installation, but it is not required. Note that you must Exit your session after running this command and reopen to continue with the latest version.

Check our NuGet provider version after reopening our PowerShell session:

In step 6-7, you update the PowerShellGetmodule:

Note that you must exit your session after running this command and reopen to continue with the latest version.

In step 8, check your PowerShellGet version after reopening your PowerShell session:

In step 9, you use Get-PSRepository. PowerShellGet starts with a single repository PSGallery installed by default:

In step 10, review the package providers available:

Note the source column; the first three providers listed correspond to NuGet, OneGet, and Chocolatey providers. NuGet is a repository devoted to developer libraries. OneGet was the name of this module (and repository) but has been deprecated and replaced by PackageManagement. You explore Chocolatey in a later recipe. The remaining rows are the available providers in the PSGallery repository.

In step 11, you limit your repository search with Find-PSRepository by specifying the -Source PSGallery parameter:

In step 12, you discover the PowerShellGet commands containing the verb Find:

In steps 13 - 18, you use the Find-* commands to store the available commands, modules, DSC resources, and scripts into variables, then explore what is available using Out-GridView (including using the built-in filter capability to search for a module), for example:

In step 19, you review the install commands in the PowerShellGet module. Their functions are very similar:

In step 20, the TreeSize module looks like an interesting tool to inspect folders and their sizes. Install it by using the Install-Module cmdlet. You use the -Verbose switch to get more information about what the cmdlet is doing:

After confirming the Untrusted repository pop up dialog, PowerShell installs the module.

In step 21, you see that the code available on PSGallery, as well as other public repositories, is just that, public. You must choose to trust the code you download from the internet to take advantage of the functionality provided by that code. To trust this repository and disable prompting, use the command (at your own risk and responsibility):

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

In step 22, you evaluate and test the module:

In step 23, uninstalling a module is simple:

In step 24, if you prefer, download code and inspect it before installing, using Save-Module, then browse the module's files in Windows Explorer:

In step 25, after reviewing the code, import the module by locating the .psm1 file which defines the module, using Get-ChildItem, then piping that filename to Import-Module:

In step 26, you uninstall the module from your session and delete the module's folder. You may, of course, wish to keep the module!

There's more...

There are a wealth of other resources in the PSGallery—you use the Find-* cmdlets to explore the online resources you can download and use:

The PowerShellGet module enables search for commands, DSC resources, modules, role capabilities, a feature of Just Enough Administration (JEA), and scripts. You can download and use these various tools, or leverage them to build your own custom scripts.


Exploring PackageManagement

PowerShellGet is a powerful resource for PowerShell, built on top of the core PackageManagement capabilities of PowerShell 5. It is one of many PackageManagment providers available, as shown here:

Image Source:

PackageManagement is a unified interface for software package management systems, a tool to manage package managers. You use the PackageManagement cmdlets to perform software discovery, installation, and inventory (SDII) tasks. PackageManagement involves working with package providers, package sources, and the software packages themselves.

Within the PackageManagement architecture, PackageManagement providers represent the various software installers that provide a means to distribute software via a standard plug-in model using the PackageManagement APIs. Each PackageManagement provider manages one or more package sources or software repositories. Providers may be publicly available or can be created within an organization to enable developers and system administrators to publish or install propriety or curated software packages.

PackageManagement Core is effectively an API. The core includes a set of PowerShell cmdlets that enable you to discover available software packages, as well as to install, uninstall, update, and inventory packages using PackageManagement.

Each PackageManagement provider is a different installer technology or package manager that plugs-in via the PackageManagement API. PowerShellGet, NuGet, and Chocolatey are examples of PackageManagement providers.

Each provider is made up of one or more sources, which may be public or private. For example, NuGet has a public source, but your organization may add private sources for the NuGet provider, enabling curation of approved software to make it available to corporate developers.

How to do it...

You use the cmdlets within the PackageManagement module to explore the capabilities it provides.

  1. Review the cmdlets in the PackageManagement module:
  Get-Command -Module PackageManagement
  1. Review the installed providers with Get-PackageProvider:
  Get-PackageProvider | Select-Object -Property Name, Version
  1. The provider list includes msi, msu, and Programs package providers. These providers expose applications and updates installed on your computer which you can explore:
      Get-Package -ProviderName msi |
         Select-Object -ExpandProperty Name
      Get-Package -ProviderName msu | 
         Select-Object -ExpandProperty Name
      Get-Package -ProviderName Programs | 
         Select-Object -ExpandProperty Name
  1. The NuGet source contains developer library packages. This functionality is outside the scope of this book, but worth exploring if you do Windows or web development:
  Get-PackageProvider -Name NuGet
  1. There are also other package providers you can explore:
     Find-PackageProvider |
         Select-Object -Property Name,Summary |
             Format-Table -Wrap -AutoSize
  1. Notice Chocolatey, which is a very useful tool for Windows administrators and power users. Those with some Linux background may think of Chocolatey as apt-get for Windows. You cannot use this provider until you install it and confirm the installation:
  Install-PackageProvider -Name Chocolatey -Verbose
  1. Verify Chocolatey is now in the list of installed providers:
  Get-PackageProvider | Select-Object Name,Version
  1. Look for available software packages from the Chocolatey package provider. Store these in a variable so you don't request the collection more than once, and explore it:
      $AvailableChocolateyPackages = `
          Find-Package -ProviderName Chocolatey
      # How many software packages are available at Chocolatey?
      $AvailableChocolateyPackages | Measure-Object
  1. Pipe to Out-GridView to search for interesting software packages from Chocolatey:
      $AvailableChocolateyPackages |
         Sort-Object Name,Version | 
            Select-Object Name, Version, Summary |
  1. Install one or more packages. sysinternals is a good example to use. Use -Verbose to get details on the installation:
    Install-Package -ProviderName Chocolatey `
                      -Name sysinternals `
  1. Review installed Chocolatey packages, stored to C:\chocolatey\ by default, this path is stored in the $env:ChocolateyPath environment variable. Then review the executable files included with the sysinternals package:
      Get-ChildItem -Path $env:ChocolateyPath\lib |
         Select-Object -Property Name
      Get-ChildItem -Path `
         $env:ChocolateyPath\lib\sysinternals.2016.11.18\tools `
                    -Filter *.exe | 
         Select-Object -Property Name
  1. Run any installed command included with sysinternals:
      $PSInfoCommand = `
      Invoke-Expression -Command $PSInfoCommand
  1. Installed packages are enumerated with Get-Package and updated using the same command to install them, Install-Package:
  Get-Package -ProviderName Chocolatey | 
         Install-Package -Verbose

How it works...

In step 1, you review the cmdlets available in the PackageManagement module:

In step 2, you use the Get-PackageProvider cmdlets to display the currently installed package providers:

In step 3, you use Get-Package with the -ProviderName parameter to review packages installed via the msi, msu, and Programs package providers:

In step 4, review the NuGet provider:

In step 5, search for other package providers:

In step 6, you use Install-PackageProvider to install the Chocolatey provider. Since it is untrusted as a public source, you must approve the installation (at your own risk and responsibility):

In this example, you run Install-PackageProvider from within the ISE. By default, this pops up a confirmation dialog. If you run this cmdlet from the PowerShell console, you see a prompt there. You can suppress these confirmation requests by including the parameter -Confirm:$False.

In step 7, you verify Chocolatey is now installed as a package provider:

In step 8, retrieve a list of available software packages from the ChocolateyPackageProvider, store as a variable, and count the available packages:

In step 9, pipe the variable to Out-GridView and use the filter feature to explore what is available. This example is filtering for the Sysinternals package:

In step 10, you install this package (or any package you choose):

In step 11, you review the installed Chocolatey packages, and the files contained within the sysinternals package folder:

In step 12, run any Sysinternals command, for example, PsInfo.Exe :

In step 13, you enumerate the installed packages with Get-Package. As time goes by, packages can be updated with bug fixes, new features, and so on. You can update all the installed packages if any updates exist, as follows:

There's more...

Details of NuGet package and its functionality are outside the scope of this book, but worth exploring if you do Windows or web development. More information on NuGet packages is available from

Chocolatey has both a command-line interface and a PowerShell module. The command line interface offers functionality comparable to the PackageManagement module, targeted toward end users and system administrators. Chocolatey is supported on any Windows PC running Windows 7 or later. You can get more information on installing and using Chocolatey via the command line from

Sysinternals is a must-have toolkit for Windows administrators. You can find additional training on the Sysinternals tools on the Channel 9 website at


Creating an internal PowerShell repository

It is useful to create your own PowerShell repository for personal or corporate use. The tools to enable you to build your own repository are not included in PowerShell. There are three main approaches available that enable you to build a repository:

  • Using Visual Studio's NuGet package manager to download and install the Nuget.Server package into a new web project, and deploy to your own IIS Server. This option is free. However, you need to use Visual Studio 2015 (Either the full version or the free community edition) to create your own web project, download the Nuget server software, and deploy it into your environment. More information is available at
  • Using a third-party NuGet host's SAAS platform. This is the simplest solution, but software licensing fees may apply, and some organizations might have reservations about keeping the code on external servers. Choices for this approach include Visual Studio Team Services,, and ProGet.
  • Installing a 3rd-party NuGet software repository on your server. This simplifies the setup process for hosting your own software repository, but software licensing fees may apply.


More information is available on hosting from the NuGet site at

The simplest approach to setting up your own software repository is to install and configure the free or trial version of ProGet. Do so via a GUI installation—the steps are described at

You have the choice of using an existing SQL Server instance or installing SQL Express as part of the installation. SQL is used to hold the repository's data. You may also choose to install your repository to an existing IIS Server or install ProGet with its own internal web server.

Inedo also provides a PowerShell script to perform the installation, which you may customize. For the script based installation, you need to register for a free license key at


You can find more information on using ProGet from the Inedo web site at

How to do it...

  1. Once you have installed ProGet using either the GUI or PowerShell script approach, log in to the ProGet application home page using the default admin account until you create a username and password:
  1. From Feeds page, click Create New Feed:
  1. A list of supported feed types is displayed. Choose PowerShell:
  1. Enter a feed name of your choice: (for example, MyPowerShellPackages) and click the Create New PowerShell Feed button:
  1. Review the properties of your new feed:
  1. Open the PowerShell ISE or console, and register your new repository:
      $RepositoryURL = `
      Register-PSRepository -Name MyPowerShellPackages `
          -SourceLocation $RepositoryURL`
          -PublishLocation $RepositoryURL `
          -InstallationPolicy Trusted
  1. Publish a module you already have installed (Pester, for example):
      Publish-Module -Name Pester -Repository MyPowerShellPackages `
                     -NuGetApiKey "Admin:Admin"
  1. Download a module from PSGallery, save it to the C:\Foo folder, and publish to your new repository (for example, Carbon):
      Find-Module -Name Carbon -Repository PSGallery 
      New-Item -ItemType Directory -Path 'C:\Foo'
      Save-Module -Name Carbon -Path C:\foo
      Publish-Module -Path C:\Foo\Carbon `
                     -Repository MyPowerShellPackages `
                     -NuGetApiKey "Admin:Admin"
  1. Find all the modules available in your newly created and updated repository:
  Find-Module -Repository MyPowerShellPackages

How it works...

There are various options for setting up a NuGet-based repository for PowerShell. ProGet is a universal package manager from Inedo (See for more information on ProGet). ProGet is a very simple choice as it is easy to get started and offers the ability to scale to enterprize level. ProGet has both a free and a paid subscription version available. The ProGet installer creates a NuGet web server backed by a SQL Express database.

In step 1, you visit the server web administration page and optionally review the functionality available.

In steps 2-5, you use ProGet to create a new repository for your PowerShell modules. As you see, you use the ProGet GUI to create this new repository.

In step 6, you register your new repository in your PowerShell session. You need to know the repository URL and have a NuGet API key, using the default username/password of Admin /Admin.

In step 7, you publish a module to the repository—you are using a module that is installed in your PowerShell session, Pester.

In step 8, you locate and download an additional module from the PSGallery, and publish this module to your local repository.

In step 9, you see the modules available from your local repository:

There's more...

ProGet is a rich product. It provides both automatic failover and scalability which are needed features for PowerShell repositories in large organization's repository. ProGet is one option you have for creating your own organization specific repository. To learn more about ProGet, visit

NuGet is a free, open source package management system provided by the Microsoft ASP.NET development platform and is provided as a Visual Studio extension. To learn more about NuGet, visit

About the Author

  • Thomas Lee

    Thomas Lee is a consultant/trainer/writer from England and has been in the IT business since the late 1960's. After graduating from Carnegie Mellon University, Thomas joined ComShare where he was a systems programmer building the Commander II time-sharing operating system, a forerunner of today's Cloud computing paradigm. In the mid 1970's he moved to ICL to work on the VME/K operating system. After a sabbatical in 1980/81, he joined Accenture, leaving in 1988 to run his own consulting and training business, which is still active today.

    Thomas holds numerous Microsoft certifications, including MCSE (one of the first in the world) and later versions, MCT (25 years), and was awarded Microsoft's MVP award 17 times.

    Browse publications by this author

Latest Reviews

(3 reviews total)
Very informative reference!
Goes into the detail required for the next step in Windows server deployment
good examples and includes more recent topics.

Recommended For You

Book Title
Access this book, plus 7,500 other titles for FREE
Access now