giving something back after taking a lot :-)

Maik Koster at myITforum.com

Create your custom Boot Wizard - Execute the Wizard, process the results and create the Boot Image

April 18, 2009

In the last two articles Create your custom Boot Wizard - some advanced stuff and Create your own Boot Wizard - Display dynamic data we created a Custom Boot Wizard which requests a list of available OSD Task Sequences (we actually get the collections the Task Sequences are advertised to) and shows this dynamic list to the user to chose from. In this article we now will create a script which will call our custom Boot Wizard and process the results of the users choice.

If you deploy a Boot Image via WDS/PXE or CD you can configure it in a way to execute something, before the "real" process (The Task Sequence) starts. This is called "pre-execution Media Hook". Sounds groovy but it's quite simple. During the startup it will look for a file called "TSConfig.ini" in the root of the Boot image. If this file exists it will be processed. Now you can add a section like

[CustomHook]
CommandLine="wscript.exe x:\Deploy\Scripts\ZTIMediaHook.wsf"

to this file and it will execute the Script "ZTIMediaHook.wsf" which is located at x:\Deploy\Scripts. X:\ is the path to the Boot Image. We will first go through this script to see what it does for us. At the end I will show you how you can add this file, the Boot Wizard and all supporting script files to your Boot image.

OK, let's start with the script. You will recognize that it looks quite similar to other MDT Scripts. In most cases it is the easiest to take an existing script and just change it the way you want it to have. This way you don't need to pay much attention on being compliant with the MDT Standards. We will skip the header and look at the "Main routine".

On Error Resume Next
iRetVal = ZTIProcess
ProcessResults iRetVal
On Error Goto 0

This simply executes the Function "ZTIProcess" and call a MDT Internal function called "ProcessResults" with the return value. Skip this for now. Important is only that it calls the function ZTIProcess. Now we have a look on the ZTIProcess Function:

Function ZTIProcess() 

    Dim iRetVal
    Dim sCmd
    Dim sAssignedSite
    Dim iCount     ' Initialization
    iRetVal = Success
    oEnvironment.Item("DeploymentMethod") = "SCCM"     ' Process bootstrap rules
    sCmd = "wscript.exe """ & oUtility.ScriptDir & "\ZTIGather.wsf"" /inifile:SCCM_Bootstrap.ini"
    iRetVal = RunAndLog(sCmd, true)

So far nothing important. Just some standard variables and we call ZTIGather.wsf with the "SCCM_Bootstrap.ini" file which has already been mentioned in the last article. We do this to gather some values we need for further processing like IP Address, MAC Address, etc.

    ' Get assigned Site
    oEnvironment.Item("AssignedSite") = GetAssignedSite
    If IsNothing(oEnvironment.Item("AssignedSite")) Then
        oLogging.CreateEntry "Unable to determine assigned site.", LogTypeWarning
    Else
        oLogging.CreateEntry "Client is assigned to site " & oEnvironment.Item("AssignedSite"), LogTypeInfo
    End if

Here we get the assigned Site of the Computer which is required by the wizard to get the list of collections. The Assigned Site will be returned by the custom Function "GetAssignedSite":

Function GetAssignedSite
    Dim oService
    Dim oXML     ' Create the web service instance
    Set oService = new WebService
    oService.IniFile = "SCCM_Bootstrap.ini"
    oService.SectionName = "GetSCCMAssignedSite"
    ' Make the web service call
    Set oXML = oService.Query
    If oXML Is Nothing Then
        oLogging.CreateEntry "Unable to call GetSCCMAssignedSite web service.", LogTypeWarning
    Else
        GetAssignedSite = UCase(oXML.SelectSingleNode("string").Text)
    End if
End Function

Again it queries a webservice with the following definition:

[GetSCCMAssignedSite]
WebService=http://YourWebServer/Deployment/AD.asmx/GetSCCMAssignedSite

In this case, I chose to query AD for the AssignedSite. If SCCM information is not published to AD you can also find a corresponding webservice for SCCM which will call the SLP to get the necessary information. Now we go ahead with the ZTIProcess function:

    If Not HasOSDAdvertisement Then
        ' Show Wizard
        sCmd = "MSHTA.exe """ & oUtility.ScriptDir & "\Wizard.hta"" /definition:CustomBootWizard.xml"
        RunAndLog sCmd, true         ' Process result from Wizard if requested
        If oEnvironment.Item("WizardComplete") <> "Y" Then
            oLogging.CreateEntry "User has canceled the wizard. Exiting!", LogTypeInfo
            Exit Function
        End If
    Else
        oLogging.CreateEntry "Computer has already an Advertisement. Skipping Wizard.", LogTypeInfo
        Exit Function
    End If

Here we will execute the wizard only, if there isn't already a Task Sequence available for that computer (I will skip this function as it looks almost identical to "GetAssignedSite". Just find it in the download for the complete source). The wizard is called by a function called RunAndLog. Again this is a Function which comes with MDT (even if it needs to be available within the Script "ZTIMediaHook.wsf) and can be found in the download.It just adds some common logging functionality. Not really something which gives us some more information here so lets also skip this. After the user has finished the wizard, we need to check if he canceled the wizard, in that case we should also cancel the further processing, or chose collection.

Now to the core functionality:

    ' Add Computer to specified collection
    If AddComputerToCollection Then
        ' Wait for Advertisement
        oLogging.CreateEntry "Waiting for Advertisement", LogTypeInfo
        WScript.Sleep 5000         For iCount = 1 To 20

            oLogging.CreateEntry "Sleeping 5 seconds to wait for an OSD Advertisement (Attempt " & iCount & " of 20).", LogTypeInfo
            WScript.Sleep 5000

            If HasOSDAdvertisement Then
                oLogging.CreateEntry "Found an OSD Advertisement, continuing ...", LogTypeInfo
                WScript.Sleep 3000  ' Wait three more seconds, just in case
                Exit For
            End If
         Next
     End If

This finally will add the computer to the collection and then wait until the advertisement is available for the computer. This typically takes only a couple of seconds but depending on the current load of the server also up to a couple of minutes. You can adjust the timing to your needs. That's it! The called functions "AddComputerToCollection" and "HasOSDAdvertisement" again are quite similar to the "GetAssignedSite". Quite useless to repeat similar stuff so just download the solution and have a look on the complete Scripts and SCCM_Bootstrap.ini.

End Function

;-)


This was a quite simple example. Typically you need to include additional information into the wizard and probably a bit more complex process to decide what to do, etc. But this is meant as a start to your own wizards. As soon as you understand how the different parts work together it's easy to extend it. Or just ask for help.

However, the last step is now to include all this information into a Boot Image. We first start with a new Boot Image.

As this is about MDT, we will create our Boot Image using MDT. Before we actually create the image, some actions are necessary. First, have a look at the installation folder of the "Microsoft Deployment Toolkit" (typically within Program Files). You should find a subfolder called "SCCM". In there you will find some of the files used for the original MDT Wizard. You probably recognize the "ZTIMediaHook.wsf" and "SCCM_Bootstrap.ini" files. During this articles we simply used the same names. You will also find the "TSConfig.ini" file mentioned at the beginning of this article. As we stick to the same names MDT is using to execute its wizard there is now need to create our own, so we can use the on contained in this folder. 

We could now simply copy our custom files into this folder to have them included into the Boot image. I personally prefer to not touch any original stuff (Have fun if you install an Update :-) ). So we will use a different way for adding our files. To do this, we need to create a folder which will contain our files. As we need to supply the path to this folder later via its UNC path, create it on a network share. Preferably the share which is already hosting all your Reference files. During the creation of the Boot image with MDT we will have the option to add an additional folder to the image. The content of the path will be copied to the root of the Boot image. So if you have a file just in this folder it will be available in the root. I use this e.g. to add files like Trace32.exe and some others for easier troubleshooting. OK, lets say you have a folder "\\YourFileServer\Packages$\MDT\Additional_Files" within this folder create a Folder called "Deploy" and within this a new folder called "Scripts". That's the path MDT will store its files so we just use the same. Now copy all your custom Scripts, the wizard xml file, the SCCM_Bootstrap.ini  and what else you would like to have in there into this folder.

If you are done with this, it's now time to create the new Boot image. First you need to create another folder to store the Boot Image itself. Again, it needs to be on a networks share. For this example it will be \\YourFileServer\Packages$\MDT\Custom_Boot_Image. Now open the ConfigMgr Console and expand the "Operating System Deployment" Node. Right click on the node "Boot Images" and choose "Create Boot Image using Microsoft Deployment".

CreateMDTBootImage1

It will now open a wizard which will help you creating your new Boot Image. First you need to supply the path where the new Boot image shall be stored. Just type in the UNC Path of the folder us just created

CreateMDTBootImage2

Next supply a name, version and comment for the Boot image. On the next Screen

CreateMDTBootImage3

you have the possibility to enable support for the pre-execution Hook (just check the "Add media hook files ..." option) and supply the path for our Additional Folder. You don't need to take care about the text field with the "Web service URL" as we will overwrite the SCCM_Bootstrap.ini file anyway :-). (btw. don't forget to adjust the SCCM_Bootstrap.ini to your environment. If you just downloaded it it will contain a generic path to http://YourWebServer/Deployment/...) .Adjust the rest of the options to your needs. After finishing the Wizard it will then create two files. a WinPE.wim and a WinPE.PackageID.wim. The second is the one which will be distributed by SCCM. You will notice that it is noticeable larger as it contains additional SCCM binaries and the Drivers you added (or will add) to the Boot image. So the WinPE.wim is the reference which is used by SCCM to create the second one. If you mount the WinPE.wim with imagex you can verify that all files from our "Additional Folder" have been added to the Boot image and that the original files from MDT have been overwritten.

Now the drawback. If you "Update" the Boot image in SCCM, changed files from the "Additional folder" or the MDT Folder will not be updated in the wim :(

There are two ways to update your files

  1. Recreate the image instead of updating. Just delete the old Boot image, and Create a new one. The problem with this is that you need to add it again to the DPs where you need it and the PXE Shares. You also would need to change the Boot Image in each Task Sequence which used the old one.
     
  2. The method I prefer! Mount the image, make the changes and commit them and then update the Boot image in SCCM.

 

The second way isn't actually very complicated. To do what I suggested just

  • Create a new Folder to mount the image (e.g.: C:\Mount)
     
  • Mount the wim with imagex (It's part of the WAIK which has (or should) already been installed on your SCCM Server. Or install it on your computer. You probably need a couple more things from the WAIK if you digg into Deployments :-)) using "imagex /mountrw Path_and_Name_to_the_winPE.wim 1 C:\Mount". "/mountrw" mounts the wim in read/write mode so that you can make changes to the wim. The 1 in the commandline specifies the first image within the wim file (wim files can contain several images) and C:\Mount is the folder we just created
     
  • Open C:\Mount and do all the changes necessary. Adding new files, etc.
     
  • Unmount the wim and commit the changes with "imagex /unmount /commit C:\Mount"

After you have changed the wim just Update the Boot Image in the console and all changes will now be integrated into the Boot image used by your Task Sequences and it will be deployed to all your DPs and PXE Shares. 

 

As mentioned already in the last article, you will find all files, scripts etc. on our new codeplex page http://mdtcustomizations.codeplex.com/ (Download example files). It is a repository for MDT Scripts, Front ends, Web services and Utilities for use with ConfigMgr/SCCM. Also be aware that you need to adjust some files you downloaded to your environment. Specifically the SCCM_Bootstrap.ini file needs to be changed to that that Webservice definitions are pointing to the Webserver which is hosting the webservice in your environment.  

 See also

Create your custom Boot Wizard - make it available for all known and unknown Computers

Using a custom Boot Wizard to boot known and unknown computers in SCCM and choose a Task Sequence to run - Step by Step

Comments

  • No Comments