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

FOG Post Install, Sysprep, unattend file

Scheduled Pinned Locked Moved
General
2
2
582
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.
  • H
    HorizonG
    last edited by HorizonG Jul 29, 2024, 12:13 PM Jul 29, 2024, 6:08 PM

    Hello everyone,

    [I am new to the forum, I thank in advance those who will be interested in the following post]

    I have a question about the post-installation method, specifically about the unattend.xml file.

    1. Step 1 [OK] : I created an image, which we can call “Golden Image” with an unattend.xml file that I then captured via FOG.

    => My unattend file does not contain the command to run a post install script like Powershell or SetupComplete.cmd

    1. Step 2 [OK] : I then used these 2 guidlines to copy the drivers according to the computer model:
    https://forums.fogproject.org/topic/7740/the-magical-mystical-fog-post-download-script
    
    https://forums.fogproject.org/topic/11126/using-fog-postinstall-scripts-for-windows-driver-injection-2017-ed
    

    => This method allows me to :

    • Update the unattend file (unattend.xml) here: C:\Windows\System32\Sysprep
    • Drop the drivers folder here: C:\Drivers\
    • Install powershell scripts here: C:\FOG
      Current folder structure :
      [Parent Folder] C:\FOG
      [Subfolder] C:\FOG\Master_Script [Script .PS1 calling each .PS1]
      [Subfolder] C:\FOG\Scripts [ Mutiple Scripts .PS1]
      [Subfolder] C:\FOG\Logs [Logs files]

    These scripts contains code to install : Drivers, FOG client,specific configurations

    1. I’d like to know if the unattend file I’m updating via the post-installation method is updated before the OS starting the image that has already been “syprep”. So that I can update it dynamically.
      This would also allow me to run my script located at this level: C:\FOG\Master_Script … because I didn’t indicate this in the nitial unattend.xml file.

    2. is it possible to rename automatically (with script?) the machine after post-sysprep initialization, reusing the computer name from Full Inventory ?

    Thank you for your replies 🙂

    J 1 Reply Last reply Jul 30, 2024, 6:13 PM Reply Quote 0
    • J
      JJ Fullmer Testers @HorizonG
      last edited by Jul 30, 2024, 6:13 PM

      @HorizonG Short answer to both, yes.

      There’s a bit of work to do to make it work but you can.
      The first thing to know to help in full is what phase of sysprep you captured at?

      If you captured right after the generalize phase (best practice) and specialize is what starts you can indeed update the unattend file dynamically with computer name, domain, ou, etc.
      You can only effect the phases that haven’t happened yet. So you can add things to the specialize and oobe phases. Specialize does things before windows fully loads, it’s essentially a winpe environment, and oobe is the full windows where you can have a setupcomplete run. I have it kick off a series of powershell scripts (essentially).

      Windows also moves the unattend file around across the phases, when I update the unattend file in a post install script I just update it in all these places. i.e. in the context of fog having mounted 😄 at /ntfs
      "/ntfs/Windows/System32/Sysprep/Unattend.xml" "/ntfs/Windows/Panther/unattend.xml" "/ntfs/Windows/Panther/Unattend.xml"

      I also have one at C:\Unattend.xml you’ll see in my example below.

      Also note that it’s case sensitive, which is why I have 2 in the same spot as I’ve seen it both ways.

      I don’t have time to dig into too much detail right now but here’s an example of injecting some stuff into the unattend files. I also included my bit where I can just patch in an updated Unattend.xml file, though this wouldn’t scale for every host I just use it for another option before recapturing a whole image to test an unattend change.

      One very important bit for this to work as it does in the example is I have this bit in my specialize phase, which I replace with computername and AD info, replace NETBIOSDOMAINNAME with your short domain name that you use for this format logon string domain\username

      <component name="Microsoft-Windows-UnattendedJoin" 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">
                  <Identification>
                      <JoinWorkgroup>NETBIOSDOMAINNAME</JoinWorkgroup>
                  </Identification>
              </component>
      

      I also have <ComputerName></ComputerName> in the specialize phase under my "Microsoft-Windows-Shell-Setup" component i.e. the end of this has that. I took out my company info from this example, you don’t need all of this the same, just a contextual example. The product key is the GVLK for windows 10/11 publicly available.

      <component name="Microsoft-Windows-Shell-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">
                  <DesktopOptimization>
                      <GoToDesktopOnSignIn>true</GoToDesktopOnSignIn>
                      <ShowWindowsStoreAppsOnTaskbar>true</ShowWindowsStoreAppsOnTaskbar>
                  </DesktopOptimization>
                  <BluetoothTaskbarIconEnabled>true</BluetoothTaskbarIconEnabled>
                  <ConvertibleSlateModePromptPreference>1</ConvertibleSlateModePromptPreference>
                  <CopyProfile>false</CopyProfile>
                  <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet>
                  <EnableStartMenu>true</EnableStartMenu>
                  <OEMName>Company Name</OEMName>
                  <RegisteredOrganization>Company Name</RegisteredOrganization>
                  <ShowPowerButtonOnStartScreen>true</ShowPowerButtonOnStartScreen>
                  <RegisteredOwner>Company Name</RegisteredOwner>
                  <SignInMode>2</SignInMode>
                  <TimeZone>Mountain Standard Time</TimeZone>
                  <OEMInformation>
                      <SupportURL>http://helpme.company.tld</SupportURL>
                      <Logo>C:\img\company-logo.bmp</Logo>
                      <SupportPhone>555-5555</SupportPhone>
                      <SupportProvider>String that shows up in sys info</SupportProvider>
                      <Manufacturer>string that shows up in sys info</Manufacturer>
                  </OEMInformation>
                  <Themes>
                      <BrandIcon>C:\img\company-logo.png</BrandIcon>
                      <ThemeName>Company Theme</ThemeName>
                      <DesktopBackground>%WINDIR%\web\Wallpaper\some-injected-background.jpg</DesktopBackground>
                      <WindowColor>Automatic</WindowColor>
                      <DefaultThemesOff>false</DefaultThemesOff>
                  </Themes>
                  <DoNotCleanTaskBar>true</DoNotCleanTaskBar>
                  <AutoLogon>
                      <Password>
                          <Value>supersecretencryptedpassword</Value>
                          <PlainText>false</PlainText>
                      </Password>
                      <Enabled>true</Enabled>
                      <Username>Administrator</Username>
                      <LogonCount>99</LogonCount>
                  </AutoLogon>
                  <ProductKey>NPPR9-FWDCX-D2C8J-H872K-2YT43</ProductKey>
                  <ComputerName></ComputerName>
              </component>
      

      The fog post download examples. I also do something with the device form setting but I tried to just take that out for this example. Device form is mildly helpful for configuring the tablet vs desktop user experience if you have a mix of such devices.

      unattends=("/ntfs/Unattend.xml" "/ntfs/Windows/System32/Sysprep/Unattend.xml" "/ntfs/Windows/Panther/unattend.xml" "/ntfs/Windows/Panther/Unattend.xml")
      for unattend in ${unattends[@]}; do
          [[ ! -f $unattend ]] && break
          #as a failsafe, reload the funcs.sh from fog
          . /usr/share/fog/lib/funcs.sh
          dots "Preparing Sysprep File at $unattend"
          #update unattend files if an Unattend.xml file is present to replace current file
          if [[ -f "/images/drivers/Unattend.xml" ]]; then
              echo -en "\n\nUnattend.xml patch file detected, updating the Unattend.xml file baseline\n\n";
              echo -en "\n\nUnattend.xml patch file detected, updating the Unattend.xml file baseline\n\n" >> $updateUnattendLog
              rsync -aqzz "/images/drivers/Unattend.xml" $unattend;
          else
              echo -en "\n\nNo Unattend.xml patch file detected, skipping update of unattend.xml file baseline and just updating contents\n\n";
              echo -en "\n\nNo Unattend.xml patch file detected, skipping update of unattend.xml file baseline and just updating contents\n\n" >> $updateUnattendLog
          fi
          #echo "File update Done"
          debugPause
          if [[ $adon=="1" ]]; then 
          cp $unattend $unattend.old
          
                  domainJoinStr="<JoinDomain></JoinDomain>\n\t\t<MachineObjectOU></MachineObjectOU>\n\t\t<Credentials>\n\t\t\t<Domain></Domain>\n\t\t\t<Password></Password>\n\t\t\t<Username></Username>\n\t\t</Credentials>"
          
                  echo -en "\n\nInjecting Unattend Join fields into unattend for Dynamic update....\n"
          
                  echo -en "\n\nInjecting Unattend Join fields into unattend for Dynamic update....\n" >> $updateUnattendLog
          
                  # get the value of the workgroup to set as the netbios domain for the domain login
          
                  netbiosdomain=`sed -n '/JoinWorkgroup/{s/.*<JoinWorkgroup>//;s/<\/JoinWorkgroup.*//;p;}' $unattend`
          
                  #replace the workgroup join string with the domain tags to be updated
          
                  sed -i -e "s|<JoinWorkgroup>${netbiosdomain}</JoinWorkgroup>|${domainJoinStr}|g" $unattend >/dev/null 2>&1
          
          
          
                  echo -en "\n\nSetting Dynamic Unattend fields - \n\nComputer Name: ${hostname}\nJoining Domain: ${addomain}\nWill be in OU: ${adou}\n"
          
                  echo -en "\n\nSetting Dynamic Unattend fields - \n\nComputer Name: ${hostname}\nJoining Domain: ${addomain}\nWill be in OU: ${adou}\n" >> $updateUnattendLog
          
                  sed -i \
          
          
                      -e "s|<ComputerName></ComputerName>|<ComputerName>${hostname}</ComputerName>|g" \
          
                      -e "s|<Name>\*</Name>|<Name>${hostname}</Name>|g" \
          
                      -e "s|<Password></Password>|<Password>${adpass}</Password>|g" \
          
                      -e "s|<Username></Username>|<Username>${aduser}</Username>|g" \
          
                      -e "s|<Domain></Domain>|<Domain>${netbiosdomain}</Domain>|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 -en "\n\nFailed to update user, pass, ou, and domain setter, set just computername and deviceform instead and using simplified unattend file\n"
          
                      echo -en "\n\nFailed to update user, pass, ou, and domain setter, set just computername and deviceform instead and using simplified unattend file\n" >> $updateUnattendLog
          
                      echo -en "\n\Restoring unattend file from before domain join attempt\n"
          
                      echo -en "\n\Restoring unattend file from before domain join attempt\n" >> $updateUnattendLog
          
                      mv $unattend.old $unattend -f
          
                      echo -en "\n\nSetting Dynamic Unattend fields - \n\nDeviceForm: ${DeviceForm}\nComputer Name: ${hostname}"
          
                      echo -en "\n\nSetting Dynamic Unattend fields - \n\nDeviceForm: ${DeviceForm}\nComputer Name: ${hostname}" >> $updateUnattendLog
                      debugPause
                      sed -i \
                          -e "s|<ComputerName></ComputerName>|<ComputerName>${hostname}</ComputerName>|g" \
          
                          -e "s|<Name>\*</Name>|<Name>${hostname}</Name>|g" $unattend >/dev/null 2>&1
          
                      if [[ ! $? -eq 0 ]]; then
          
                          echo -en "\nFailed again after using failsafe unattend\n"
          
                          echo -en "\nFailed again after using failsafe unattend\n" >> $updateUnattendLog
          
                          debugPause
          
                          handleError "Failed to update user, pass, ou, and domain setter and then failed the failsafe with no domain"
          
                      fi
          
                  else
          
                      echo -en "\n\nRemoving Workgroup join section and backup unattend as adding domain join was a success...\n"
          
                      echo -en "\n\nRemoving Workgroup join section and backup unattend as adding domain join was a success...\n" >> $updateUnattendLog
          
                      rm -f $unattend.old
          
                      sed -i "/<JoinWorkgroup>/d" $unattend >/dev/null 2>&1
          
                      sed -i "/<MachinePassword>/d" $unattend >/dev/null 2>&1
          
                      if [[ ! $? -eq 0 ]]; then
          
                          echo "Failed"
          
                          debugPause
          
                          handleError "Failed to remove the Workgroup setter"
          
                      fi
          
                  fi
                  echo -en "\n\nDone updating $unattend\n"
                  echo -en "\n\nDone updating $unattend\n" >> $updateUnattendLog
                  debugPause
              else
                  echo -en "\n\nNo domain to join variable present, just setting deviceform and computer name and using simplified unattend file\n"
                  echo -en "\n\nNo domain to join variable present, just setting deviceform and computer name and using simplified unattend file\n" >> $updateUnattendLog
                  echo -en "\n\nSetting Dynamic Unattend fields - \n\nDeviceForm: ${DeviceForm}\nComputer Name: ${hostname}"
                  echo -en "\n\nSetting Dynamic Unattend fields - \n\nDeviceForm: ${DeviceForm}\nComputer Name: ${hostname}" >> $updateUnattendLog
                  debugPause
                  sed -i \
                      -e "s|<ComputerName></ComputerName>|<ComputerName>${hostname}</ComputerName>|g" \
                      -e "s|<Name>\*</Name>|<Name>${hostname}</Name>|g" $unattend >/dev/null 2>&1
                  if [[ ! $? -eq 0 ]]; then
                      echo "Failed"
                      debugPause
                      handleError "Failed to set workgroup join fields"
                  fi        
              fi
          done

      Have you tried the FogApi powershell module? It's pretty cool IMHO
      https://github.com/darksidemilk/FogApi
      https://fogapi.readthedocs.io/en/latest/
      https://www.powershellgallery.com/packages/FogApi
      https://forums.fogproject.org/topic/12026/powershell-api-module

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

      145

      Online

      12.0k

      Users

      17.3k

      Topics

      155.2k

      Posts
      Copyright © 2012-2024 FOG Project