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
The green output shows the same command but filters on 802.3 physicalmedia type.
Get-NetAdapter | Where-Object PhysicalMediaType -EQ 802.3
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
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"}
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.
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.
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.
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 another file…
xcopy ".\CheckNetwork.ps1" "C:\Windows\Temp\OSDScripts\" /D /E /C /I /Q /H /R /Y /S
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
Apply the changes.
Don’t forget to distribute the content contained in your task sequence to your CMG.
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.
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.
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.
If the user is not connected to a wired LAN cable or USB-C docking station, they’ll get this popup.
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.
Related reading
https://docs.microsoft.com/en-us/mem/configmgr/osd/deploy-use/deploy-task-sequence-over-internet