PowerShell Module Test-TCPConnection

I have this love versus disappointment relationship with PowerShell. It can provide a lot of great stuff for us in automation, but sometimes the thing that looks likes the best ever since sliced bread can be a bit of a disappointment. Take the cmdlet “Test-NetConnection” for example. It’s absolutely wonderful in what it does. It assists you in doing a network diagnosis with just a single command. Much more than you could ever get out of just a simple icmp ping. However, the latter is just the problem with this PowerShell cmdlet. You cannot run it without it using a ping. The real downside to that is when the port is not available, blocked by a firewall or something else is blocking it, you have to wait for it to get a time out. And that takes time, a lot of time. If it was just for one host, I could live with it, but if you need to figure out if 200 servers are reachable, you are going to be in the office for a while. Hence the creation of my ever first cmdlet!

Based on my disappointment for the “Test-NetConnection” cmdlet and my desire to learn more on PowerShell I created my first cmdlet that does exactly what “Test-NetConnection” does with respect to a port query but without the icmp ping involved. I have dubbed it “Test-TCPConnection”, because, well that it what it does. Being the nerd that I am, I have included a full help in the module itself but I will list on my site as well. Use “help Test-TCPConnection –Online” to connect to the online help page.

To make the “Test-TCPConnection” module work, extract the folder and place it in your PowerShell Modules folder. Use the following command to see your individual module path’s.

$env:PSModulePath -Split ";"

After reloading your PowerShell environment, the module will be loaded automatically. You can check the commands the module exposes with:

Get-Command -Module TestTCPConnection


Getting the syntax is easily accomplished with:

Get-Command Test-TCPConnection -Syntax


Any feedback is always appreciated. Use the comment option down below or send me a message using the contact page.

Download version from the PowerShell Gallery:

Replacing DiskPart with PowerShell

In my previous life, I was a deployment person. MDT, WDS, WinPE & bare-metal installation were all part of my life. For managing disks, physical or virtual I always used “diskpart.exe” to create the disk layout, create bootable partitions and everything surrounding the magic of disks and partitions. Since I am trying to do as much as possible now with PowerShell I thought it would be fun to see if “diskpart.exe” could be replaced with pure PowerShell CMDLET’s? To give you a heads-up, it can for 99%, almost there! Just one feature I could not find is setting GPT attributes. According to this article, a Recovery Partition should have the attribute of “GPT_ATTRIBUTE_PLATFORM_REQUIRED” & “GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER” resulting in a value of “0x8000000000000001”. Using “diskpart.exe” to query for information from a default installation of Windows 10 results in the correct attributes.


I did expect that setting a partition to the guid value for a recovery partition with PowerShell (“de94bba4-06d1-4d40-a16a-bfd50179d6ac”) ,would also take care of both the attributes. It partially does that, just the “GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER” is set, so the drive is hidden for the OS. The other one is not set and according to my research, it is simply not available in PowerShell. Therefore, you will still need “diskpart.exe”.

During my experimentations, I have concluded that PowerShell’s “Disk”, “Partition” and “Volume” cmdlets are tricky to work with. It takes time to understand how to handle them, but it eventually works. In my opinion “diskpart.exe” is still more powerful when it comes down to pure handling disks, however PowerShell has far better support for handling the dynamics surrounding scripting and error handling. Still it is not so difficult to combine them both, as you will see in my example.

Here is my code or download the script below. Please note that I have put a “return” at the top of the script so you do not destroy your disk the first time you run the script.

# Define the disk
$Disk = Get-Disk | where Number -EQ "0"
$DiskNumber = $Disk.DiskNumber

# Clean the disk and convert to GPT
if ($disk.PartitionStyle -eq "RAW")

Initialize-Disk -Number $Disk.DiskNumber -PartitionStyle GPT

} Else {

Clear-Disk -Number $DiskNumber -RemoveData -RemoveOEM -Confirm:$false
 Initialize-Disk -Number $DiskNumber -PartitionStyle GPT


#Create the System Partition Partition
$SystemPartition = New-Partition -DiskNumber $DiskNumber -Size 512MB
$SystemPartition | Format-Volume -FileSystem FAT32 -NewFileSystemLabel "system"
$systemPartition | Set-Partition -GptType "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}"
$SystemPartition | Set-Partition -NewDriveLetter "S"

#Create Microsoft Reserved Partition
New-Partition -DiskNumber $DiskNumber -Size 128MB -GptType "{e3c9e316-0b5c-4db8-817d-f92df00215ae}"

#Create Primary Partition
$PrimaryPartition = New-Partition -DiskNumber $DiskNumber -UseMaximumSize
$PrimaryPartition | Format-Volume -FileSystem NTFS
$PrimaryPartition | Set-Partition -GptType "{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}"
$PrimaryPartition | Set-Partition -NewDriveLetter "W"

#Shrink Primary Partition by 500MB for the Recovery Partition
$newSize = ($PrimaryPartition.Size - 524288000)
$PrimaryPartition | Resize-Partition -Size $newSize

#Create the Recovery Partition
$RecoveryPartition = New-Partition -DiskNumber $DiskNumber -UseMaximumSize
$RecoveryPartition | Format-Volume -FileSystem NTFS
$RecoveryPartition | Set-Partition -GptType "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"
$RecoveryPartition | Set-Partition -NewDriveLetter "R"

# Add "Required" attribute to the GPT Recovery partition. (No .Net Function available)
$partitionNumber = $RecoveryPartition.PartitionNumber
"select disk $DiskNumber"
"select partition $partitionNumber"
'gpt attributes=0x8000000000000001'

$DiskpartCMD | diskpart.exe

If anyone reading has a PowerShell solution to setting the attributes, please let me know.







Customizing the recovery partition after upgrading the OS from Windows 8.1 to Windows 10



Using Credential Manager in PowerShell

Using PowerShell remoting can be a fantastic experience, but the number of  times I had to enter credentials to make a new pssession is getting out of hand, or to put it better a painful hand. Wouldn’t it be great if you could store the credentials somewhere safe and retrieve it when necessary? Fortunately, you can! Since a long time Windows has had the option to store credentials in a local secured database and use it when needed. This is known as the “Credential Manager” and can be located in the control panel.


Within this tool you can store credentials for both Web Sites and network resources such as remote servers. Wouldn’t it be really cool if you could store credentials there once and retrieve them using PowerShell? Luckily, you can! Someone actually created a PowerShell Module called “CredentialManger” that does just what this post is about.

First, we need to install the module. It’s located in the PowerShell Gallery so you need to trust that Gallery (Use Set-PSRepository) and have NuGet installed. If you didn’t do this just yet, you’ll get additional messages, accept them to continue.

Install-Module -Name "CredentialManager"

To see what the module exposes use:

Get-Command -Module "CredentialManager"


Let’s start with creating new credentials. The CMDLET “New-StoredCredential” seems to do just that. I’ve constructed the following code to create a new set of credentials in the credential manager. The first part prompts for input and stores it in the $Secure variable. Next I create the new object and store it as persistant accross sessions by specifying the “-Persist” parameter. As it’s also a generic type of credentials I explicitly specify that also.

$Target = "YourServerName"
$UserName = "Administrator"
$Secure = Read-host -AsSecureString
New-StoredCredential -Target $Target -UserName $UserName -SecurePassword $Secure -Persist LocalMachine -Type Generic

The output will result in this:


Using the help system I figured out that “Get-StoredCredential” retrieves the objects stored in credential manager. To select the credentials we just created the “-Target” property needs to be specified. In this case we will be referring to the target server we just created, “servername”. Use this command to get all properties into a credentialized object:

Get-StoredCredential -Target "servername" –AsCredentialObject

Retreiving a single pair of credentials is easy, right!? Now what I am after is credentials that are stored for the use in PowerShell remoting. In my specific case to connect to a remote server I’m managing.

Eventually, I created this command-line:

Enter-PSSession -ComputerName "servername" -Authentication Credssp -Credential (Get-StoredCredential -Target "servername")

As you can see the “Get-StoredCredential” needs a target parameter to retrieve the credentials. That outputs a username and password (as System.Security.SecureString) that is then passed to the “Enter-PSSession” cmdlet.


My servername in this case is “WHV” and the credentials are stored as “HyperVManager/WHV”.

Removing credentials using the same module is very straightforward. The “Remove-StoredCredentials” does the trick. Again pointing it to the credentials using the “-Target” parameter.

Remove-StoredCredential -Target "servername"

I hope that this post helps you to use credentials in a safe and easy manner.

ByValue & ByPropertyName

Recently I had the pleasure of attending a PowerShell course. Although it was not exactly what I expected I still picked up a few things here and there. It was good to see that people attending the course got a bit more enthusiastic on PowerShell during the course and they acquired a solid base to start using PowerShell.

On of the items that was discussed was how to use the pipeline. Casting the output of a cmdlet to another. Something obvious as “get-service -name “bits”| start-service” was used during a demo. That’s great for starters, however it gets a little more confusing when cmdlets with a different noun are used. As an example, lets try these two cmdlets to play nice with each other.

Resolve-DnsName <something> | Test-NetConnection

Let first try these two cmdlets individually to see how they actually work. Remember you can always use the help system for more information.

help Resolve-DnsName -Full

Without knowing anything about the cmdlet itself, I’m guessing that it will need a hostname, fqdn or ip address. Just trying a hostname with the name “server” resolves into this:

ByValueProprtyName 01

So apparently I was correct. But how does this actually work? What does this cmdlet actually expect as input? In PowerShell this is really easy to figure out. The next command gets the parameter that’s required for this cmdlet.

get-help Resolve-DnsName -Parameter * | where {($_.Position -eq "0") -and ($_.Required -like "true")}

ByValueProprtyName 02

Here we see that a single input object is required, which is called “Name”. We didn’t specify the Name parameter but it still worked because according to the help system anything on position 0 (The first parameter) is automatically assigned to the first parameter. Let’s try this on “Test-NetConnection”.

ByValueProprtyName 03

Okay… weird that produces absolutely nothing. Not to worry, the cmdlet construction isn’t faulty, “Test-NetConnection” just doesn’t require any input. Running the cmdlet by itself checks connectivity to the Internet.

ByValueProprtyName 04

Since we want to try testing an internal server it would make sense that a certain parameter would accept input. Using “get-help” we would need to figure that out.

get-help Test-NetConnection -Parameter *

ByValueProprtyName 05

Because this cmdlet doesn’t require input, the parameter position “0” is not available. This is now transferred to position “1”. Looking at the help file a parameter with the name “Computername” would do the trick. Let’s try it first without specifying the actual parameter name itself.

ByValueProprtyName 06

Eureka! This works. So combining the two cmdlets would work. Let’s try that.

ByValueProprtyName 07

Hmm no go, bummer. “Test-NetConnection” apparently has no idea what we want to accomplish. Let’s figure out what the result of “Resolve-DnsName” actually is? We do this with

Resolve-DnsName server | gm

GM stands for Get-Members, or “give me all stuff from an object”.

ByValueProprtyName 08

What’s important here is the Typename, “Microsoft.DnsClient.Commands.DnsRecord_A”. This “Type” is the object type that is passed over the pipeline. This object type needs to be something that the receiving end understands. This is the PowerShell technique that is called “ByValue”. So the value type of the object that’s being passed needs to be of the same type.  PowerShell under the hood does it’s magic by trying to match the output of the first cmdlet to the input of the second one IF the object type is the same. So let’s see what “Test-NetConnection” expect.

ByValueProprtyName 09

Using the “Get-help” function again we take a closer look at the “Computername” parameter. The input is specified directly after the parameter name “[<string>]”. So it expects the “ByValue” object name property that is passed over the pipeline to be of the string type. Let’s try the simplistic version first. Just pass a string as input.

“server” | Test-NetConnection

ByValueProprtyName 10

So, now we know that this actually works. Let’s convert the output of the “Resolve-Dnsname” and see what happens.

(Resolve-DnsName server).name.ToString() | Test-NetConnection

ByValueProprtyName 11

That seems to work as well! Please note that you could technically skip the “.ToString” part because the property “name” is already a string, regardless of the original type of the entire object. This wouldn’t work for other properties that have a different type. Use “GM” or the “.GetType()” method again to see the actual type.

ByValueProprtyName 12

Please note that by using “ByValue” you can only pass a single property over the pipeline!


One of the other options that we could also use is the “ByPropertyName” option. As we can see from the help text this option is available for the “Computername” parameter of “Test-NetConnection”.

What this simply means is that the property name of the output of the first cmdlet must match the input parameter of the second cmdlet. In our example the property “Name” of the “Resolve-DnsName” output must match the input parameter “Computername” of the “Test-NetConnection” cmdlet. It doesn’t by now but we can make it so by creating an expression like this:

Resolve-DnsName server | select @{Name="Computername";Expression={$_.name}} | Test-NetConnection

The select statement is where the magic happens. This “Name=” part tells PowerShell that a new property with the name “Computername” should be created. The “Expression” fills that newly created property with the value of the “Name” property of the first cmdlet. The best part here is that the Object type here doesn’t matter, as long as the type of the property matches. In this case it still needs to be a string. However the object type can remain a different type. In this case a “Selected.Microsoft.DnsClient.Commands.DnsRecord_A” object type.

ByValueProprtyName 13

Putting this all together we end up with the following command line:

Resolve-DnsName server | select @{Name="Computername";Expression={$_.name}} | Test-NetConnection

ByValueProprtyName 14

And there we have what we wanted to accomplish!!

As you can see there are multiple ways to go about constructing your entire command line and casting properties over the pipeline. Specially with the “ByValue” and “ByPropertyName” options. I hope that this post added in understanding the differences.


Learn About Using PowerShell Value Binding by Property Name

Two Ways To Accept Pipeline Input In PowerShell

PowerShell – Help

Last year I had the opportunity to self-educate myself on Microsoft PowerShell. Having had just too little experience with it I thought it was about time to dig in and at least learn the basics. So I bought a book and got started. In the next couple of blog posts I will share my experiences and notes that I took over the month’s that I had my first try at learning PowerShell. Although the language can be very complex, it all starts out with having the basic skills to understand the language. After that it’s getting the experience that counts. Today I’ll start with a very important topic. Getting help…

Tip! Always start the PowerShell command-prompt or the Integrated Scripting Environment (ISE) elevated. Throughout the blog post I’ll use the ISE as much as possible. It has far better and more modern way of working.

First things first

The beauty of having PowerShell is that is a modern language integrated with not just local resources but also online repositories. The help functionality is no different. Although Windows ships with an up to date help file for PowerShell, things can change very quickly. So it’s always A good idea to update the local help files every now and again. Here’s a few tips on how to do it.

Update local help files
Use the following Cmdlet to update the help content.


Download help content
Suppose not all your systems are Internet connected, use save-help to store help files locally.

Save-help -path <path>

Use the -SourcePath on the target system to update the help files

Update-Help -SourcePath <path>

Tip! man & help are wrappers for get-Help cmdlet

After the help files are updated it’s time to make use of them. In a command-line environment it’s really not that hard. First you need to figure out what command you need help on. That can easily be done be done with Get-Command. Suppose we want to do something with Windows Services. We could use something like this:

Get-Command *service*

The output will look something like this:


Tip! Use the following to list only the Functions and CmdLets

Get-Command *service* | Where {$_.CommandType -eq "Cmdlet" -or $_.CommandType -eq "Function"} | select Name

Or use the “Commands” Window in the ISE. That will bring up a list of only the Cmdlets (PowerShell Commands) and functions that you can use. Getting help from the ISE is also very easy. Just click on the little blue icon with the question mark to get the help overview.


To get the same output as available in the ISE and more on the command-line, use these parameters after the get-help Cmdlet. Let’s use the Get-Service CmdLet as an example.

Quick help

Get-Help Get-Service

Detailed Help (without parameter details)

Get-Help Get-Service -Detailed

Full information (I always use this)

Get-Help Get-Service -Full


Get-Help Get-Service -Examples

Up-to-date online information

Get-Help Get-Service -Online

That’s all for this post on the PowerShell help system.




0x800b010e – The revocation process could not continue – the certificate(s) could not be checked

I my line of work, every now and then I run into these unique situations. A few weeks ago we needed to do an application upgrade on a few of our systems. Once we started we got the following message:

0x800b010e – The revocation process could not continue – the certificate(s) could not be checked.

Okay, now what? Turns out that the combination of .Net or system hardening with a non-Internet connected system can trigger this error message. What happens is that the systems notices that the software is digitally signed. Because of its policies it tries to check the validity of the certificate and its revocation status. Since our systems are hardened its expected behavior. The software was digitally singed by Microsoft (signing is a good thing btw!), so it tried to reach the public Microsoft servers. Since it wasn’t allowed to go out and fetch the crl it failed. Luckily it’s a simple matter of switching a registry key to turn the revocation check on or off again. Since I can’t remember registry keys (and I seem to forget these kind of little tricks) I’ve written a PowerShell script to enable or disable the offline installation capabilities. Just in case you want to check the value on your system, use the setreg.exe tool from the SDK. In case you’re curious about the registry entry look at:

HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing\State (REG_DWORD)

The default value of state is 23c00 (Hex).

My script can be used with the following parameters:

Set-OfflineInstallationMode.ps1 [-On] [-Off] [-Force]

  • On: Enables the offline installation of signed binary files.
  • Off: Reset the system to the previous (or default) value.
  • Force: Ignore the previous setting and execute anyway.

You can download the script here. Version 1.0


Set Registry Tool (Setreg.exe)




Custom RDP Certificate on Windows Server 2012 R2

Ever since Windows 2012 the Remote Desktop host tool has been removed from the system, making it more difficult to set a custom certificate. When you’re in a domain context it’s more likely that you will use GPO’s and domain related tools to configure your system, but in my work environment I deal with stand-alone systems, making it a bit harder to manage. During one of my security scans with our vulnerability tool it started complaining about self-signed certificates. Simply removing the certificates from the local computer store and using WMI to update the system is fairly easy, but after doing the same trick twice, it gets annoying so I decided to write a PowerShell script to handle the task of setting the correct certificate.

My script has a couple of parameters that you can use:

Set-RDPCertificate.ps1 -Hash <string> [-Delete] [-Terminalname <string>] [<CommonParameters>]
Set-RDPCertificate.ps1 -listCerts [<CommonParameters>]
Set-RDPCertificate.ps1 -ListCurrent [<CommonParameters>]

  • Hash: This is the default input parameter, expects a 40 character string value
  • Delete: Delete the current certificate from the local store after setting the provided hash value.
  • Terminalname: If you changed the default RDP-TCP connection name you can enter it here, not providing the parameter will result in using the default name.
  • Listcert: Lists the certificates in the personal store of the local computer.
  • ListCurrent: Lists all certificates in the personal store of the local computer.

Download the script from here. Version 1.1.