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

    Using FOG Postinstall scripts for Windows Driver injection 2017 ed.

    Scheduled Pinned Locked Moved
    Tutorials
    1
    4
    12.2k
    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.
    • george1421G
      george1421 Moderator
      last edited by JJ Fullmer

      This thread is going to be a no nonsense tutorial rehashing other posts if yesteryear.

      In this tutorial we will create 2 new FOG postinstall scripts and update the master fog postinstall script to call our new scripts.

      fog.custominstall

      1. Create the following file named fog.custominstall in the following path on the FOG server /images/postdownloadscripts.
      2. Copy the content into that newly created file
      #!/bin/bash
      . /usr/share/fog/lib/funcs.sh
      [[ -z $postdownpath ]] && postdownpath="/images/postdownloadscripts/"
      case $osid in
          5|6|7|9)
              clear
              [[ ! -d /ntfs ]] && mkdir -p /ntfs
              getHardDisk
              if [[ -z $hd ]]; then
                  handleError "Could not find hdd to use"
              fi
              getPartitions $hd
              for part in $parts; do
                  umount /ntfs >/dev/null 2>&1
                  fsTypeSetting "$part"
                  case $fstype in
                      ntfs)
                          dots "Testing partition $part"
                          ntfs-3g -o force,rw $part /ntfs
                          ntfsstatus="$?"
                          if [[ ! $ntfsstatus -eq 0 ]]; then
                              echo "Skipped"
                              continue
                          fi
                          if [[ ! -d /ntfs/windows && ! -d /ntfs/Windows && ! -d /ntfs/WINDOWS ]]; then
                              echo "Not found"
                              umount /ntfs >/dev/null 2>&1
                              continue
                          fi
                          echo "Success"
                          break
                          ;;
                      *)
                          echo " * Partition $part not NTFS filesystem"
                          ;;
                  esac
              done
              if [[ ! $ntfsstatus -eq 0 ]]; then
                  echo "Failed"
                  debugPause
                  handleError "Failed to mount $part ($0)\n    Args: $*"
              fi
              echo "Done"
              debugPause
              . ${postdownpath}fog.copydrivers
              # . ${postdownpath}fog.updateunattend
              umount /ntfs
              ;;
          *)
              echo "Non-Windows Deployment"
              debugPause
              return
              ;;
      esac
      
      
      1. Save and exit your text editor.
      2. Make the script executable with chmod 755 /images/postdownloadscripts/fog.custominstall

      fog.copydrivers

      1. Create the following file named fog.copydrivers in the following path on the FOG server /images/postdownloadscripts.
      2. Copy the content into that newly created file
      #!/bin/bash
      ceol=`tput el`;
      manu=`dmidecode -s system-manufacturer`;
      dots "Identifying hardware"
      case $manu in
          [Ll][Ee][Nn][Oo][Vv][Oo])
              machine=$(dmidecode -s system-version)
              ;;
          *[Dd][Ee][Ll][Ll]*)
              machine=$(dmidecode -s system-product-name)
              ;;
          *I[Nn][Tt][Ee][Ll]*)
              # For the Intel NUC and intel mobo pick up the system type from the
              # baseboard product name
              machine=$(dmidecode -s baseboard-product-name)
              ;;
          *)
              # Technically, we can remove the Dell entry above as it is the same as this [default]
              machine=$(dmidecode -s system-product-name) 
              ;;
      esac
      
      # if the machine isn't identified then no need to continue with this script, just return to caller
      if [[ -z $machine ]]; then 
          echo "Unable to identify the hardware for manufacturer ${manu}";
          debugPause;
          return;
      fi 
      echo "${machine} Identified";
      
      # Removes Spaces in machine name, works better with path definitions
      # machine="${machine%"${machine##*[![:space:]]}"}";
      
      # 14-Sep-23 Jeffrey Boulais posted that the above code did not work for his install. He
      #  supplied this code as an alternative. If you run in to a problem using my code
      #  comment out my code and see if his code works better for your installation. The 
      #  only right way is the one that works. Thank you Jeff for your input. 
      # machine="$(echo -e “${machine}” | tr -d ‘[:space:]’)"
      # 03-Jan-24 marsface posted that he could not get either of the two above machine clean up commands to work correctly so he provided this one below which worked for him.
      machine="${machine//[[:space:]]/}"
      
      dots "Verifying we've found the OS disk"
      if [[ ! -d /ntfs/windows && ! -d /ntfs/Windows && ! -d /ntfs/WINDOWS ]]; then
          echo "! OS root Not found !";
          debugPause
          return;
      fi
      echo "Found";
              
      dots "Verifying target Arch"
      system64="/ntfs/Windows/SysWOW64/"
      [[ ! -d $system64 ]] && arch="x86" || arch="x64"
      echo "${arch} found";
      
      debugPause
      
      # set osn path names based on the osid set in the FOG WebGui
      case $osid in
          5) osn="win7" ;;
          6) osn="win8" ;;
          7) osn="win8.1" ;;
          9) osn="win10" ;;
      esac
      
      dots "Preparing Drivers"
      clientdriverpath="/ntfs/Drivers"
      remotedriverpath="/images/drivers/$machine/$osn/$arch"
      
      debugPause
      
      if [[ ! -d "${remotedriverpath}" ]]; then
          echo "failed";
          echo " ! Driver package not found for ${machine}/$osn/$arch ! ";
          debugPause;
          return;
      fi
      echo "Ready";
      
      debugPause
      
      [[ ! -d $clientdriverpath ]] && mkdir -p "$clientdriverpath" >/dev/null 2>&1
      echo -n "In Progress"
      
      rsync -aqz "$remotedriverpath" "$clientdriverpath" >/dev/null 2>&1
      
      [[ ! $? -eq 0 ]] && handleError "Failed to download driver information for [$machine/$osn/$arch]"
      
      debugPause
      
      # the following code is only valid for Windows 7 operating systems since Windows 8 and beyond
      # relies on the unattend.xml section to locate OEM drivers. If you are no longer deploying Win7
      # you may exclude this section. 
      
      regfile="/ntfs/Windows/System32/config/SOFTWARE"
      key="\Microsoft\Windows\CurrentVersion\DevicePath"
      devpath="%SystemRoot%\DRV;%SystemRoot%\inf;";
      reged -e "$regfile" &>/dev/null <<EOFREG
      ed $key
      $devpath
      q
      y
      EOFREG
      
      1. Save and exit your text editor.
      2. Make the script executable with chmod 755 /images/postdownloadscripts/fog.copydrivers

      fog.updateunattend

      This section is optional. You do not need to use this script if you do not need to patch or amend your unattend.xml file. If you want dynamic updates to your unattend file then you can use this section of code. Remember to uncomment the call to this script in the fog.custominstall script.

      1. Create the following file named fog.updateunattend in the following path on the FOG server /images/postdownloadscripts.
      2. Copy the content into that newly created file:
      #!/bin/bash
      hostadpwd="ADPASSWDHERRE"; #only downside to this method- this is the plain ad password
      unattends=$(find /ntfs/ -iname "unattend.xml")
      for unattend in $unattends; do
          [[ ! -f $unattend ]] && return
          dots "Preparing Sysprep File"
          #rm -f /ntfs/Windows/System32/sysprep/unattend.xml >/dev/null 2>&1
          #if [[ ! $? -eq 0 ]]; then
              #echo "Failed"
              #debugPause
              #handleError "Failed to remove original unattend file"
          #fi
          echo "Done"
          debugPause
          dots "Writing Computer Name to $unattend"
          sed -i "/ComputerName/s/*/$hostname/g" $unattend >/dev/null 2>&1
          if [[ ! $? -eq 0 ]]; then
              echo "Failed"
              debugPause
              handleError "Failed to update originating unattend file"
          fi
          echo "Done"
          echo "ComputerName set to $hostname in $unattend"
          debugPause
          [[ -z $addomain ]] && continue
          dots "Set PC to join the domain"
          sed -i "/<JoinWorkgroup>/d" $unattend >/dev/null 2>&1
          if [[ ! $? -eq 0 ]]; then
              echo "Failed"
              debugPause
              handleError "Failed to remove the Workgroup setter"
          fi
          sed -i \
              -e "s|<Password></Password>|<Password>${hostadpwd}</Password>|g" \
              -e "s|<Username></Username>|<Username>${addomain}\\\\${aduser}</Username>|g" \
              -e "s|<MachineObjectOU></MachineObjectOU>|<MachineObjectOU>${adou}</MachineObjectOU>|g" \
              -e "s|<JoinDomain></JoinDomain>|<JoinDomain>${addomain}</JoinDomain>|g" $unattend >/dev/null 2>&1
          if [[ ! $? -eq 0 ]]; then
              echo "Failed"
              debugPause
              handleError "Failed to update user, pass, ou, and domain setter"
          fi
          echo "Done"
          debugPause
      done
      
      1. Save and exit your text editor.
      2. Make the script executable with chmod 755 /images/postdownloadscripts/fog.updateunattend

      fog.postdownload

      The last bit of magic we need to do is update the FOG supplied script called fog.postdownload to call our custom script fog.custominstall

      1. Insert at the bottom of the fog.postdownload script this line.
      . ${postdownpath}/fog.custominstall
      
      1. Save and exit your text editor.

      Driver repository structure

      For this process to work you must setup your driver library on the fog server in a certain fashion.

      On your fog server create the drivers directory under the images directory with:
      md /images/drivers
      Below the /images/drivers directory you will create a directory per machine name (that exactly matches what comes from smbios using this command for Dell computers dmidecode -s system-product-name
      Hint: You can also find the system product name by reviewing the inventoried system in the FOG WebGui.

      The structure should be built to match the variables used in the fog.drivers script.

      /images
      ├─/drivers
        ├─$machine
            ├─$osn
              └─$arch
      

      or translated into real values (note that the space has been removed for “Optiplex 7040” to this Optiplex7040. There is a clean up line above that removes spaces in the product name. While linux supports spaces in path names (like Windows) its bad practice to use them because some utilities will see the space as a parameter delimiter.

      /images
      ├─/drivers
        ├─Optiplex7040
            ├─win7
              └─x86
              └─x64
            ├─win10
              └─x64
        ├─Optiplex7050
      ...
      

      Unattend.xml

      For WIN10 you must update the unattend.xml file to include this section. This is an example for the amd64 arch.

          <settings pass="offlineServicing">
              <component name="Microsoft-Windows-PnpCustomizationsNonWinPE" 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">
                  <DriverPaths>
                      <PathAndCredentials wcm:action="add" wcm:keyValue="1">
                          <Path>C:\Drivers</Path>
                      </PathAndCredentials>
                  </DriverPaths>
              </component>
          </settings>
      

      If you want to read more into the how and why of this tutorial you can review this thread and its links: https://forums.fogproject.org/topic/8889/fog-post-install-script-for-win-driver-injection

      EDIT: Changed arch test to the syswow64 path instead of the regedit.exe path within as the latest Windows 11 changed things so that the file is a symlink that isn’t recognized as a symlink or file in linux. Thanks to @lukebarone

      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!

      1 Reply Last reply Reply Quote 1
      • george1421G
        george1421 Moderator
        last edited by

        (place holder)

        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!

        1 Reply Last reply Reply Quote 0
        • george1421G
          george1421 Moderator
          last edited by

          (place holder)

          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!

          1 Reply Last reply Reply Quote 0
          • george1421G
            george1421 Moderator
            last edited by george1421

            Update: With the later releases of Win10 post 1703, the offline servicing section doesn’t seem to load the drivers. As a fix, add the following lines to your setupcomplete.cmd batch file to load the drivers at the end of the OSD process.

            pnputil.exe /add-driver "C:\Drivers\*.inf" /subdirs /install
            pnputil.exe /add-driver "C:\Drivers\*.inf" /subdirs /install
            pnputil.exe /add-driver "C:\Drivers\*.inf" /subdirs /install
            

            Running pnputil 2 times seems to be the sweet spot to capture all of the hardware devices, because some hardware is hidden behind other hardware drivers (such as USB3 and PCI hardware)

            Update: if you want to use the pnputil.exe command with versions of windows before Win10 you will need to use this command instead, since the older versions of pnputil do not support the /subdir switch.

            forfiles /p "C:\Drivers" /s /m *.inf /c “cmd /c pnputil -a @Path”
            forfiles /p "C:\Drivers" /s /m *.inf /c “cmd /c pnputil -a @Path”
            forfiles /p "C:\Drivers" /s /m *.inf /c “cmd /c pnputil -a @Path”
            

            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!

            1 Reply Last reply Reply Quote 0
            • george1421G george1421 referenced this topic on
            • george1421G george1421 referenced this topic on
            • george1421G george1421 referenced this topic on
            • Y youzersef referenced this topic on
            • I IT-MAN referenced this topic on
            • H HorizonG referenced this topic on
            • 1 / 1
            • First post
              Last post

            262

            Online

            12.0k

            Users

            17.3k

            Topics

            155.2k

            Posts
            Copyright © 2012-2024 FOG Project