FOG Post install script for Win Driver injection


  • Moderator

    Introduction

    First I have to say this article contains the results of many brilliant people and is not my content. I’m only assembling this information into a consistent document instead of spread around buried in posts and responses. My intent is to not dig into the details behind the scripts or how to tweak them for your needs. You can read the links below to figure out why things are being done the way they are. I wanted to create a tutorial that was as close to a cut and paste to get driver injection going in your environment. Now I will primarily focus on Dell hardware for the main reason that Dell does supply driver archive files (known as .CABs) that can be downloaded and extracted quickly to create the driver structure. I’m sure that HP, Lenovo, and others have similar driver packs.

    You can download the Dell driver cabs for your hardware from here: http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment

    Reference links:
    https://forums.fogproject.org/topic/4278/utilizing-postscripts-rename-joindomain-drivers-snapins
    https://forums.fogproject.org/topic/7740/the-magical-mystical-fog-post-download-script-under-construction
    https://forums.fogproject.org/topic/7740/the-magical-mystical-fog-post-download-script
    https://forums.fogproject.org/topic/8878/fog-drivers-script-will-not-run-correctly-in-postdownloadscripts/46


  • Moderator

    @Lee-Rowlett said in FOG Post install script for Win Driver injection:

    @george1421 nice write-up - think this needs updating to be inline with hostinfo.php variables?

    Thank you for your kind words.

    Yes, looking over the code its a bit dated. There are a few things that while they work, could use a fixup because I don’t think they work as well as it should.

    Possibly include setting the host name with this snippet. So they host name can be anything and sed will just swap it out. In the one I wrote for my business it is setup for global deployments. It will identify the local subnet where its being installed and update the timezone, system mui language and keyboard settings for the local region. But the point is they all use a variant of the sed script below.

    sed -i -e "s#<ComputerName>\([^<][^<]*\)</ComputerName>#<ComputerName>$hostname</ComputerName>#gi" $unatendfile 
    

    Ref: https://forums.fogproject.org/topic/7740/the-magical-mystical-fog-post-download-script/7


  • Developer

    @george1421 said in FOG Post install script for Win Driver injection:

    fog.ad

    This script can be used to update files on the target computer. In this case we’ll use it to update the unattend.xml file with install time data like host name, connect to AD or what ever you need. I can say if you use the FOG client to do this stuff, then this script isn’t really needed. But its here to show you what’s possible.

    #!/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
        [[! -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
    

    0_1478213498187_fog.ad

    @george1421 nice write-up - think this needs updating to be inline with hostinfo.php variables?


  • Moderator

    @Tom-Elliott I think having more than one repo for community scripts is a bad idea. It’s just scripts. It’s not jumbled together. It’s well organized, every contribution has a readme. The entire idea was to put scripts into one place.


  • Senior Developer

    fog-community-scripts I think should be their own thing independent of “post download scripts”

    Maybe we could get a postdownload scripts repo in a similar fashion though?


  • Moderator

    @Joe-Schmitt are these scripts something we can add to the fog community scripts repo? I didn’t originally write them.


  • Moderator

    fog.postdownload

    This script is called by the FOS engine just after the image has been pushed to the target computer. It is up to the FOG Admin to decide what to do in this script and what other scripts to call. This script will replace the default fog.postinstall script. Don’t forget if you replace this file you must change the file mode to 755 using the following linux command chmod 755 fog.postdownload
    This script will call 3 additional scripts that will do a bit more than copying the drivers to the target system. You can include or exclude these scripts based on your need. This (fog.postinstall)) script will setup the foundation functions needed by the other scripts.

    I’ll include an attachment at the end of this post to help speed up script deployment.

    #!/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 /ntf >/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.log
            . ${postdownpath}fog.drivers
            . ${postdownpath}fog.ad
            umount /ntfs
            ;;
        *)
            echo "Non-Windows Deployment"
            debugPause
            return
            ;;
    esac
    
    

    0_1478217907134_fog.postinstall


  • Moderator

    fog.log

    This script does a bit of house keeping by removing the fog.log if it happens to exist in the reference image before image capture.

    #!/bin/bash
    #deletes fog.log for Windows 7, 8, or 8.1 or 10
    #Greg Grammon (Junkhacker)
    #
     
    #funcs.sh allows us to use the functions that are used in the rest of
    #fog i.e. "dots" and use the vars already in place i.e. "$part" and "$osid"
    . /usr/share/fog/lib/funcs.sh;
    case $osid in
        [5-7]|9)
            [[ -f /ntfs/fog.log]] && rm /ntfs/fog.log >/dev/null 2>&1 || true
            if [[ ! $? -eq 0 ]]; then
                echo "Failed"
                debugPause
                handleError "Failed to remove original fog.log file"
            fi
            ;;
        *) return ;;
    esac
    

    0_1478212047634_fog.log


  • Moderator

    fog.drivers

    This script does the heavy lifting of identifying what hardware the script is running on and then copies all of the files from the correct source directory to the destination directory on the target computer.

    #!/bin/bash
    ceol=`tput el`;
    manu=`dmidecode -s system-manufacturer`;
    case $manu in
        [Ll][Ee][Nn][Oo][Vv][Oo])
            machine=$(dmidecode -s system-version)
            ;;
        *[Dd][Ee][Ll][Ll]*)
            machine=$(dmidecode -s system-product-name) #pruduct is typo, just realized sorry :(
            ;;
        *)
            machine=$(dmidecode -s system-product-name) # Technically, we can remove the dell one as it's the "default"
            ;;
    esac
    [[ -z $machine ]] && return #assuming you want it to break if it is not lenovo or dell?
    machine="${machine%"${machine##*[![:space:]]}"}" #Removes Trailing Spaces
    
    #############################################
    # Quick hack to find out if the installed OS image is a x86 or x64
    system64="/ntfs/Windows/SysWOW64/regedit.exe" # sloppy detect if 64bit or not
    [[ ! -f $system64 ]] && arch="x86" || arch="x64"
    
    #############################################
    #this section has been updated to bring the osn names in line
    # with how the Dell CABs are defined
    case $osid in
        5) osn="win7" ;;
        6) osn="win8" ;;
        7) osn="win8.1" ;;
        9) osn="win10" ;;
    esac
    
    #############################################
    dots "Preparing Drivers"
    # below creates local folder on imaged pc
    # this can be anywhere you want just remember
    # to make sure it matches throughout! (case IS important here)
    clientdriverpath="/ntfs/Windows/DRV"
    remotedriverpath="/images/drivers/$machine/$osn/$arch"
    
    [[ ! -d $clientdriverpath ]] && mkdir -p "$clientdriverpath" >/dev/null 2>&1
    echo -n "In Progress"
    
    #there's 3 ways you could handle this,
    #driver cab file, extracted driver files or both
    #so on the server put extracted driver files to match below folder tree
    #i.e. Model Latitude E5410, Windows 7 x86 image would be:
    #/fog/Drivers/Latitude E5410/win7/x86
    
    rsync -aqz "$remotedriverpath" "$clientdriverpath" >/dev/null 2>&1
    [[ ! $? -eq 0 ]] && handleError "Failed to download driver information for [$machine/$osn/$arch]"
    
    #this next bit adds driver location on pc to devicepath in registry (so sysprep uses it to reference)
    # remember to make devicepath= match the path you've used locally
    #also do not remove %SystemRoot%\inf
    #and to add more locations just use ; in between each location
    
    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
    echo -e "\b\b\b\b\b\b\b\b\b\b\b${ceol}Done"; # this just removes "In Progress and replaces it with done :-)"
    
    

    I can tell you that this section works for Windows 7 and older (no idea on Win8 or Win8.1), but it DOES NOT WORK with Win10. Windows 10 no longer references this registry key to locate its drivers. For Win10 you must enter this information into the unattend.xml file.

    
    regfile="/ntfs/Windows/System32/config/SOFTWARE"
    key="\Microsoft\Windows\CurrentVersion\DevicePath"
    devpath="%SystemRoot%\inf;%SystemRoot%\DRV";
    reged -e "$regfile" &>/dev/null <<EOFREG
    ed $key
    $devpath
    q
    y
    EOFREG
    echo -e "\b\b\b\b\b\b\b\b\b\b\b${ceol}Done"; # this just removes "In Progress and replaces it with done :-)"
    
    

    0_1478217813029_fog.drivers

    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:\Windows\DRV</Path>
                    </PathAndCredentials>
                </DriverPaths>
            </component>
        </settings>
    

  • Moderator

    fog.ad

    This script can be used to update files on the target computer. In this case we’ll use it to update the unattend.xml file with install time data like host name, connect to AD or what ever you need. I can say if you use the FOG client to do this stuff, then this script isn’t really needed. But its here to show you what’s possible.

    #!/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
        [[ ! -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
    

    0_1478213498187_fog.ad


  • Moderator

    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

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

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

    or translated into real values

    /images
    ├─/drivers
      ├─Optiplex 7040
          ├─win10
            └─x64
    

    (my standard workflow will be added here)


Log in to reply
 

Looks like your connection to FOG Project was lost, please wait while we try to reconnect.