MSEndpointMgr

Build a WinPE with wireless support

Deploying Windows with the help of a Windows Preinstallation Environment (WinPE) is known since the release of Windows XP. We always take care of adding network drivers to WinPE to support our various models in the environment. The standard WinPE provided by the Windows Assessment and Deployment Kit (Windows ADK) does not have any support for wireless network. Even the latest (at the time of writing) WinPE version 1709 (10.0.16299) does not provide native wireless support. If we look at the Windows Recovery Environment (WinRE) you can find an additional optional component that provides WiFi support for the WinRE. This is easily verified by mounting the WinRE with dism and listing the features:

dism /Image:C:\mount\offline /Get-Features

The output should list all available features and the additional WinPE-WiFi feature only provided in WinRE:

Feature Name : WinPE-WiFi
State : Enabled

All we need to do is to replace our WinPE with a WinRE and some additional modifications to get wireless support in our new WinPE. The modifications are basically:

  • adding wireless drivers to the PE if needed (I used a Surface devices which has wireless driver support out of the box)
  • removing or modifying winpeshl.ini as it tries to load the recovery environment of the WinRE
  • adding back some dependency dlls otherwise the support is broken for WinPE version later than 1511
  • creating a wireless xml profile
  • assigning and connecting to the wireless network via netsh
  • a good strategy how to use the new wireless support with MDT and ConfigMgr 🙂

Building a test WinPE with wireless support

  • Create a folder C:\mount and a sub folder offline
    md C:\mount\offline
  • copy WinRE from the Windows folder to the new mount folder (assuming the running OS on which the new WinPE is created is Windows 10 1709)
    copy /y C:\Windows\System32\Recovery\Winre.wim C:\mount
  • Mount the WinRE to C:\mount\offline
    dism /Mount-Image /ImageFile:C:\mount\winre.wim /index:1 /MountDir:C:\mount\offline /Optimize
  • Copy missing libraries (dlls) to WinRE
    copy /y C:\Windows\System32\dmcmnutils.dll C:\mount\offline\Windows\System32
    copy /y C:\Windows\System32\mdmregistration.dll  C:\mount\offline\Windows\System32

    Without the additional dlls you will get the following error when using netsh in the wlan context (netsh wlan): The following helper DLL cannot be loaded: WLANCFG.DLL. I troubleshoot this with the help of the Dependency Walker (depends.exe). I loaded wlancfg.dll with depends.exe within the WinPE environment and observed mdmregistration.dll listed as “Error opening file. The system cannot find the file specified“. Loading mdmregistration.dll then and found the second layer dependency dmcmnutils.dll with the same error. I added them to the WinRE and the initial error for wlancfg.dll was solved. After a manual connect via netsh the wlan context was working. All this is needed for WinRE versions 1607 and later. With a WinRE version 1511 it is working without the two dlls.

  • Create the wireless xml profile Wi-Fi-YourNetwork.xml by exporting your Wi-Fi with netsh wlan export
    netsh wlan export profile name=YourNetwork key=clear

    Note that the described WinPE setup does support shared key authentication with Open\WEP\WPA and WPA2. The command above will export the shared key as plain text within the xml file!

  • Create a batch file wlan.cmd to start the WLAN AutoConfig Service and use netsh to add a wireless profile to the wlan interface and finally connect to the wireless network
    net start wlansvc
    netsh wlan add profile filename=Wi-Fi-YourNetwork.xml
    netsh wlan connect name=YourNetwork ssid=YourNetwork
    ping localhost -n 30 >nul

    The timeout of 30 seconds (build with the ping command) is needed to make sure the script pauses some time to let the wireless network stack connect to the wireless network. My tests have shown between 30-45 seconds are needed to successfully connect, get an IP address, and to have a valid connection in the end.

  • Remove the winpeshl.ini file as it has an entry to load the recovery environment
    del /q C:\mount\Windows\System32\winpeshl.ini
  • Un-mount the WinRE file to get our newly created WinPE with wireless support
    Dism /Unmount-Image /MountDir:C:\mount\offline /commit

Please note the downside of this approach is the plaintext shared key in the Wi-Fi-YourNetwork.xml file.

Now we have a tow basic options what to do with the new test WinPE. Here some ideas:

  1. use it with MDT
    rename the existing winpe.wim template in the path:

    C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\en-us\winpe.wim

    and copy the newly created one as winpe.wim there. Now we can build a MDT solution with our new WinPE. As soon as the WinPE is loaded we can test wireless by hitting F8 and type wlan.cmd.

  2. use it with ConfigMgr
    I didn’t test yet but as we need the support for the wireless network very early in the process, I assume we need to hook something into TsBootShell.ini, and let the system connect to the wireless before starting the actual task sequence.

User driven experience with wireless connect

I built a solution with MDT which does not use the Wi-Fi-YourNetwork.xml file which has the plain text key material. The solution is a simple .NET 4.5 program to simplify the connection to a wireless network. Remember to add .NET framework support to the WinPE. The tool will create the xml file with the correct parameters provided by the UI and connects to the wireless network. It will make active probes to the Microsoft Network Connection Status Indicator (NCSI) to verify if there is an internet connection. This can be easily overwritten by providing a parameter during startup of the tool via:

WirelessConnect.exe <specify-custom-url-as-arg-here>

To support the keyboard button we must add the osk.exe and osksupport.dll to the execution directory of WirelessConnect. The .NET solution WirelessConnect can be found on my GitHub Helper repository here:
https://github.com/okieselbach/Helpers

After download we can create a MDT bootable USB device with wireless support and easy connection handling with WirelessConnect.exe. We provide the WirelessConnect.exe and the unattend.xml file for the WinPE as an extra file in MDT to start the WirelessConnect.exe before we run the MDT LiteTouch process.

Unattend.xml

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="windowsPE">
        <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="https://schemas.microsoft.com/WMIConfig/2002/State">
            <Display>
                <ColorDepth>32</ColorDepth>
                <HorizontalResolution>1024</HorizontalResolution>
                <RefreshRate>60</RefreshRate>
                <VerticalResolution>768</VerticalResolution>
            </Display>
            <RunSynchronous>
                <RunSynchronousCommand wcm:action="add">
                    <Description>Start Wireless Connect</Description>
                    <Order>1</Order>
                    <Path>X:\WirelessConnect.exe</Path>
                </RunSynchronousCommand>
                <RunSynchronousCommand wcm:action="add">
                    <Description>Lite Touch PE</Description>
                    <Order>2</Order>
                    <Path>wscript.exe X:\Deploy\Scripts\LiteTouch.wsf</Path>
                </RunSynchronousCommand>
            </RunSynchronous>
        </component>
    </settings>
</unattend>

When using MDT we can also easily provide mdmregistration.dll and dmcmnutils.dll in a sub folder Windows\System within the extra directory to add. The MDT process will only need a modified WinRE to have no winpeshl.ini file and then MDT builds the complete WinPE for us.

The ExtraFiles folder should look like this:

  • WirelessConnect.exe
  • unattend.xml
  • Windows\System32\mdmregistration.dll
  • Windows\System32\dmcmnutils.dll
  • osk.exe
  • osksupport.dll

Adding an extra directory to MDT is a simple task:

As last step I needed to modify ZTIUtility.vbs to support a deployment via wireless network:

If sIPConnectionMetric = "" Then
   ' ################################################################ MODIFIED CODE #########################################################################
   'oLogging.CreateEntry "No physical adapters present, cannot deploy over wireless", LogTypeError
   'ValidateNetworkConnectivity = Failure
   'Exit Function
   oLogging.CreateEntry "No physical adapters present, cannot deploy over wireless", LogTypeInfo
   oLogging.CreateEntry "=> normally MDT would exit here!", LogTypeInfo
   oLogging.CreateEntry "=> CUSTOM HOOK UP", LogTypeInfo
   ' ################################################################ MODIFIED CODE #########################################################################
End IF

If everything was successful you will see the WirelessConnect UI from above and you are able to connect to your wireless network protected by WPA/WPA2/WEP or as an Open network before the task sequence will start.

Additional considerations need to be made when dealing with reboots during WinPE phase to ensure proper reconnect and during OS phase. Basically I wanted to show the possibility to provide wireless support, even when not used with OSD it might help in other scenarios.

Oliver Kieselbach

Oliver started as a System Engineer and is now a Lead Cloud Architect and has been working in the IT industry for the past 15+ years specializing in Enterprise Mobility and Security, Deployment and Automation. Oliver has been awarded Enterprise Mobility MVP in August 2018. Currently working for Glück & Kanja Consulting AG and is engaged in enterprise projects with up to 100k endpoints. Most recent focus has been on Modern Management projects, helping customers to solve actual challenges there. In 2017, Oliver has founded https://oliverkieselbach.com blog and is blogging on MSEndpointMgr.

14 comments

  • Hi Oliver,

    I must still be missing something and I believe it has to do with my “LiteTouchPE_x64.iso” not getting updated to reflect the changes. I am right clicking to run the Update Deployment Share Wizard.

    What I am finding is the wlan.cmd is not in the X:\Windows\System32 folder of the LiteTouchPE_x64.iso but rather in the root of “X:” I did manually copy the required files in your steps will the “winre.wim” was mounted as well as the specified “D:\DeploymentShare\ExtraFiles”

    If I F8 to CMD and try to run the wlan.cmd manually I get “net start wlansvc”, The service name is invalid. If I run this from the Windows\System32 folder I get, “The system cannot find the path specified”

    Please advise,
    Niles

    • Hi Niles,

      Sorry for my late response, due to long vacation. Did you rename the existing winpe.wim template in the path: C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\en-us\winpe.wim to for example winpe_original.wim and copied the winre.wim in there and renamed this to winpe.wim? Otherwise the MDT update process will not pick the right wim file? This is normally everything you need to do.

      best,
      Oliver

  • Ok, figure it out. I did not create the Windows\System32 folder under ExtraFiles.

    Any tips on how to change the DeploymentShare that WinPE keeps trying to access? I have change the default path but WinPE is still pointing to DeploymentShare$

    • Hi,

      open the properties of the MDT share and click on WinPE > Rules > Edit Bootstrap.ini there you modify DeployRoot property.
      DeployRoot=\\192.168.1.1\DeploymentShare$

      best,
      Oliver

  • Hi Oliver,

    Thank you for your reply. I believe I have everything configured correctly. However, when I boot from the LiteTouchPE_x64.iso I get the following error,

    “Not enough memory resources are available to process this command”

    Any thoughts?

    • Hi Niles,

      I think you have to increase the “Scratch space size” to more than 32 MB. I usually increase the size to 128 or 265 MB. This solves this kind of problems.
      To do that go to the Properties of your MDT share in the section WinPE, choose your architecture (x64) and then increase the Scratch size.

      best,
      Oliver

  • Is there a way to auto run the wlan.cmd before WinPE attempts to connect to the MDT share?

    • Hi Niles,

      yes use the approach like described below with the unattend.xml file for the WinPE. Instead of calling WirelessConnect.exe replace it with wlan.cmd, then rebuild the WinPE (Update Deployment Share) and your WinPE has everything necessary to start the commands to create the wireless connection.

      best,
      Oliver

  • Hi Oliver,

    Is there a way for the WirelessConnection application to automatically after it has connected to a network?

    • Hi Jon,

      sorry for the delay. There is nothing built-in but as it is a C# GitHub project you can easily clone and modify yourself and enhance it with every functionality you like.

      best,
      Oliver

    • Hi Yisrael,

      I didn’t try to but it may be possible. You need to create a correct Wi-Fi EAP xml profile and a certificate in the machine store. But I see problems here as you need to use a static cert because I don’t know how to distribute device individual certs in a clever way. The cert must be available in WinPE session and later on during Windows session. This all seems not very easy but it may be solvable.

      best,
      Oliver

Sponsors