Adding drivers to WIM’s

The following will allow you to add additional drivers to Windows Vista/7, and Server 2008. (Also ConfigMgr/MDT boot media.)

First create a directory on your C: drive called images. Within that folder create a folder called Drivers, offline, and Source. Next open up the Deployment Tools Command Prompt. At this point you need to copy the wim file you want to modify to the C:imagessource folder. In this example we’ll say we’re trying to add additional drivers to an RTM Server 2008 R2 boot.wim. Now put all the drivers you want to add in the C:imagesdrivers folder. They need to be actual drivers with the inf files, not just executables that install the drivers.

Now at the command prompt, type

Dism /Get-WimInfo /WimFile:C:imagessourceboot.wim

It will now display all the images contained within boot.wim. Note the name of the image that you want to add the drivers to. When you run this command against a Server 2008 R2 boot.wim you should see the following.

Now you need to mount the wim image that you want to add drivers to. Run the following command.

Dism /Mount-Wim /WimFile:C:imagessourceboot.wim /Name:”Microsoft Windows PE (x64)” /MountDir:C:imagesoffline

Now you have two different possible command to run for adding drivers. The first command will only add the driver you specify. The second command will add all drivers in the Drivers folder and in sub directories.

Dism /Image:C:imagesoffline /Add-Driver /Driver:C:imagesdriversintelraiddriver.INF

 

Dism /IMage:C:imagesoffline /Add-Driver /Driver:C:imagesdrivers /Recurse

If you need to add an unsigned driver run the following command.

Dism /Image:C:imagesoffline /Add-Driver /Driver:C:imagesdriversunsigneddriver.INF /ForceUnsigned

Once you’ve added all the drivers you need, run this last command.

Dism /Unmount-Wim /MountDir:C:imagesoffline /Commit

At this point you can copy your boot.wim file back into the Server 2008 R2 installation source and you’ll have a boot.wim with all your drivers. I would also recommend adding the drivers to install.wim as well.

Creating a bootable USB Thumb Drive using WAIK

First thing you need to do is download and install WAIK. It’s about 1.6GB for Windows 7, so unless you have a decent Internet connection you’re going to be waiting awhile for this part.

Once installed, you’ll want to launch “Deployment Tools Command Prompt” as an admin and then run through the steps below.

  1. type “diskpart”
  2. type “list disk” and then locate the USB Thumb Drive and remember the number assigned to it
  3. type “select disk *” where * is the number associated with the USB Thumb Drive
  4. type clean
  5. type “Create partition primary”
  6. type “select partition 1”
  7. type “active”
  8. type “format fs=fat32”
  9. type “assign”
  10. type “exit” to get out of diskpart

Making BIOS changes using the Dell CCTK during a TS

Something I’ve ran into at my current company is that the now non-existant parent company didn’t seem to know how to inject drivers during a task sequence or into the XP source. What this means is in order for them to image any systems they would have the desktop tech’s manually change the SATA controllers to ATA (Compatibility) mode. Other than it being a huge pain for them to have switched every new system they go over to ATA mode, it’s caused issues for us now becuase it seems every Dell Latitude (E and D series) that’s running in ATA mode with the latest version of McAfee EndPoint Encryption installed seems to have a fatal McAfee error after about a week of being encrypted. (I was told at my previous job by a Safe Boot support person that ATA mode on newer systems “causes problems”. I have no hard proof that it does, but from what I’ve witnessed it appears to be true.)

So, other than finding a way to switch a Windows XP system over to using AHCI instead of ATA and switching all my systems over to AHCI all at once (which I know can be done… but would be a lot of work… and I don’t have the time), I’ve choosen to just make sure that every time a Dell system is imaged it’s using AHCI before it installs Windows. I’m doing this by using CCTK. The steps below will show you how to integrate CCTK into your WinPE Boot Images so that you can use CCTK.exe in your task sequence while still in WinPE. (It’s assumed that you’ve already downloaded the CCTK from Dell and installed the Windows AIK.

  1. The first thing you want to do is make a copy of the source boot.wim for your boot image. It can be x86 or x64, however the following steps will assume it’s x86. I recommend creating a folder called “pesource” on your C: drive and placing the boot.wim within it.
  2. You now need to mount the boot.wim file. I recommend creating a subfolder to pesource called “mount” and then run the following command.
    DISM /Mount-Wim /WIMFile:C:pesourceboot.wim /Index:1 /MountDir:C:pesourcemount
  3. Next you’ll need to add scripting support and WMI support to your boot image. Do that by running the two following commands.DISM /Image:C:pesourcemount /Add-Package /PackagePath:”C:Program FilesWindows AIKToolsPEToolsx86WinPE_FPswinpe-wmi.cab”DISM /Image:C:pesourcemount /Add-Package /PackagePath:”C:Program FilesWindows AIKToolsPEToolsx86WinPE_FPswinpe-wmi.cab”
  4. Now create the folder structure “C:pesourcemountCCTKx86HAPI”
  5. You now need to copy all the files from “C:Program FilesDellCCTKx86HAPI” to “C:pesourcemountCCTKx86HAPI” and the two files cctk.exe and pci.ids from “C:Program FilesDellCCTKx86” to “C:pesourcemountCCTKx86”.
  6. Now find the file “startnet.cmd” located in “C:pesourcemountwindowssystem32” and add the following two lines before “wpeinit”.net start winmgmt
    X:CCTKx86HAPIhapint -i -k C-C-T-K -p X:CCTKx86HAPI
  7. In addition to all of the above, I also injected the “Systems Management Device” drive found in the HAPI folder. This might not be neccesary, but I did it anyways.
  8. Finally the finish everything up you have to commit the changes by running the following commandDISM /Unmount-WIM /MountDir:C:pesourcemount /commit

Now that you’ve done all of that, you can execuate CCTK tasks from within a task sequence. (Just make sure that you have the boot image that you modified assigned to that task sequence you’re running.)

A CCTK command example from within a task sequnce would be as follows…

Create a “Run Command Line” task, populate the command line field with cctk.exe –embsataraid=ahci and then set the Start in: field to X:CCTKx86.

Combining WIM images

You can use the following to combine WIM images. This can be useful because of the amount of space you’ll save by doing so, as well as keeping your WIM directory on your file server looking clean.

You’ll have to start off with two WIM images. One will be used for your master WIM and the other will be merged with the master WIM and then deleted. As an example we’ll say that we have a directory C:WIMS that has WindowsXP_ITUsers.wim and WindowsXP_StdUsers.wim within it. We’re going to keep WindowsXP_ITUsers.wim as the master WIM.

The first thing we need to do is make sure that we turn off any Anti-Virus software that’s running on your machine. Next, create a directory under C:WIMS called MOUNT. Now open the Deployment Tools Command Prompt that comes with Windows AIK and run the command

imagex /info WindowsXP_ITUsers.wim 1 “IT Users” “Windows XP”

By running that command we’ve set the name for index 1 within the WIM WindowsXP_ITUsers.wim to “IT Users” and the description to “Windows XP”. I highly recommend being descriptive in your naming that way you don’t get lost when viewing the contents of your master WIM image later on.

We now need to mount our second WIM image. Do so by running the command

imagex /apply “WindowsXP_StdUsers.wim” 1 C:WIMSMount

Now that our secondary image has been mounted, we want to merge it to our master WIM.

imagex /append C:WIMSMount “WindowsXP_ITUsers.wim” “Standard Users” “Windows XP”

And finally you’ll want to rename the master WIM file to something like WindowsXP.wim since it’s no longer just the IT Users WIM. Keep in mind that when you merge two WIMs using the command line above, the WIM you’re appending will use the next available index number. (There might be a way to specify an index number to use, however I haven’t looked into it yet.) In the event that you’ve created a new WIM file that needs to replace one that’s in your master WIM, you’ll likely want to delete the old WIM from the master. You can do that by running the following

imagex /delete MASTER.wim (INDEX NUMBER)

Keep in mind that if you were to delete index 1 from your master wim and then update the WIM file in ConfigMgr, you’ll need to update any task sequences that were using index 2 of that WIM because index 2 will become index 1.

 

Upgrading the BIOS on Dell systems during OSD

One thing that I do during my OSD task sequences is to have the BIOS on the client machine updated. With Dell systems this is made simple.

Start by downloading the latest BIOS updates for all the models you have in your environment. Once done, add them all into a single package. Then go into the package and start creating a program for each BIOS version, putting “-NOREBOOT -NOPAUSE -FORCEIT” at the end of the BIOS executable. You can now have your task sequence reboot the system and update the BIOS on the system. I would also suggest that you create a WMI filter on the task so that it only runs when obsoletely necessary.

Provisioning mode in ConfigMgr OSD

Occasionally if your task sequence fails, ConfigMgr will fail to take the client out of provisioning mode. This will cause the Run Advertised Programs to not list any advertisements. To manually take the client out of provisioning mode, do the following.

Go to [HKEY_LOCAL_MACHINESOFTWAREMicrosoftCCMCcmExec]

Check for the values

  • ProvisioningMode
  • SystemTaskExcludes

Ensure that ProvisioningMode is set to false, and that SystemTaskExcludes is blank.

Target machines with successful advertisements

By using the following WQL query, you can populate a collection with machines that successfully ran an advertisement. All you need to do is update the Advertisement ID in the query.

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomain
ORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ResourceId in (select ResourceID from SMS_ClientAdvertisementStatus where
AdvertisementID = "CHO000A5" and LastStateName = "Succeeded")

Installing updates during an OSD

It’s taken me awhile to get this working properly, however I’ve finally come up with a way to guaranteeing that your imaged computers finish imaging with all the necessary updates installed. (Of course you can embed the updates into the operating system source files using a product like nLite, or create and deploy a WIM image that already contains the updates… however this is the way I prefer.)

  • First you need to create a collection with no collection memberships or queries. This collection will be used to target update deployments at machines being imaged. In my case I have created a parent collection called “Updates for OSD” and then two child collections, “Windows 7 Updates OSD” and “Windows XP Updates OSD”.
  • You then need to create a deployment targeting your collection and ensure it contains the updates you want the imaging system to receive. (Don’t forget to make sure the updates exist on a distribution point.)
  • Now in your task sequence, you’ll need to create the following tasks.

    The first task (Add to OSD Updates Collection…) is a “Run Command Line” task. The command line it runs is “AddtoCollection.vbs SCCMSERVER COLLECTIONID %SMSTSClientIdentity%”. It’s running that command from a package that contacts the vbs script. (I didn’t make the vbs script, however I don’t recall where I got it.) This script adds the machines that’s being imaged to whatever collection you specify. The script contains a sleep command that makes the task sequence wait 3 minutes before proceeding. Waiting the 3 minutes ensures that the computer shows up in the collection before the next step.The second task (Machine Policy Retrieval & Evaluation)  is a “Run Command Line” task. The command line it runs is “machinepolicy.vbs”. This script (other than obviously initing a machine policy retrieval and evalution…) makes the imaging process aware of the software updates available to it.The third task (Sleeping for a minute to allow the policy to apply) does just what it says. It is a “Run Command Line” task that runs “sleep.vbs”.The fourth task (Initiate Update Scan…) also does just what it says. This step might not be necessary… however I haven’t taken it out yet. It is a “Run Command Line” task that runs “updatescan.vbs”.The fifth  step (Deploy Updates) is a “Install Software Updates” task, set to install All Software Updates. At this stage, you’ll see it sit for awhile (sometime a long while…) then download all the updates and install them.The sixth step (Execute SU cache evaluation…) is a  “Run Command Line” task that runs “evaluateSUcache.vbs”. This script just evaluates the Software Update cache. This also might not be necessary however I haven’t taken it out yet.

    The seventh and last step (Deploy Updates) is again an “Install Software Updates” task, set to install All Software Updates. I put this in again to ensure that no updates were missed. As long as no updates were missed, this step should finish in under a minute.

As of right now I haven’t worked on getting a script together to remove the computer from the updates collection at the end. I’m sure it wouldn’t take long to do, however at the moment I prefer to leave the computers in the update collection just to ensure that they get all the updates. All the scripts that are needed can be downloaded HERE.

 

::EDIT

I’ve recently ran into an issue were regenerating the WSUS Client GUID is required. In my case, I’ve added a run command line task with the below command line after the “Sleeping for a minute…” step, followed by a reboot. The command line step for regenerating the GUID needs to start in “C:WindowsSystem32”.

wuauclt /resetauthorization /detectnow

 

 

Software Update Display Notifications

Most of the time when you’re working with software updates within ConfigMgr, you want to see the display notification on server systems however you don’t want any display notifications on workstations. Unfortunately in ConfigMgr there’s only an option to turn on or off the display notification for the entire site, not just collections of machines.

However I’ve finally found a solution around this issue and have put a link below to vbscripts that will set the display flag for the software update client and allow you to set different display notification settings for different collections of machines. The link below will download a zip file that contains three vbscripts. The title of the scripts explain what each one will do. All you need to do is advertise the script to a collection of machines and have it run as the System.

Download for the vbscripts

Enable Notification

dim updatesDeployment
set updatesDeployment = CreateObject (“UDA.CCMUpdatesDeployment”)
updatesDeployment.SetUserExperienceFlag 1
Disable Notification
dim updatesDeployment
set updatesDeployment = CreateObject (“UDA.CCMUpdatesDeployment”)
updatesDeployment.SetUserExperienceFlag 2
Follow ConfigMgr Policy
dim updatesDeployment
set updatesDeployment = CreateObject (“UDA.CCMUpdatesDeployment”)
updatesDeployment.SetUserExperienceFlag 0

Initiate SCCM Client actions via VBScript

Often times you’ll find yourself wanting to initiate client actions using a script. The below script allows you to do just that. Simply replace the value of the sInventoryActionID to whatever action you’d like to initiate.

Action IDs

  • Hardware Inventory – 00000000-0000-0000-0000-000000000001
  • Software Inventory – 00000000-0000-0000-0000-000000000002
  • Data Discovery – 00000000-0000-0000-0000-000000000003
  • Machine Policy Assignment Request – 00000000-0000-0000-0000-000000000021
  • Machine Policy Evaluation – 00000000-0000-0000-0000-000000000022
  • Refresh Default Management Point – 00000000-0000-0000-0000-000000000023
  • Refresh Location (AD site or Subnet) – 00000000-0000-0000-0000-000000000024
  • Software Metering Usage Reporting – 00000000-0000-0000-0000-000000000031
  • Sourcelist Update Cycle – 00000000-0000-0000-0000-000000000032
  • Refresh proxy management point – 00000000-0000-0000-0000-000000000037
  • Cleanup policy – 00000000-0000-0000-0000-000000000040
  • Validate assignments – 00000000-0000-0000-0000-000000000042
  • Certificate Maintenance – 00000000-0000-0000-0000-000000000051
  • Branch DP Scheduled Maintenance – 00000000-0000-0000-0000-000000000061
  • Branch DP Provisioning Status Reporting – 00000000-0000-0000-0000-000000000062
  • Software Update Deployment – 00000000-0000-0000-0000-000000000108
  • State Message Upload – 00000000-0000-0000-0000-000000000111
  • State Message Cache Cleanup – 00000000-0000-0000-0000-000000000112
  • Software Update Scan – 00000000-0000-0000-0000-000000000113
  • Software Update Deployment Re-eval – 00000000-0000-0000-0000-000000000114
  • OOBS Discovery – 00000000-0000-0000-0000-000000000120

Initiate client action script (script below initiates hardware inventory action)

 

 

 

‘Declare Variables
On Error Resume Next
Set sho = CreateObject(“WScript.Shell”)
strSystemRoot = sho.expandenvironmentstrings(“%SystemRoot%”)
strCurrentDir = Left(Wscript.ScriptFullName, (InstrRev(Wscript.ScriptFullName, “”) -1))
‘ Get a connection to the “rootccminvagt” namespace (where the Inventory agent lives)
Dim oLocator
Set oLocator = CreateObject(“WbemScripting.SWbemLocator”)
Dim oServices
Set oServices = oLocator.ConnectServer( , “rootccminvagt”)
‘Reset SMS Hardware Inventory Action to force a full HW Inventory Action
sInventoryActionID = “{00000000-0000-0000-0000-000000000001}”
‘ Delete the specified InventoryActionStatus instance
oServices.Delete “InventoryActionStatus.InventoryActionID=””” & sInventoryActionID & “”””
‘Pause 3 seconds To allow the action to complete.
wscript.sleep 3000
‘Run a SMS Hardware Inventory
Set cpApplet = CreateObject(“CPAPPLET.CPAppletMgr”)
Set actions = cpApplet.GetClientActions
For Each action In actions
If Instr(action.Name,”Hardware Inventory”) > 0 Then
action.PerformAction
End If
Next