This page details how to use custom entries with WinPEShl.ini to run custom actions before or after the machine boots.
2PXE writes a new WinPEShl.ini into the %programdata% directory each time it starts, one for x86 builds and one for x64 builds.
NOTE:
Please note that the WinPEShl.ini is ONLY transferred by default if the underlying configuration requires this. This is normally only the case for ConfigMgr related environments, and not other types of custom iPXE Anywhere Web Service scenarios. But the same file can be retrieved and injected if required.
The following text is written into the winpeshl.ini by default for an x64 boot image: (the x86 has other paths)
[LaunchApps]
%SYSTEMDRIVE%\sms\bin\x64\TsProgressUI.exe,/register:winpe %windir%\system32\iPXEWinPEClient.exe,/NetworkInit %windir%\system32\iPXEWinPEClient.exe,/SkipNetworkInit %SYSTEMDRIVE%\sms\bin\x64\TsBootShell.exe
The x86 part with it's default paths:
[LaunchApps]
%SYSTEMDRIVE%\sms\bin\i386\TsProgressUI.exe,/register:winpe %windir%\system32\iPXEWinPEClient.exe,/NetworkInit %windir%\system32\iPXEWinPEClient.exe,/SkipNetworkInit %SYSTEMDRIVE%\sms\bin\i386\TsBootShell.exe
The first line initialises the TSProgressUI.exe in WinPE to show ConfigMgr progress UI. This is done so that the second command, the iPXEWinPEClient.exe can show progress.
The second command, initialises the network drivers in a way that guarantees that the network is available at the time of the second command exits. It' seems as a trivial task, but is actually harder than what most people realise, as the WinPE environment linked with some extra interesting drivers for special hardware and it's a complicated mess to sort out.
The third command runs the iPXEWinPEClient.exe, but skips the network init, causing it to just contact the iPXE Anywhere infrastructure to report back/get any command line information required to run from the server side PowerShell script in the iPXE Anywhere Web Service.
The fourth command runs TSBootShell.exe that starts the whole OSD process. That's it.
If you want to modify the content of these WinPEShl.ini files, you can edit them directly in files under 2PXE's %ProgramData% directories, but the changes are only there until service restart. So if you want the change to be permanent, you need to change the .config file for 2PXE.
The following shows how to put an entry in the .config file for 2PXE, the key x64WinPEShlConfiguration and x86WinPEShlConfiguration. So the following adds a new step in there to launch a cmd.exe before it starts the TSBootShell.exe.
The corresponding for an x86 system:
There are a few tips here on the syntax:
Note that the x86 and x64 entries are just for matching the machines booting, NOT the server itself.
As this is XML, some characters might need to be encoded, using XML encoding syntax to allow proper handling of the .config file itself.
If you mess up the .config file, the service will fail to start and crash.
Given point two above, make sure you check the xml integrity if you are uncertain using an XML parser that is better than notepad.exe.
If you don't have carriage return + newline by separating into the same line, you can do the same via \r\n in the line above.
When using OneVinn's/Johan Schreweliu's TSBackground app, the syntax needs to be updated a little to avoid having it crash. If you never heard of it, check out: https://onevinn.schrewelius.it/Apps01.html
So What needs to happen is the following line has to be added after iPXE Anywhere have done their bits, which is done by adding: %SYSTEMDRIVE%\sms\bin\x64\TsProgressUI.exe,/unregister
This then unloads the TSProgressUI in process COM server to allow TSBackground to override it, without it, it will look messy.
[LaunchApps]
%SYSTEMDRIVE%\sms\bin\x64\TsProgressUI.exe,/register:winpe %windir%\system32\iPXEWinPEClient.exe,/NetworkInit %windir%\system32\iPXEWinPEClient.exe,/SkipNetworkInit
%SYSTEMDRIVE%\sms\bin\x64\TsProgressUI.exe,/unregister
x:\sms\pkg\sms10000\TSBackground\TSBackground.exe
Given above, the following would be the .config entry:
This page explains hot the CustomMenuItems item in the .config file works to allow custom actions in the 2PXE menu.
Note: Please use 2.9.18.0 or later with 2PXE when experimenting with this.
The CustomMenuItems section provides the following capabilities;
Provide a way to link custom iPXE scripting language with an entry in the menu provided by 2PXE.
Using the custom script entry, a call to the iPXE Anywhere Web Service can be made to create custom scripting scenarios from the 2PXE boot menu.
Define one or many entries in the CustomMenuItems using the key/value format, where;
The "key" value links to an entry under CustomItems which is just below in the same .config file.
The "value" value is the display text shown in the menu itself on the machine you are booting.
The below scenario is linking a single entry as per below, in this case, we create a single entry with the "key" set to "myShell", and the display text will then be "iPXE Shell" in the menu:
So then we need a matching entry with iPXE code in the "CustomItems" sections. In this case, it's simple, create a key with "myShell" identifier, linking with above, then the iPXE code snippet to start a shell, is "shell". Simple!
After the snippet returns, it will run the "goto keypressed" label, which is an internal label to return to the menu. You can call this yourself in your custom script if you want to exit out early.
You can have multiple items in here, as long as you match the keys as per below:
Keep in mind that the .config file is XML based, so using & and other XML syntax language, you need to escape them correctly so that the XML parsing is not broken. So an iPXE && would in the config file be && etc.
If you want a line break, you can do this two ways;
Create an actual line break in the .config file
Don't use the \r\n line feed character inline. Its important that there is no \r\n characters in the script piece as the .Net parser will double escape this which break. Instead use the following syntax:
Its certainly possible to boot against a custom boot image, you just have to issue the right commands, and make sure you have the right files available.
Please see the following link to the iPXE web site for some inspiration: https://ipxe.org/howto/winpe
The syntax would be something like this in the .config section:
One great feature is to use the 2PXE menu items to integrate with the iPXE Anywhere Web Service. Please reach out to us if you have custom scripting scenarios you would like to discuss. You can use this issue to automate a "ticket" etc for machine refusing to boot, or reset PXE flags etc. There is really no end to the possibilities.
For a typical EFI boot, without the optional boot fonts, a total of 314KB of data is transferred per booting device. A 99,9% reduction from the standard TFTP protocol. All data sizes in Kilobytes. Note that the file version sizes are averages as some builds might include debug information and/or troubleshooting tools like nslookup and ping etc.
The total transfer of data is then typically the iPXE boot loader, then wimboot (hashed or not) and the boot.bcd file + some iPXE scripts to hold it all together. Then we transfer the hash of the WinPE image which then does the TFTP download using TFTP.
The following speeds have been noted in our labs downloading over a poor link, with BranchCache support 5 clients serving the WinPE image and on Gigabit network without BranchCache. The test speeds are with EFI capable devices and for downloading a 300MB WinPE image only.
A typical boot process using iPXE as the boot loader looks like the following:
Client starts,
Initiate the on board PXE ROM
PXE ROM requests an DHCP with HW capabilities in DHCP request
Typically Option 60 and Option 97 are used for architecture management
DHCP Servers (Proxy DHCP or/and DHCP) responds with right filename depending on HW capabilities in the requesting DHCP package
PXE ROM merges DHCP with possible proxy DHCP response(s) according to the PXE standard, and developers interpretation of that standard.
PXE ROM initiates the TFTP transfer of the boot file specified in merged DHCP offer (iPXE)
Note: DHCP is not actually booting from DHCP Option #66 in DHCP, in the case of a Microsoft DHCP server it translates the IP address in DHCP Option #66 to an IP address in the SIADDR field of DHCP. If you are using a non-Microsoft DHCP server you need to ensure it sends the SIADDR field of the 2PXE server.
TFTP of the boot loader finish
PXE ROM loads iPXE
iPXE initializes and does a whole lot of magic before launching the embedded script.
Embedded script checks that all seems to be in order and then processes the logic.
iPXE contacts the 2PXE server, this is done by using DHCP option #175 which is the full URL to the 2pxe server like: https://rig10c20.2pstest1.local:8050/
iPXE sends up heaps of info about the client to the 2PXE server over https
2PXE process the data and depending on the configuration settings it executes a PowerShell script or talks to the Configuration Manager Database for boot actions.
An iPXE boot script is sent down to the client for execution
iPXE executes the script and transfers the corresponding files listed in the boot script, typically booting a WinPE image.
Client downloads required files using HTTP with BranchCache support from the source:
Certificates, in order for WinPE to trust the 2PXE server
iPXEWinPEClient.exe, which sets up the right certificates and environment
Wimboot as the kernel to load the WinPE image
Boot.sdi as the NTFS virtual drive is included in the boot.wim image
Optional boot fonts are used from the boot.wim image
bcd file is created dynamically by the 2PXE service
WinPE boot.wim file, typically from the Distribution Point
A new WinPEShl.ini which replaces the original one, executes the iPXEWinPEClient.exe as the first step
The WimBoot kernel boots the downloaded WinPE image using the bcd data
WinPE Client boots WinPE and executes the iPXEWinPEClient.exe which starts networking and talks to the iPXE Anywhere Web Service to report status, and then hand back to start any custom process or the Configuration Manager task sequence engine.
File Name | Size | Hash size | Purpose |
snponly.efi | 150 | N/A | EFI iPXE bootloader, using UNDI, can’t be use BranchCache as its the start of the process |
undionly.kpxe | 75 | N/A | BIOS iPXE bootloader, using UNDI, can’t be use BranchCache as its the start of the process |
WimBoot | 35KB | 1KB | WinPE boot loader |
Boot.bcd | 12KB | N/A | Typically about +8KB per added |
Boot Scripts | 1-2KB | N/A | Auto generated |
Variable.dat | 22KB | N/A | Transferred using TFTP from Configuration Manager binaries in WinPE |
Windows PE | 300-500MB | 150-300KB | Size depends on drivers, optional components etc. |
Transfer | Kilo Bytes | Comment |
Total BIOS WAN transfer with BranchCache | ~275KB |
Total EFI WAN transfer with BranchCache | ~350KB |
Reduction in percentage of WAN traffic | -99.9% | Yeah, it’s that awesome! |
Bandwidth Up/Down/%Packet Loss | Speed (mm:ss) | Reduction from TFTP |
56/33.6 Kb 2% (Modem) | 02:00 | Are you kidding me? |
128/512 Kb 2% (ISDN/DSL Type) | 00:30 | Keep dreamin baby! |
1.544Mb/s (Typical T1) | 00:10 | Still aint happening! |
10Mb/s 1% Loss | 00:07 | On a sunny day? Right! |
100Mb/s 0,5% Loss | 00:07 | About 10 mins |
1Gb/s 0% Loss with BranchCache | 00:06 | Down 1-5 mins |
1Gb/s 0% Loss without BranchCache | 00:02 | Down 1-5 mins |