Help! Telnet not installed!

If you’re a system administrator the following has probably happened to you: you’re trying to troubleshoot a connection issue to a service in the environment and you want to test if a specific port is open on the destination machine. Being the veteran that you are you immediately turn to the trusted telnet command only to receive the dredded Telnet is not recognized as a command… error notifying you the client is not installed on the local system.

So now what? Sure you can simply install the client and go back to your old ways but there’s a better alternative these days that requires no installation: the PowerShell command Test-NetConnection.
(not available on Windows 7 but we’ll fix that later on)

To test port connectivity like you would using telnet you simply open a powershell console and type:

Test-NetConnection -ComputerName www.peppercrew.nl -Port 443

This will perform a ping and tests port connectivity, giving you the following output:

ComputerName           : www.peppercrew.nl
RemoteAddress : 104.207.253.58
RemotePort : 443
InterfaceAlias : LAN01
SourceAddress : 10.100.1.12
PingSucceeded : True
PingReplyDetails (RTT) : 157 ms
TcpTestSucceeded : True

As you can see, the ping succeeded and so did the TcpTest on port 443. You can also use the InformationLevel parameter with value Quiet if you only need a boolean (true/false) answer to your request. This is recommended practice when using this command in a script because it is much faster. The Test-NetConnection command is even faster than the Test-Connection command. It’s also more versatile: it can also be used for route tracing and route selection diagnostics.

If you’re environment is a bit behind and you’re source computer is still on Windows 7 or Server 2018 R2 then you’re out of luck: the Test-NetConnection command is not available on these operating systems even when you have PowerShell 5.1 installed. There’s still one alternative that does not require installing telnet! Just open you PowerShell console and type:

[System.Net.Sockets.TcpClient]::new('www.peppercrew.nl',443)

This syntax is a little more difficult to remember because it’s dotnet, but it works like a charm. This command gives you the following output:

Client              : System.Net.Sockets.Socket
Available : 0
Connected : True
ExclusiveAddressUse : False
ReceiveBufferSize : 65536
SendBufferSize : 64512
ReceiveTimeout : 0
SendTimeout : 0
LingerState : System.Net.Sockets.LingerOption
NoDelay : False

As you can see by the value in the Connected property the port connection succeeded. I’ve used this method to create a Windows 7 version of the Test-NetConnection commandIt works very much the same as it’s Windows 8+ counterpart (no route tracing though). You can add ports you test regularly to the CommonTCPPort parameter list in the begin block (you have to add them to the validation set on the parameter as well). Hopefully it will be helpful for some of you.

<#
.Synopsis
   Displays diagnostic information for a connection.
.DESCRIPTION
   The Test-NetConnection cmdlet displays diagnostic information for a connection. 
   It supports ping test and TCP test. Depending on the input parameters, the output 
   can include the DNS lookup results, a list of IP interfaces and/or confirmation 
   of connection establishment.
.EXAMPLE
   Test-NetConnection
   Test internet connectivity (port 80)
.EXAMPLE
   Test-NetConnection -CommonTCPPort HTTPS
   Test internet connectivity (port 443)
.EXAMPLE
   Test-NetConnection -ComputerName SRV-001
   Test connection to computer SRV-001 (ping only)
.EXAMPLE
   Test-NetConnection -ComputerName SRV-001 -Port 3193
   Test port connection to computer SRV-001 using port 3193 (Detailed)
.EXAMPLE
   Test-NetConnection -ComputerName 10.100.10.15 -CommonTCPPort WINRM -InformationLevel Quiet
   Test port connection on ip address 10.100.10.15 on the Windows Remote Management port (True/False)
#>
function Test-NetConnection 
{
    [CmdletBinding(DefaultParameterSetName='Port')]
    [Alias('telnet','tnc')]
    Param
    (
        # Specifies the Domain Name System (DNS) name or IP address of the target computer that runs the Dynamic Host Configuration Protocol (DHCP) server service.
        [Parameter(ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [Alias('Name','PSComputerName','VMName')]
        [string]
        $ComputerName = 'internetbeacon.msedge.net',

        # Specifies the TCP port number on the remote computer. The cmdlet uses this port number to test connectivity to the remote computer.
        [Parameter(ParameterSetName='Port',
                   Position=1)]
        [int]
        $Port,

        # Specifies the common service TCP port number.
        [Parameter(Mandatory=$true,
                   ParameterSetName='CommonPort',
                   Position=1)]
        [ValidateSet('SMB','HTTP','HTTPS','RDP','WINRM')]
        [string]
        $CommonTCPPort,

        # Specifies the information level.
        [Parameter(Position=2)]
        [ValidateSet('Detailed','Quiet')]
        [string]
        $InformationLevel = 'Detailed'
    )

    Begin
    {
        If ($PSBoundParameters['CommonTCPPort'])
        {
            switch ($CommonTCPPort)
            {
                SMB   {$Port = 445}
                HTTP  {$Port = 80}
                HTTPS {$Port = 443}
                RDP   {$Port = 3389}
                WINRM {$Port = 5985}
            }
        }
        If (!$PSBoundParameters['ComputerName'] -and !$PSBoundParameters['Port'])
        {
            $Port = 80
        }
    }
    Process
    {
        try
        {
            $IPDestination = [System.Net.Dns]::GetHostEntry($ComputerName).AddressList.IPAddressToString
        }
        catch
        {
            Write-Warning "Ping to $ComputerName failed"
        }
        If (!($PSBoundParameters['Port'] -and $InformationLevel -eq 'Quiet'))
        {
            try
            {
                $Ping = [System.Net.NetworkInformation.Ping]::new().Send($ComputerName)
                $PingSuccess = $Ping.Status -eq 'Success'
            }
            catch{
                $PingSuccess = $false
            }
            If (!$PingSuccess)
            {
                Write-Warning "Ping to $ComputerName failed"
            }
        }
        If ($Port)
        {
            Try
            {
                $TcpClient = [System.Net.Sockets.TcpClient]::new($IPDestination,$Port)
            }
            catch{}
            If ($TcpClient)
            {
                $Connected = $TcpClient.Connected
            }
            else
            {
                $Connected = $false
            }
            If (!$Connected)
            {
                Write-Warning "TCP connect to $ComputerName`:$Port failed"
            }
        }
        switch ($InformationLevel)
        {
            Quiet    {
                If ($PSBoundParameters['Port'] -or $PSBoundParameters['CommonTCPPort'])
                {
                    return $Connected
                }
                else
                {
                    return $PingSuccess
                }
            }
            Detailed {
                $Adapter = Get-WmiObject Win32_NetworkAdapter -Filter "PhysicalAdapter='True' AND NetEnabled='True'"
                If ($Adapter.Count -gt 1)
                {
                    (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage").Bind.foreach({
                        $GUID = $_.Split('\')[2]
                        If ($GUID -in $Adapter.GUID)
                        {
                            $Adapter = $Adapter.Where({$_.GUID -eq $GUID})
                            Break
                        }
                    })
                }
                $AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "Index = $($Adapter.DeviceID)"
                [pscustomobject]@{
                    ComputerName             = $ComputerName
                    RemoteAddress            = $IPDestination
                    PingSucceeded            = $PingSuccess
                    'PingReplyDetails (RTT)' = $Ping.RoundtripTime.ToString() + ' ms'
                    RemotePort               = $Port
                    InterfaceAlias           = $Adapter.NetConnectionID
                    InterfaceIndex           = $Adapter.InterfaceIndex
                    InterfaceDescription     = $Adapter.Description
                    NetAdapter               = $Adapter
                    SourceAddress            = $AdapterConfig.IPAddress
                    TcpTestSucceeded         = $Connected
                }
            }
        }
    }
}

Preserve audio volume and mute in RES One Workspace

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com.

RES One Workspace has a lot of great options to preserve your settings between sessions. But some settings are not as easy to capture because there’s no file or registry setting for them. One of these troublemakers is the volume of the audio. If you’ve adjusted the volume in a session to be less than 100% or even muted the audio completely you’ll find yourself having to do this each time you start a new session (unless you’re on a dedicated persistent client of course).  Read more

Capture multiple images using one MDT task sequence

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com.

If you deploy images in your environment that are very similar, meaning one has a few more applications installed than the other, then this is the blogpost for you! In this blogpost I’m going to share a script with you that will allow you to capture multiple images in one WIM file using only one MDT task sequence. Sound good? Let’s get cracking!  Read more

RES One Automation PowerShell Module

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com.

resam-posh

When you’re a system administrator and a PowerShell enthusiast a single solution to a problem can result in something big and elaborate. A while ago I was implementing a MDT environment for a customer. I wanted to fill the MDT database with all existing client computers. For that I needed all the clients names and their MAC addresses. Client names weren’t the issue but MAC addresses were a little bit more challenging. I decided to turn to RES One Automation (RES AM) for help. I knew RES AM has the ability to identify agents by their MAC address so it has to store all agent MAC addresses in the datastore. After figuring out how to pry this information from the database I started to wonder what else I could find in there. This resulted in a complete PowerShell module (my first!) for RES One Automation!  Read more

Configure WER User-Mode (Application) crash dumps PowerShell-style

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com.

When you’re a system administrator you’re likely to encounter a few application crashes during your career. In order to troubleshoot these crashes Windows Error Reporting (WER) comes in handy. It can be configured so that full user-mode dumps are collected and stored locally after a user-mode application crashes. You can than send the dumps to the software supplier or analyse it yourself using your tool of choice. Read more

Copy AD group memberships from a source user to other users

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com

One of those mondaine tasks you get to do as an IT administrator is assigning users to security groups for access to resources in the domain. Usually, when you ask the person making this request which security groups the user account needs membership for, they’ll tell you to use some other user account as a reference. Sometime you’ll even get a list of users that need to have the same memberships. Read more

Change network connection category using PowerShell

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com

 

refwin-advfirewall-img4

I recently came across an issue with PSRemoting to a Windows 7 XenDesktop VM. I discovered remoting was disabled on the remote system because one of the network connections was a Public connection (it was the PVS connection). To change this using PowerShell is quite easy in Windows 8 or higher: the Set-NetConnectionProfile command is available to do just that. However, in Windows 7 this is not so easy. Even though PowerShell 4 was installed, the command was absent. So I decided to create my own functions to facilitate this, based on this script by Microsoft: LINK. This script utilizes the Network List Manager to make the change.  Read more

Create a custom Deployment Wizard pane for Updates (MDT)

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com

One of the great things about the Microsoft Deployment Toolkit (MDT) is that it’s a very open product. All the scripts are customizable, including the Deployment Wizard. We can add new functionality to the deployment procedure and add wizard pages so we can choose to use those new functions (or not) with each new deployment. Microsoft encourages creativity for this particular product. One of the functions I wanted to create a wizard page for was the deployment of updates. I wanted to be able to choose between a quick OS deployment for test purposes (no updates) and a slower, more production worthy deployment (with updates). And since I take my deployment VM on the road with me, I wanted the ability to choose if the updates are downloaded from Microsoft Update or a clients’ WSUS server. The result looks like this:

Result Update Pane

Here’s how it’s done: Read more

Add WSUS Target Group option to MDT deployments

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com

One of the great features you get when deploying a Windows operating system using my favorite deployment tool, the Microsoft Deployment Toolkit (MDT), is the ability to update the OS using either Windows Update or a local WSUS server. The latter is obviously preferred because it’s a lot quicker and you have better control over what updates you want to install. WSUS has a feature called Target groups, which you can utilize for managing update approvals for a group of computers. This way you’ll be able to approve or decline specific updates for  Remote Desktop Session hosts or Exchange servers etc. While MDT let’s you specify a WSUS server to get updates from there’s no way to specify the target group you want to receive updates from. Let’s fix that, shall we? Read more

Screensaver not working in a XenDesktop VDI environment

Note: This blogpost is also posted on my personal blog – https://itmicah.wordpress.com

I was troubleshooting some RES Workspace Manager (RES WM) issues in a customer’s XenDesktop 7.x (Citrix) environment when I came across the following issue: The screensaver didn’t start automatically, even though I had forced a screensaver through RES WM. After some research I’d come to the conclusion that this was a known issue in XenDesktop 7.x. Apparently Citrix has decided to disable Screensavers and power-save options in XenDesktop. They provide the following solution in their eDocs documentation: Read more