Checking for network cable connections before deploying an OS from the CMG via Software Center

Introduction

Note: In a previous blog post I showed you how you can deploy an Operating System from a Cloud Management Gateway (CMG) using bootable media. That blog post assumed you had a working network connection (wired) and also required the use of bootable media. Please review that blog post and associated video before starting this one. This new ability to deploy OS via the CMG was added to Configuration Manager version 2010, screenshots in this blog post come from Configuration Manager version 2111.

In this blog post, I’ll show you how to allow your users to self-service deploy an operating system from Software Center. That task sequence will run some steps to ensure that they are connected to a LAN cable or USB-C docking station prior to starting.

But why is this important ? Well, if the user is connected to Wi-Fi, then as soon as the task sequence reboots, the boot image will load and unless it knows exactly what Wi-Fi hotspot the user was connected to  and unless it has Wi-Fi support and necessary certificates built in (unlikely) it will fail to pull down any content as there will be no network. Their are 3rd party custom solutions that can allow you to connect to Wi-Fi via the boot image, I haven’t tested them yet due to complexities with our own Enterprise Wi-Fi, but here’s a comprehensive example.

So assuming that you don’t want to use Wi-Fi, read on. In this blog post I’ll show you how to automatically check the type of network connection, and to popup a message to the end user if no wired connection (802.3) is detected. this is done using the PhysicalMediaType and Status properties from Get-NetAdapter.

In the sample below I check for all network adapters on a computer. It lists both wired and wireless (as well as virtual (non-physical)) network adapters. The red box shows the output from a laptop that is docked, as you can see multiple network cards/types are listed.

Get-NetAdapter

no filtering.png

The green output shows the same command but filters on 802.3 physicalmedia type.

Get-NetAdapter  | Where-Object PhysicalMediaType -EQ 802.3

filtering.png

Taking it one step further, you can add the -physical attribute to only show physical network adapters.

Get-NetAdapter -physical | Where-Object PhysicalMediaType -EQ 802.3

physical.png

and from the two network adapters listed here, we can see that only one of them has a status of Up, meaning that is it connected. We could even filter for that as shown here.

Get-NetAdapter -physical | Where-Object {$_.PhysicalMediaType -EQ 802.3 -and $_.Status -EQ "Up"}

filtered to physical and up.png

 

Using this logic we can build a script to detect the desired type of network and to popup a message to the end user if it’s not connected.

 

Step 1. Get the script

The following script does the checking, save it to a folder called CheckNetworkCable.
 

<#
.SYNOPSIS
	This script checks if a network cable is connected or not, if not, pops up message to connect
.DESCRIPTION
	For more info see https://www.windows-noob.com/forums/topic/22678-checking-for-network-cable-connections-before-deploying-an-os-from-the-cmg-via-software-center/
.PARAMETER [none]
	This script does not take any parameters.
.EXAMPLE
	
.NOTES
	Version: 0.1 2021/12/5
    Version: 0.2 2021/12/6 lan cable re-check
    Version: 0.3 2021/12/7 hide tsprogressui
    Version: 0.4 2021/12/8 loop through multiple 802.3 NIC types if present and check status, added Cancel ability to the popup message
    Version: 0.5 2021/12/9 check for VM and exit if so, added ExitValue
.LINK 
	.Author Niall Brady 2021/12/5
#>

Function LogWrite
{
   Param ([string]$logstring)
   $a = Get-Date
   $logstring = $a,$logstring
   Try
{
    Add-content $Logfile -value $logstring  -ErrorAction silentlycontinue
}
Catch
{
    $logstring="Invalid data encountered"
    Add-content $Logfile -value $logstring
}
   write-host $logstring
}

function CheckCable{
# checks 802.3 LAN connections for a status of Up, loops through all 802.3 nics found before popping up message if none are connected
$global:connected = $null
$networkcards = Get-NetAdapter -Physical | select Name, PhysicalMediaType, InterfaceDescription, Status
LogWrite "Checking the following 802.3 NIC(s): " $networkcards

foreach ($networkcard in $networkcards) {
# only interested in 802.3 nics...
if ($networkcard.PhysicalMediaType -eq '802.3'){
    $description = $networkcard.InterfaceDescription
    LogWrite "examining the following NIC: $description"

    if ($networkcard.status -eq 'Up') 
  { 
   LogWrite "Network Cable: CONNECTED"
   $global:connected = $true
   $ExitValue = 0
   ExitScript ($ExitValue)
   } 
                 
  else { 
  LogWrite "Network Cable: DISCONNECTED"
   $global:connected = $false   
	    }

}

  }
            LogWrite "Showing end user the 'Please connect to a network cable' popup message"
            Add-Type -AssemblyName PresentationCore,PresentationFramework
            $msgBody = "Please connect to a wired network or USB-C docking station to continue. Once connected, wait a few seconds then click <OK>, or click <Cancel> to abort this operation."
            $msgTitle = "You must connect to suitable network."
            $msgButton = 'OKCANCEL'
            $msgImage = 'info'
            $Result = [System.Windows.MessageBox]::Show($msgBody,$msgTitle,$msgButton,$msgImage)
            LogWrite "The user chose: '$result'"
            $global:connected = $false
            if ($Result -eq 'Cancel') {
            LogWrite "The user chose cancel to insert network cable popup message"
            $ExitValue = 1
            ExitScript ($ExitValue)
            }
}

Function ExitScript ($ExitValue) {
LogWrite "Exiting from the '$scriptname' version '$version' script with exit code $ExitValue."
Exit $ExitValue

}

###########################################################################################
# script body starts here...

$scriptname = "Check if LAN cable is Connected"
$version = "0.5"
$logfile = "$env:temp\CheckNetworkCableConnected.log"

LogWrite "Starting the '$scriptname' version '$version' script..."

#Hide the progress dialog
try {
    LogWrite "hiding the task sequence progress user interface"
    $TSProgressUI = new-object -comobject Microsoft.SMS.TSProgressUI
    $TSProgressUI.CloseProgressDialog()}
catch
{LogWrite "failed to hide the Task Sequence UI, are we really in a task sequence ?"}

# check is this a vm, exit if so...
$IsVirtual=((Get-WmiObject win32_computersystem).model -eq 'VMware Virtual Platform' -or ((Get-WmiObject win32_computersystem).model -eq 'Virtual Machine'))
 if ($IsVirtual) {LogWrite "virtual machine detected, will exit now."
 $ExitValue = 0
 ExitScript ($ExitValue)
 }
 else
 {LogWrite "Virtual machine not detected, continuing..."}
do{
LogWrite "Looping until connected..."
CheckCable
 }
            
until($connected -eq $true)
$ExitValue = 0
ExitScript ($ExitValue)

Step 2. Get ServiceUI.exe from MDT

You’ll need the ServiceUI.exe executable file to display user interfaces (UI) to end users when operating in SYSTEM context. To get the file, download and install MDT somewhere and navigate to C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64. To download MDT click here.

Copy the ServiceUI.exe file to your extracted CheckNetworkCable folder so it looks like this.

CheckNetworkCable folder.png

Next, copy this folder to your package source on your Configuration Manager server.

Step 3. Create a package (with no program)

In ConfigMgr create a new package *with no program* using the files in the CheckNetworkCable folder you created above.

create package.png

Step 4. Distribute the package

After creating the package, right click it and choose Distribute Content. Distribute the content to all of your CMG’s and any other on-premise distribution points.

distribute to cmg.png

Step 5. Edit the task sequence and point to the package

In your task sequence, add the following lines at the start of the task sequence.

cmd.exe /c mkdir C:\Windows\Temp\OSDScripts\

 

Then copy files to the C:\Windows\Temp\OSDScripts folder..

xcopy ".\ServiceUI.exe" "C:\Windows\Temp\OSDScripts\" /D /E /C /I /Q /H /R /Y /S

copy first file to folder.png

 

copy another file…

xcopy ".\CheckNetwork.ps1" "C:\Windows\Temp\OSDScripts\" /D /E /C /I /Q /H /R /Y /S

copy second file to folder.png

 

Run the script, note: do NOT select the timeout value in this step otherwise it will fail.

C:\Windows\Temp\OSDScripts\ServiceUI.exe -process:TSProgressUI.exe %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -NoProfile -ExecutionPolicy bypass -File C:\Windows\Temp\OSDScripts\CheckNetwork.ps1

run the check for network script.png

Apply the changes.

Don’t forget to distribute the content contained in your task sequence to your CMG.

distribute task sequence content to CMG.png

Step 6. deploy the Task sequence

Deploy your task sequence as Available to a collection containing client computers that you intend to test with, make sure that the following option is selected.

allow task sequence to run for clients on the internet.png

Step 7. Test the solution

On a client computer with real network cards (or with a connection to a USB-C hub or Thunderbolt 3 dock that is in turn connected to a wired LAN), verify that the Configuration Manager client detects that it is connected to the Internet and that you can see the task sequence in Software Center.

For the purposes of the test, unplug the dock and/or network cable and use Wi-Fi to test.

client is on Internet and can see the task sequence.png

Note: The script detects virtual machines and assumes they have network connectivity and therefore skips the popup. This particular task sequence also informs the user about the type of network they need to use, but we’ll still run our detection script.

testing.png

 

If the user is not connected to a wired LAN cable or USB-C docking station, they’ll get this popup.

message popup.png

After connecting to the required network type and clicking OK the task sequence will continue.

Job done.

Troubleshooting

The script logs to C:\Windows\Temp\CheckForNetworkCable.log. Below we can see that at first the cable was disconnected, and then the user connected the cable and it allowed the script to continue.

logfile.png

Related reading

https://docs.microsoft.com/en-us/mem/configmgr/osd/deploy-use/deploy-task-sequence-over-internet

This entry was posted in 2111, CMG, System Center Configuration Manager (Current Branch). Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.