Niklas Blog

Exploring Device Management.

Injecting custom oem drivers to Windows installation media

03 February 2025

Injecting custom oem drivers to Windows installation media

I wrote this post because I created a script that I will present you today which is really useful for me when developing new solutions in Microsoft Intune which I want to test with Autopilot. The script does something very basic but automated – injecting oem driver packages into an Windows installation media. I know with Intune we can reset the device from the cloud, that’s what I would recommend in an production environment where you dont want to re-stage devices manually. BUT for dev/test purposes this can save you some time as the Windows installation media is way faster than a reset from the cloud, at least from my experience.

The script

So as I wrote in the introduction to this post the use case of the script is to inject drivers into a fresh Windows installation media. This is necessary because some devices will not work without the oem driver – like for example a touchpad or some ethernet drivers. That`s why I created a script that does all the DISM work for you and you are only left with the following 4 simple tasks:

  • Download the driver packs from OEM`s website
  • Create a bootable usb drive with the Windows Media Creation Toolkit
  • Run the script and fill the parameters
  • Boot your device from this stick.

So lets walk though each of those steps:

  1. Download the driver packs from OEM`s website

Most vendors offer some Enterprise Management driver packs which include all drivers for a specific hardware model – that`s what we need. For DELL look here, for LENOVO here, as I usually use those vendors I had those links ready but other vendors should have that too. So pick the right device model from the list, download the package and extract it locally on your device.

  1. Create a bootable usb drive with the Windows Media Creation Toolkit

This step also is very simply and you might be familiar with it already. Download the Media Creation Tool from the official Microsoft website here and create a bootable usb drive with it. The usb drive should have at least 8GB of storage and be aware that the stick will be formatted – so save data that you need from it. Optionally you could download the iso file from the same link and copy it to the usb drive with a tool of your choice.

  1. Run the script and fill the parameters

Now that we have the driver pack and a fresh usb installation media ready – lets start with injecting the oem driver package into the windows installation media. If your interested more, the drivers will be injected in the install.wim (or when the installation media has been created with Media Creation Toolkit install.swm and install1.swm) file located in the SOURCES folder on your usb drive. The install.wim holds the Windows Installation and is copied from the installation media to its destination drive inside of the device that you are going to install Windows onto. A .swm file is a splited wim file which is necessary to be able to copy files to the installation media stick as it is formatted in FAT32 which only can handle files up to 4GB, so a swm file will be created from my script that is max 3.9GB and can be copied easily.

Copy the following script into a elevated PowerShell session or your PowerShell profile for more simpler future usage. I am going to explain it below 🙂

function InjectDriversToWIM {
    Write-Host "This function will inject OEM drivers Windows install file." -ForegroundColor Yellow

    #Set USB path and check that install file(s) exist
    $usb = Read-Host -Prompt "Please enter drive path for pre-created windows install stick (for example: D:)"
    $wim = "$usb\sources\install.wim"
    $swm = "$usb\sources\install.swm"
    $installfile
    switch ($true) {
        { Test-Path $wim } { 
            Write-Host "Installer is WIM" -ForegroundColor Green
            $installfile = "wim"
        }
        { Test-Path $swm } { 
            Write-Host "Installer is SWM" -ForegroundColor Green
            $installfile = "swm"
        }
        Default { 
            Write-Host "There is no WIM or SWM file located at $usb\sources" -ForegroundColor Red; break
        }
    }

    #Set DRIVER path
    $driver = Read-Host -Prompt "Please enter path for enterprise driver pack (for example: C:\Data\drivers\x13_drivers)"
    if (Test-Path -Path $driver) {Write-Host "Found driver directory" -ForegroundColor Green} else {Write-Host "No valid driver directory path found!" -ForegroundColor Red}

    #Create Temp path
    New-Item -Path C:\ -Name Data-ItemType Directory -Force
    New-Item -Path C:\Data -Name temp -ItemType Directory -Force
    New-Item -Path C:\Data\temp\IMAGE -Name IMAGE -ItemType Directory -Force
    New-Item -Path C:\Data\temp\IMAGE -Name Source -ItemType Directory -Force
    New-Item -Path C:\Data\temp\IMAGE -Name Mount -ItemType Directory -Force 

    #Remove all SWM files from the Sources folder on the usb drive
    Move-Item -Path $usb\Sources\*.$installfile -Destination C:\Data\temp\IMAGE\Source -Force
    if (Test-Path -Path C:\Data\temp\IMAGE\Source\boot.wim) { Move-Item -Path C:\Data\temp\IMAGE\Source\boot.wim -Destination $usb\Sources\ -Force }
    switch ($installfile) {
        wim {Move-Item -Path C:\Data\temp\IMAGE\Source\install.wim -Destination C:\Data\temp\IMAGE\Source\install_org.wim -Force}
        swm {dism /export-image /sourceimagefile:C:\Data\temp\IMAGE\Source\install.$installfile /swmfile:C:\Data\temp\IMAGE\Source\install*.$installfile /sourceindex:1 /destinationimagefile:C:\Data\temp\IMAGE\Source\install_org.wim /Compress:max /CheckIntegrity}
    }
    
    #Get wim index number by choice
    Dism.exe /Get-WimInfo /WimFile:C:\Data\temp\IMAGE\Source\install_org.wim
    $index = Read-Host -Prompt "Please enter Index number where you want to inject drivers (for example 5)"

    #Extract needed version by Index number
    Dism.exe /Export-Image /SourceImageFile:C:\Data\temp\IMAGE\Source\install_org.wim /SourceIndex:$index /DestinationImageFile:C:\Data\temp\IMAGE\Source\install.wim
    Remove-Item -Path C:\Data\temp\IMAGE\Source\install_org.wim -Force

    #Inject drivers to WIM
    Dism.exe /Mount-Wim /WimFile:C:\Data\temp\IMAGE\Source\install.wim /Index:1 /MountDir:C:\Data\temp\IMAGE\Mount
    Dism.exe /Image:C:\Data\temp\IMAGE\Mount /Add-Driver /Driver:$driver /recurse
    Dism.exe /Unmount-Wim /MountDir:C:\Data\temp\IMAGE\Mount /Commit

    #Split WIM to SWM files
    Dism /Split-Image /ImageFile:C:\Data\temp\IMAGE\Source\install.wim /SWMFile:C:\Data\temp\IMAGE\install.swm /FileSize:3900

    #Move SWM files to usb
    Move-Item -Path C:\Data\temp\IMAGE\*.swm -Destination $usb\sources -Force

    #Cleanup
    Remove-Item -Path "C:\Data\temp\IMAGE" -Recurse -Force

Lets see what the script does:

  • Run the script by typing InjectDriversToWIM in the PowerShell session.
  • First of all the script will ask for the drive letter of the usb stick that holds your windows installation media. Enter that like this D: without the quotation marks.
  • Next it will ask you for the full path to your enterprise driver pack. Enter it like this C:\drivers\lenovo_x13_drivers, again without the quotation marks.
  • Then the script will create some temp folders to handle the files at C:\Data\temp\IMAGE. They will be deleted after the script run is finished.
  • Next it will automatically move wim or swm (if it is multiple swm files it will combine them to a single wim file first as we only can inject drivers here) files from the installation media to our temp folder structure and ask you into which version (defined as numbers) of the installation media you want to inject the drivers. It is doing that because a default Windows installation media contains multiple versions of Windows like HOME, PRO or ENTERPRISE and we only want to inject it to the one that we want to use to reduce storage and building time. Then the script will extract the version that you selected, inject the drivers, split the wim file again into swm files (the number of swm files depends on the needed storage for the drivers but is usually 2-3) and move them back onto the installation media into the SOURCES folder.
  • Lastly it will cleanup the temp folders that we created onto your local disk for combining all those files.
  1. Boot your device from this stick.

Now all thats left is to eject the stick from your device, plug it into the machine that you want to install Windows to and boot from the usb drive.

But I have one more optimization here for you to make your life more easy 🙂

Have you yet heard of the autounattend.xml file? If yes – GREAT then you know what to do.

If you do not know about the autounattend.xml file let me try to explain it quickly.

The autounattend.xml file is a file that we can create and simply copy in the root directory of our installation media usb stick which then will automatically do all the steps that the Windows installer will ask normally, like disk partitioning or the Microsoft EULAs. It is a great solution to totaly automate this manual Windows deployment process so that you only need to boot from the stick and it will then completely deploy Windows by itself until you are in the Windows OOBE or Autopilot takes over.

Here is a autounattend.xml file that would do all that for you – but you might want to change Language and Locales depending on your Windows Image because the following is for a en-US Windows Image:

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="windowsPE">
        <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
            xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <SetupUILanguage>
                <UILanguage>en-us</UILanguage>
            </SetupUILanguage>
            <InputLocale>0409:00000409</InputLocale>
            <SystemLocale>en-us</SystemLocale>
            <UILanguage>en-us</UILanguage>
            <UILanguageFallback>en-us</UILanguageFallback>
            <UserLocale>en-us</UserLocale>
        </component>
        <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
            xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <DiskConfiguration>
                <Disk wcm:action="add">
                    <DiskID>0</DiskID>
                    <WillWipeDisk>true</WillWipeDisk>
                    <CreatePartitions>
                        <!-- Windows RE Tools partition -->
                        <CreatePartition wcm:action="add">
                            <Order>1</Order>
                            <Type>Primary</Type>
                            <Size>300</Size>
                        </CreatePartition>
                        <!-- System partition (ESP) -->
                        <CreatePartition wcm:action="add">
                            <Order>2</Order>
                            <Type>EFI</Type>
                            <Size>100</Size>
                        </CreatePartition>
                        <!-- Microsoft reserved partition (MSR) -->
                        <CreatePartition wcm:action="add">
                            <Order>3</Order>
                            <Type>MSR</Type>
                            <Size>128</Size>
                        </CreatePartition>
                        <!-- Windows partition -->
                        <CreatePartition wcm:action="add">
                            <Order>4</Order>
                            <Type>Primary</Type>
                            <Extend>true</Extend>
                        </CreatePartition>
                    </CreatePartitions>
                    <ModifyPartitions>
                        <!-- Windows RE Tools partition -->
                        <ModifyPartition wcm:action="add">
                            <Order>1</Order>
                            <PartitionID>1</PartitionID>
                            <Label>WINRE</Label>
                            <Format>NTFS</Format>
                            <TypeID>DE94BBA4-06D1-4D40-A16A-BFD50179D6AC</TypeID>
                        </ModifyPartition>
                        <!-- System partition (ESP) -->
                        <ModifyPartition wcm:action="add">
                            <Order>2</Order>
                            <PartitionID>2</PartitionID>
                            <Label>System</Label>
                            <Format>FAT32</Format>
                        </ModifyPartition>
                        <!-- MSR partition does not need to be modified -->
                        <ModifyPartition wcm:action="add">
                            <Order>3</Order>
                            <PartitionID>3</PartitionID>
                        </ModifyPartition>
                        <!-- Windows partition -->
                        <ModifyPartition wcm:action="add">
                            <Order>4</Order>
                            <PartitionID>4</PartitionID>
                            <Label>OS</Label>
                            <Letter>C</Letter>
                            <Format>NTFS</Format>
                        </ModifyPartition>
                    </ModifyPartitions>
                </Disk>
            </DiskConfiguration>
            <ImageInstall>
                <OSImage>
                    <InstallTo>
                        <DiskID>0</DiskID>
                        <PartitionID>4</PartitionID>
                    </InstallTo>
                    <InstallToAvailablePartition>false</InstallToAvailablePartition>
                </OSImage>
            </ImageInstall>
            <UserData>
                <ProductKey>
                    <Key></Key>
                    <WillShowUI>Never</WillShowUI>
                </ProductKey>
                <AcceptEula>true</AcceptEula>
                <FullName></FullName>
                <Organization></Organization>
            </UserData>
        </component>
    </settings>
</unattend>

Conclusion

So for me this helps me a lot when developing new things in Intune where I want to test it with Autopilot to ensure that everything works fine and I always use it when I create a new Windows Installation stick. Yes there are tools that can do the same but I like to explore things by myself and so I 100% know what’s happening and how it is done. That is also one thing that I highly recommend you to not simply trust any tool or script that you find online – check it out before you use it to ensure security and check what it does …. or build something similar by yourself to expand your knowledge 🙂

If you have questions to the script or more ideas feel free to write me a DM on LinkedIn – I would be happy to hear your feedback and or ideas to optimize it even more.