FOG Post install script for Win Driver injection


  • 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?



  • @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?



  • @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 /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.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
 

441
Online

5.6k
Users

12.9k
Topics

121.1k
Posts