• Recent
    • Unsolved
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    Post-deployment Driver Installation using PowerShell scripts.

    Scheduled Pinned Locked Moved
    Tutorials
    2
    2
    11.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • AvaryanA
      Avaryan
      last edited by

      Hello,

      I just wanted to share how I’ve been handling driver installation to have 1 image work for over 20 different models. I’ve done this for both Windows 7 and Windows 10 with (mostly) great results.

      I’d argue that the most important step is to make sure your image contains all of the NIC drivers for all the models that you need to support. Drivers are going to be hosted on a network share. No NIC drivers means no Internet.

      Go ahead and download all of the NIC drivers for all of your models or find driver packs online. Once downloaded extract the files to a common folder. In the root of the folder create a PowerShell script with the following line. Run the script. (You may need to adjust your Execution Policy to run scripts. Google it.)

      Get-ChildItem -Path $PSScriptRoot -Recurse | Where-Object -Property Extension -EQ ".inf" | ForEach { PnPUtil.exe -a $PSItem.FullName } 
      

      This will do a recursive search for all files that have the .inf extension and use pnputil to add them to Windows driver store. During sysprep Windows will detect your hardware and pull the correct driver from the driver store.

      Besides the NIC drivers, there are only 3 files that I add to the image. My unattend.xml, SetupComplete.cmd, and SetupComplete.ps1. The rest are pulled from a network share.

      I assume you already have a working answer file, I’m not going to go into that or how to use sysprep.

      SetupComplete.cmd - Located in C:\Windows\Setup\Scripts\ - You’ll need to create the Scripts folder.

      @ECHO OFF
      
      ECHO Initializing Driver Installation Script
      START /wait PowerShell.exe -Command "& '%~dpn0.ps1'"
      
      ECHO Removing configuration files.
      CD %dp0
      DEL SetupComplete.ps1
      
      CD %windir%\System32\Sysprep
      DEL unattend.xml
      

      This will launch a PowerShell script with the same name as the SetupComplete.cmd file, stored in the same location. SetupComplete.ps1.
      After SetupComplete.ps1 is finished running it will get deleted. The unattend.xml file also gets deleted.

      SetupComplete.ps1 - Located in C:\Windows\Setup\Scripts\

      # Credentials used to access network drive.
      $Username = "Domain\Username"
      $Password = "Password" | ConvertTo-SecureString -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Password
      $RootPath = "$env:HOMEDRIVE\Drivers\"
      
      # Function to determine if 10.10.0.1 is reachable, used to verify
      # that NIC drivers are working. Waits up to 30 seconds.
      Function Wait-ForConnection {
          $wait = $true
          $count = 30
          Write-Host "Establishing network connection." -NoNewline
          while($wait) {
              $connection = Test-Connection 10.10.0.1 -ErrorAction SilentlyContinue
              if ($connection) {
                  Write-Host
                  Write-Host "Connection established!" -ForegroundColor Green
                  $wait = $false
              } else {
                  Write-Host " ." -NoNewline
                  $count = ($count -1)
                  Start-Sleep -Seconds 1
              }
              if ($count -le 0) {
                  $wait = $false
                  Write-Host "Unable to establish a network connection." -ForegroundColor Red
              }
          }
      }
      
      Wait-ForConnection
      Write-Host
      Write-Host "Mounting network drive."
      New-PSDrive -Name "Deploy" -PSProvider FileSystem -Root \\ShareName\Windows10 -Credential $Credential | Out-Null
      $Deploy = Test-Path -Path Deploy:\ -ErrorAction SilentlyContinue
      if ($Deploy) {
          Write-Host "Successfully mounted network drive." -ForegroundColor Green
          Write-Host
          if (!(Test-Path -Path $RootPath)) {
              New-Item -Path $RootPath -ItemType Directory | Out-Null
          }
          $Controller = "Deploy:\Controller.ps1"
          Copy-Item -Path $Controller -Destination "$env:HOMEDRIVE\Drivers\Controller.ps1" -Force
          $Controller = "$env:HOMEDRIVE\Drivers\Controller.ps1"
          Write-Host "Running script " -NoNewline 
          Write-Host "Controller.ps1 " -NoNewline -ForegroundColor Yellow
          Invoke-Expression -Command $Controller
      
          # Do other stuff, etc...
      
          Write-Host
          Write-Host "Unmounting network drive."
          Remove-PSDrive -Name "Deploy"
      } else { 
          Write-Host "Failed to mount network drive." -ForegroundColor Red
      }
      
      Start-Sleep -Seconds 5
      
      Restart-Computer
      

      First off, this will check to see if you can reach 10.10.0.1 (Change this to something relevant to you).
      If you can reach it then your NIC is probably working.
      Second, it will mount a network drive using supplied credentials. The account only needs Read access to the share and it’s contents.
      Third, it will copy another PowerShell script that I’ve titled Controller from the network share to a local directory. It’ll then run that script.
      Last, after Controller.ps1 has finished doing it’s thing we unmount the network drive and restart the computer.

      Controller.ps1 - Stored in the root of the network share you mounted in the last step.
      Note: This is a shortened version. I removed somethings for the purpose of this guide.

      $Model = (Get-WmiObject -Class Win32_ComputerSystem).Model
      Write-Host "Model identified as: " -NoNewline -ForegroundColor DarkYellow
      Write-Host $Model -ForegroundColor Yellow
      
      Write-Host
      
      $file = ""
      switch ($Model) {
          "OptiPlex 7040" { $file = "dell7040.ps1"; break; }
          "Precision 3510" { $file = "dell3510.ps1"; break; }
          "Precision T1700" { $file = "dell1700.ps1"; break; }
          "Precision Tower 7810" { $file = "dell7810.ps1"; break; }
          "HP Compaq Pro 6300 SFF" { $file = "hp6300.ps1"; break; }
          "VirtualBox" { $file = "virtualbox.ps1"; break; }
          default { 
              # There were multiple numbers for these models.
              If ($model -like '*6710b*') { $file = "hp6710.ps1"; }
              ElseIf ($model -like '*6730b*') { $file = "hp6730.ps1"; }
          }
      
      }
      
      $filePath = $RootPath + "Model.ps1"
      Copy-Item -Path "Deploy:\ModelScripts\$file" -Destination $filePath -Force
      Invoke-Expression -Command $filePath
      
      if ((Get-WmiObject -Class Win32_ComputerSystem).Manufacturer -match "Dell") {
          # May do some Dell BIOS settings here.
      }
      
      Write-Host
      Write-Host "Downloading FOG Client from FOGServer." -ForegroundColor Yellow
      $url = "http://<FOGSERVER>/fog/client/download.php?newclient"
      $outfile = "$RootPath + FOGService.msi"
      (New-Object System.Net.WebClient).DownloadFile($url, $outfile)
      
      Write-Host "Installing FOG Client." -ForegroundColor Cyan
      $ArgumentList = "/i $outfile /quiet USETRAY=""0"" WEBADDRESS=""<FOGSERVER>"" WEBROOT=""/fog"" /norestart"
      Start-Process -FilePath MSIEXEC.exe -ArgumentList $ArgumentList -Wait
      
      Write-Host "Creating a scheduled task to start the FOGClient after reboot."
      $TaskPath = "$env:windir\Setup\StartFOG.ps1 "
      Copy-Item -Path "Deploy:\StartFOG.ps1" -Destination $TaskPath
      $Action = New-ScheduledTaskAction -Execute PowerShell.exe -Argument "-Command ""& $TaskPath """
      $Trigger = New-ScheduledTaskTrigger -AtStartup
      Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "StartFOG" -User "NT AUTHORITY\SYSTEM" -RunLevel Highest -Force
      
      
      Write-Host "Deleting downloaded driver files."
      Remove-Item -Path $RootPath -Recurse -Force
      

      Here we use a quick WMI query to get the model number of the PC and use a switch to pick the model specific driver installation script. You’ll want to run the query on each machine beforehand to find out exactly how it’s stored.

      The beauty of this is that it’s flexible. You can easily add support for new models as long as the NIC drivers are on the image.

      hp6300.ps1 - Located in Deploy:\ModelScripts\ - You’ll make similiar script for each model. This is a very simple one.

      Write-Host "$Model Driver Installation" -ForegroundColor DarkGreen
      
      $chipset = $RootPath + "chipset.exe"
      $audio = $RootPath + "0008-64bit_Win7_Win8_Win81_Win10_R281\Setup.exe"
      
      Write-Host "Downloading Intel Chipset Drivers."
      Copy-Item -Path "Deploy:\Drivers\chipset\Intel\SetupChipset.exe" -Destination $chipset -Force
      Write-Host "Downloading Realtek HD Audio Drivers."
      Copy-Item -Path "Deploy:\Drivers\audio\Realtek\0008-64bit_Win7_Win8_Win81_Win10_R281\" -Destination $RootPath -Recurse -Force
      
      Write-Host
      Write-Host "Installing Intel Chipset Support Drivers."
      Start-Process -FilePath $chipset -ArgumentList "/s /norestart" -Wait
      Write-Host "Installing Realtek HD Audio Driver."
      Start-Process -FilePath $audio -ArgumentList "/s" -Wait
      
      Start-Sleep 5
      

      Doesn’t really get much simplier than this one. Most drivers Windows 10 already picked up. The process is basically the same for every driver, as long as they are properly signed.

      This should be enough information to get you started, if you want to do it this way. I like doing it this way because it gives me a high level of control over everything. I can specify exactly what version gets installed onto each model. You could even query the serial number of the PC and install device specify software, if you really wanted to get down to that level of detail (FOG snapins would obviously be easier though)

      Wayne WorkmanW 1 Reply Last reply Reply Quote 4
      • Wayne WorkmanW
        Wayne Workman @Avaryan
        last edited by

        @Avaryan Awesome tutorial, thank you for giving back.

        Please help us build the FOG community with everyone involved. It's not just about coding - way more we need people to test things, update documentation and most importantly work on uniting the community of people enjoying and working on FOG!
        Daily Clean Installation Results:
        https://fogtesting.fogproject.us/
        FOG Reporting:
        https://fog-external-reporting-results.fogproject.us/

        1 Reply Last reply Reply Quote 0
        • 1 / 1
        • First post
          Last post

        156

        Online

        12.0k

        Users

        17.3k

        Topics

        155.2k

        Posts
        Copyright © 2012-2024 FOG Project