Issue with “Install Software” Task Sequence Step and ConfigMgr Stand-Alone Media Build

We recently encountered an issue that has been around for a while, but no real documentation on it except for a couple posts in the TechNet Forums. Hopefully this post will save you some time.

Consider the following scenario:

  1. You are using ConfigMgr OSD, and installing additional applications by using the “Install Software” Task Sequence Step.
  2. You use a Central Administration Site (CAS) to create the stand-alone media build.

When you run the stand-alone media build process, the task sequence fails on any step that is configured to “Install a Program.” The errors appear in the smsts.log and execmgr.log, as shown below:

smsts.log:

Failed to invoke Execution Manager to Install Software for PackageID=LAB003EA
InstallSoftware Failed. hr=0x87d01004
Process completed with exit code 2278559748
Failed to run the action: Install FOO Client. The program is disabled. (Error: 87D01004; Source: CCM)
This message may also appear: Failed to invoke Execution Manager to Install Software x80008004      

smstslog-failsoftwareinstall

execmgr.log:

TS Step required to run a disabled program. Rejecting.

execmgr_failSwinstall

This is a known issue. Here are your options for work-around:

  • Create the stand-alone media at a Primary site instead of the Central Administration Site (CAS), or
  • Replace all “Install Software” TS Steps with “Run Command Line,” or
  • Add the following Run Command Line step to the task sequence after the Setup Windows  and Configuration Manager step to enable the software distribution agent before  the first Install Package step runs:
WMIC /namespace:\\root\ccm\policy\machine\requestedconfig path ccm_SoftwareDistributionClientConfig CREATE ComponentName="Enable SWDist", Enabled="true", LockSettings="TRUE", PolicySource="local", PolicyVersion="1.0", SiteSettingsKey="1" /NOINTERACTIVE

You don’t need to do all three steps-choose one.

Greg

How To: Enable Debug Logging for an OS Deployment Task Sequence

Previously, we covered how to enable debug logging for the ConfigMgr client agent as well as the ConfigMgr 2012 admin console. This post will focus on enabling debug logging for an OSD TS.  This process is a little different when starting OSD from WinPE, as you are starting in a state with no client agent installed.

* There are two steps required to fully enable debug logging for OSD task sequences – 1) WinPE phase (before ‘Setup Windows and Configmgr TS Step), and 2) Windows Phase (during ‘Setup Windows and ConfigMgr TS Step’)

Enabling Debug Logging for WinPE:

Create a file named smsts.ini with the following contents:

[Logging]
LOGLEVEL=0
LOGMAXSIZE=524288000
LOGMAXHISTORY=3
DEBUGLOGGING=1
CCMDEBUGLOGGING=1

Here’s a brief description of each property (review detailed info on TechNet):

LogLevel = 1 is the default value, set this to 0 for the most verbose logging

LogMaxSize = Maximum log file size in bytes – the example is 524288000 bytes (250000 default)

LogMaxHistory = The number of history (aka ‘rollover’) logs to keep (1 is default)

DebugLogging = Set this to 1 (True) to enable debug, which will provide more detail

CCMDebugLogging = Set this to 1 (True) to enable debug, which will provide more detail **I don’t think this is necessary, as we are doing this in the previous step (DebugLogging), but MS has told me multiple times to do it, so I include it.

Next, you need to mount the boot.wim file that will be used for OSD, and copy the file to the \windows directory. Unmount the .wim and commit changes  (Note that the latest version of dism.exe uses the mount-image argument–previous versions used mount-wim).

Now that you have updated the boot.wim, update DPs, and re-create your task sequence boot media. Another note – * Some OSD-savvy admins may attempt to simply open a command prompt at the WinPE welcome screen and drop the smsts.ini file in the x:\windows directory, but this will not work. Smsts.ini must exist in the boot media which is booted to start OS deployment, as it appears to be consumed before the welcome screen appears.

When you launch a TS from WinPE, you will find the following entries in smsts.log (after clicking Next to the welcome screen):

smstslog_debuglogging

Congratulations – you’re half-way there. If you only want to debug during WinPE,  you can stop here. But be advised that as soon as the TS completes the “Setup Windows and ConfigMgr” step, the debug logging (and any additional customizations from the smsts.ini file) will be removed. To preserve the log, continue to the next step:

Enabling Debug Logging for the Windows Phase:

During the “Setup Windows and ConfigMgr” TS step, mini-setup runs, and the ConfigMgr client is installed. The logging used from this point forward will be based on the installation parameters defined during the “Setup Windows and ConfigMgr step. So if you had a larger max log size and history in WinPE, and take the default config for “Setup Windows and ConfigMgr”, that extended logging will be removed (and logs overwritten) as soon as the TS continues from the Windows OS. You could simply modify the arguments for that step to be similar to the following:

CCMDEBUGLOGGING=1 CCMLOGLEVEL=0 CCMLOGMAXSIZE=52488000 CCMLOGMAXHISTORY=5 FSP=MYFSP.mydomain.com SMSCACHESIZE=35840

But please understand this will enable debug logging for the ConfigMgr client agent, which means these settings will apply to all client logging (unless you run something to modify logging at a later point in time). A better scenario would be to only enable the configuration on an as-needed basis. Here’s how I recommend enabling debug logging (and preserving the debug logging provided in WinPE) as needed in a TS.

Create a TS step to set a TS variable:

EnableDebug_setvariable

The variable SMSClientInstallProperties is a builtin TS variable that will override values entered into the “Setup Windows and ConfigMgr” TS step. To take this a step further, create a conditional for this step to only run if x:\debug.txt exists.

EnableDebug_setvariable-2

To leverage this, you can simply open a command prompt while the TS is running (before this step would run) and create a file called debug.txt in the root of x:\.

If you don’t want to add a step to the TS, you could launch a command prompt while the TS is running in WinPE, and run the following VBScript:

Set oTSEnv = CreateObject("Microsoft.SMS.TSEnvironment")
oTSENV("SMSClientInstallProperties") = "CCMDEBUGLOGGING=1 CCMLOGLEVEL=0 CCMLOGMAXSIZE=52488000 CCMLOGMAXHISTORY=5 FSP=MYFSP.mydomain.com SMSCACHESIZE=35840"

This will set the TS variable for a one-time use for this TS.

To recap, I recommend enabling debug logging while in WinPE, and only configure debug logging for the ConfigMgr client as needed. This will give you more debugging while in WinPE, and clean up everything back to your corporate standard after Windows is installed. And then as needed, you can easily add debug logging to the ConfigMgr client agent.

Greg

How To: List Task Sequence Environment Variables and Values

(another encore presentation from my old blog site…)

From the TechNet forums, this is an example for how to display Task Sequence Environment Variables and Values using VBScript:

Set oTSEnv = CreateObject(“Microsoft.SMS.TSEnvironment”)
For Each oVar In oTSEnv.GetVariables
WScript.Echo oVar & “=” & oTSEnv(oVar)
Next

You could save those two lines of code to “ShowTSVars.vbs”, and then when you want, simply run “cscript //nologo ShowTSVars.vbs >vars.txt” to write all variables to vars.txt.

Windows 8 – A simple start screen button

I’ve been spending some time testing Windows 8 and Server 2012 lately, mostly on virtual machines. If you’ve worked with either OS in a VM (or even Remote Desktop), you may have noticed the challenge in hitting the start screen button. . .er orb.   It is very easy on a real monitor, because you simply move the mouse to the bottom-left corner of the screen. But on a VM, you can quickly move from the bottom-left corner of the VM to the applications on ‘the real’ system.  So to make this a little easier for myself, I created a  shortcut to launch the start screen:

Task bar in Windows 8 CP

All that’s required is a simple VBScript using my all-time non-favorite method “Sendkeys.” Here’s the code:

Set WshShell = WScript.CreateObject(“WScript.Shell”)
WshShell.SendKeys “^{ESC}”

That’s it – just pressing [CTRL]+[ESC] will launch the start screen (as well as the start menu on previous versions of windows). So all you need to do is create a shortcut to run that VBScript.

Of course I wanted to automate this a little, so attached is a .zip file that you can deploy in a ConfigMgr/MDT task sequence. Simply run “InstallStart.cmd” and it will configure everything for you.

Download the install source.

As you may  know, these shortcuts are part of the user profile, that’s why we went to the extra trouble to set this shortcut for every profile. There are some handy examples in the code. ConfigureActiveSetup.reg shows you how to launch a command to run one time for each user that logs on (kind-of like a runonce per user) – this will call the PintoTaskBar.vbs to pin the shortcut to the task bar (note, if Windows is configured to a different setting than English, you may need to modify PinToTaskBar to find the equivalent action for your language). ShowStart.vbs executes the SendKeys command.  **After running the script, logoff/on for the icon to appear.

Greg

Here’s information for how to create a ”Shutdown” tile in Metro.

How to: Set Sending Priority of All ConfigMgr Driver Packages with PowerShell

Here’s a quick answer to a post yesterday on myITForum’s ConfigMgr/SMS Email list.

#replace MySiteServer with central site server name,
#and LAB with site code
get-wmiobject sms_driverpackage -namespace root\sms\site_LAB -computer MySiteServer -filter "Priority <> 3" | foreach {
    $_.Priority = 3
    $_.Put()
}

Use this script to set the Sending Priority to Low for all ConfigMgr driver packages. You can see in the script, we query the SMS_DriverPackage class for all Driver packages that do not have a Priority = 3, and then enumerate each one, set the Priority property to 3 (3=Low, 2=Medium, 1=High) and then used the Put() method to save the change. Here’s a brief list of the classes that you can use modify sending priority by simply replacing the class name in the script above:

SMS_PackageBaseClass - This is the base class for all package class. Use extreme care (and testing) when running scripts against SMS_BasePackagClass.
SMS_DriverPackage
SMS_ContentPackage – new to ConfigMgr 2012, this is for Applications, no SDK Doc currently available.
SMS_OperatingSystemInstallPackage
SMS_SoftwareUpdatesPackage
SMS_TaskSequencePackage
SMS_ImagePackage
SMS_BootImagePackage
SMS_Package

You can also use the get-wmiobject –filter command to find a specific package. Just change -filter “Priority <> 3″ to –Filter “PackageID=’LAB00028′”

Bonus TIP: Here’s a quick script to show the count of each Package type using the group-object cmdlet:

#replace MySiteServer with central site server name,
#and LAB with site code
get-wmiobject sms_packagebaseclass -namespace root\sms\site_LAB -computer MySiteServer | group-object __Class | select-object Name, Count

Happy Scripting,

Greg

Fun with WMIC

(When preparing to write this brief post, I see that my MVP colleague Sherry Kissinger also has a post on WMIC and Windows Installer. Check it out – it’s a good read too.) 

Here are a couple more examples to add to your tool belt, especially when working with teammates in remote offices, and you need information from WinPE. My perfect example is that a tech reports in that OSD isn’t working, the symptom is that no fixed disks appear to be present on the system. This error usually means that you don’t have a mass storage driver in WinPE for the hardware. Of course, this error can also mean that you have a hard disk error, or that it’s not connected to your system.

Back to task, here are two example command lines for querying win32_pnpentity to display all Plug-and-Play information for a system.

Wmic /namespace:\\ROOT\cimv2 path win32_pnpentity get /format:hform >”c:\temp\data.htm”

Wmic /namespace:\\ROOT\cimv2 path win32_pnpentity get /format:csv >”c:\temp\test.csv”

The first example writes the information to a .htm file, and the second writes the information to a .csv file.

Once you have the PNP IDs, you can begin your journey to find the appropriate mass storage drivers.

More info: Creating and editing formats in WMIC.

Greg

How To: Inject Drivers from USB During a ConfigMgr Operating System Task Sequence

ConfigMgr OSD does a great job of injecting drivers ‘on the fly’ into your OS Deployment process. For example, you can create task sequence steps with conditional statements to apply drivers for a specific model. That’s great for your standard build, but how do you handle those one-offs, those non-standard builds? Here’s a process that you can you for those non-standard builds, or for that hardware that you’re testing, but haven’t quite committed to being a standard yet.  All we need is a vbScript, raw drivers, and an additional step in your task sequence (haven’t tested with MDT, but should work there as well). The following process ONLY works on Windows 7 and Windows Server 2008 R2. If there is enough demand, I’ll create a similar script for previous Operating System versions.

Step 1 – Create a USB folder with raw drivers for the desired hardware.

  • Create a folder in the root of a USB drive named “ExportedDrivers”
  • Copy desired drivers to this folder. You can create subfolders to help with organization if you’d like. Please note that *everything* in the ExportedDrivers AND ALL SUBFOLDERS will be processed, so try to keep the folder structure organized, and to ONLY include the desired raw drivers.
  • Your folder should look similar to this:
  • We have a few extra folders here to keep things organized, but you can just put them in the root of “ExportedDrivers” if desired.

Step 2 – Create a package with ImportCustomDrivers.vbs

  • Create a new Package (or just add this file to an existing package)
  • Download ImportCustomDrivers.txt, and rename to ImportCustomDrivers.vbs.
  • Send to DPs.

Step 3 – Add new step to OSD Task Sequence

  • This step should run in WinPE, just before all other “Apply Driver Package”or “Auto Apply Drivers” step.
  • Your Task Sequence step would look similar to this:
  • Depending on your environment, you may want to enable the ‘continue on error’ checkbox on the Options tab. If the script attempts to import a driver that does not apply to the current operating system, it will return a failure exit code.
  • If you have ADDITIONAL “Apply Driver Package”, or “Auto Apply Drivers”steps, and you want to skip these steps if we import drivers from the USB, enter a conditional where Task sequence variable “OSDCustomDriversApplied” not equals “True” (this variable is set in the .vbs when it runs).

Now that you have your task sequence configured, insert the USB drive into the test system and launch a test build. At the “Add Custom Drivers…” step. you will see a command prompt that shows the status of the drivers that are being injected.

  • In WinPE, two log files will be created in X:\Windows\Temp\SMSTSLog:
    • OSD_CustomDrivers.log – this is the log for the vbscript
    • DISMCustomImport.log – this is the out file from the DISM command to import everything under USBDRIVE:\ExportedDrivers\
  • The log files will also be copied to the ConfigMgr log file directory to allow for post-image troubleshooting.

Again, this process is meant for those one-off scenarios. If you plan to fully support a platform, be sure to handle driver installation using ConfigMgr driver management.

Greg

ramseyg@hotmail.com

Source Code:


'Use this script to import custom drivers for Server 2008 R2, Win7, and newer - full blog post on http://gregramsey.wordpress.com/
'Created by: Greg Ramsey

Log "ImportCustomDrivers - Start"
strComputer = "."
strDriverFolder = "ExportedDrivers"
intReturnCode = 0
intFinalReturnCode = 0
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = WScript.CreateObject("WScript.Shell")
Set colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk")

'enum each drive letter, and see if strDriverFolder exists in the root.
For Each objDisk In colDisks
'Check each drive letter to see if there is a
If objFSO.FolderExists(objDisk.DeviceID & "\" & strDriverFolder) Then
'this will only run in a TS environment, so fail if we can't connect to sms.tsenvironment
Log vbTab & "Connecting to SMS.TSEnvironment"
Set oTSEnv = CreateObject("Microsoft.SMS.TSEnvironment")
If err.number <> 0 Then
Log vbTAB & "Unable to connect to Microsoft.SMS.TSEnvironment"
Log "ImportCustomDrivers - End"
WScript.quit(err.number)
Else
'prepare the command line, and launch the DISM command
Log vbTAB & objDisk.DeviceID & "\" & strDriverFolder & " Exists, Importing drivers.."
strCommand = CStr("Dism /image:" & oTSEnv("OSDTARGETSYSTEMDRIVE") & "\ /logpath:%windir%\temp\smstslog\DismCustomImport.log /Add-Driver /driver:" & objDisk.DeviceID & "\" & strDriverFolder & " /recurse")
Log vbTAB & "Preparing to run the following command: " & strCommand
intReturnCode = oShell.Run(strCommand, 1, True)
Log vbTAB & "Return Code = " & intReturnCode
Log vbTAB & "Setting TS Variable OSDCustomDriversApplied = True"
oTSEnv("OSDCustomDriversApplied") = "True"
End If
Else
'no custom drivers exist
End If
'slightly cheesy - if more than one drive have the special folder, the DISM command will run more than once
' so we're using this to capture if ANY of the exit code are <> 0, so we can capture that if there are any failures
' you'll have to review the %windir%\temp\smstslog\DISMCustomImport.log for details
If intReturnCode <> 0 Then intFinalReturnCode = intReturnCode
Next
Log "Final Return code = " & intFinalReturnCode
Log "ImportCustomDrivers - End"
WScript.Quit(intFinalReturnCode)

'a simple logging subroutine
Sub Log(message)
WScript.Echo message
Const ForAppending = 8
Set WshShell = CreateObject("WScript.Shell")
strSystemRoot = WshShell.ExpandEnvironmentStrings("%SystemRoot%")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(strSystemRoot & "\Temp\SMSTSLog\") Then
objFSO.CreateFolder(strSystemRoot & "\Temp\SMSTSLog\")
End If
'Create Output Log
stroutputlog = strSystemRoot & "\temp\SMSTSLog\OSD_CustomDrivers.log"
Set objTextFile = objFSO.OpenTextFile(strOutputLog, ForAppending, True)
On Error Resume Next
txtstatus.value = Trim(Replace((message & " " & Now()), vbTab, ""))
On Error Goto 0
message = Now() & " " & message
'
' Log the given message
'
objTextFile.writeline(message)
objTextFile.Close

End Sub

Dell Systems and Advanced Format Hard Drives

If you’re new to OSD, make sure you understand Advance Format Drives. Chances are, you already have them in your environment. If you have new systems (or old systems with new hard disks) where users are reporting degradation of performance, or issues with Windows Update in the event log, you could be a victim. If you are responsible for Operating System Deployment, I highly recommend the following resources:

Deploying Dell Systems with Advanced Format Hard Drives from DellTechCenter

If there’s one thing I suggest you do, it’s this: Start your change control process to perform the following tasks asap:

  1. Update the WAIK to 3.1 and then update your OSD boot disk, or  apply KB 982018 to your WinPE boot disk.
  2. Deploy KB 982018 to all Win7, Server 2008 R2 systems (or upgrade them to Sp1)
  3. Update Intel Mass Storage Drivers in your OSD Process, if necessary

The easiest way to avoid any advanced format drive headaches is to get your build process updated asap.  

Greg

Follow

Get every new post delivered to your Inbox.

Join 1,044 other followers