11 June 2017

SCCM Software Updates - Windows 10 v1607 and Group Policy Issues

The following post is for professionals that use System Center Configuration Manager (SCCM) to manage their Software Updates. Even though some of what is mentioned is a tad "old", I thought I would put pen to paper as I was once again reminded of the problem this week.  With more computers featuring Skylake or Kaby Lake processors, organisations will be forced to migrate to Windows 10 so this could still be relevant to them.


Background

Patching in Windows 10 RTM and v1511 was run of the mill. Then came the Anniversary Update also known as v1607 and suddenly for many of us, Windows 10 not only stopped patching, but was no longer even scanning WSUS. Reports showed the clients as not requiring the cumulative updates which didn't make sense. Microsoft also released new administrative templates that deprecated some policy settings used by Windows v1511. Information and documentation from Microsoft was scant or non-existant which left many of us scouring the internet for hours looking for answers. All the talk was about Windows Update for Business (WUfB) and Delivery Optmization.

Eventually Microsoft fixed the bug in Windows Update Agent which resolved the WSUS issue but for those of use who use WSUS and SCCM to patch workstations there was still another problem.

Symptom

So you've installed the servicing stack update or a recent Windows 10 cumulative update but you notice that your Windows 10 computers only install Office patches. If you check the compliance reports, the computers will show as not requiring the patch and are therefore Compliant. The UpdatesDeployment.logs only lists Office patches as missing. There is no mention of Windows patches. WUAHandler.log shows that the computers are scanning for updates.

The Problem

I mentioned earlier that Microsoft released new group policy administrative templates. They also changed how those policies now affect Windows Update Agent. The best article I've read about this problem is this:

https://blogs.technet.microsoft.com/windowsserver/2017/01/09/why-wsus-and-sccm-managed-clients-are-reaching-out-to-microsoft-online/ 

To summarise, WUfB stops SCCM client from managing your updates so make sure that you have none of those policies enabled under the section "What you need to check". Microsoft threw us a curveball on this. Under Windows 10 v1511 enabling the equivalent policy "Defer Upgrades and Updates" did not impact the SCCM client which caught some of us off guard when we moved to the next branch release.

-- Matt

5 June 2017

SCCM OSD - Dynamically Install Applications and Packages (Part Two)

This is a continuation of how to configure your OSD task sequence to install Applications and Packages dynamically. First post is here.

The example

The following example assumes that the environment is a little complex. If you plan things right at the start, you're going to have a much easier time later on when you need to make changes. What I've done is I've set myself some self-imposed numbering rules which I'll explain below. I also make use of the Set Dynamic Variables step to define my applications and packages. There are two reasons why I choose this over defining the software in an MDT CustomSettings.ini file. The first reason is I'm impatient. Any change to the INI file means I need to update my content and wait for it to distribute. In small environments this is not such a big deal but I've seen delays in bigger environments when a lot more content is being thrown around. Making a change to a task sequence and waiting for that change to replicate is much faster so that's why I utilise the task sequence a bit more. The other reason is possibly my failing. I could only get the variable Applications to work in CustomSettings.ini. Other variables I defined were ignored. I was under some time pressure so couldn't spend any real time looking into the issue. However if I could get this method to work, I would still choose setting dynamic variables every time because of the first reason.

Here's a small tip, when you've finished building your TS and are ready to test, change the name of the task sequence slightly. When you see that TS name change on your test machine then you know you're ready to go.

Building the task sequence

1. Decide on what your variables names are going to be. In this example I've decided to use APPLICATIONS###. At this point I can still use 3 suffix numbers as this is not the variable SCCM will use when it comes to actually installing the applications. I like 3 numbers as it gives me future flexibility if I need to add more self-imposed rules. Likewise the variable for packages is PACKAGES###.

2. In the State Restore phase of the TS, I've added a Set Dynamic Variable step, inserted the applications I deem mandatory and assigned them to the variable APPLICATIONS. The self-imposed rule is mandatory applications will occupy numbers 001-029.



As this example relates to applications, and remembering what I said in my previous post, you need to use the Application name.

3. Next I'm defining my country and regional specific software. The rule here is that software specific to a country occupies 030-039 while regional software has 040-049. Do the same as before. Here I've added a 7-Zip application.



4. Usually there is some sort of driver that I need to package because still to this day manufacturer's can't get it right. The rule for model specific software is that it occupies 050-070.



The above screenshot is an example of how define the variables for packages. As mentioned earlier, the format required is PackageID:ProgramName. The screenshot below shows where to find that information.



5. Now it's time to re-sort our application list. If the coalesce step is missing then add a Run Command Line step immediately before Install Applications. In the Command Line section enter:


cscript.exe "%deployroot%\scripts\ZTICoalesce.wsf" /CoalescePattern:Applications /CoalesceTarget:CoalescedApps /CoalesceDigits:2



Let's break down the switches;
  • CoalescePattern is asking for the dynamic variable we've been assigning to our applications. The script will enumerate all applications we've assigned to the variable Applications.
  • CoalesceTarget is asking for the output variable that the script will use to bring all our applications together into a new sequential list. In this example I've used CoalescedApps.
  • CoalesceDigits defines the numbered suffix of CoalescedApps. Recall earlier that I said Applications must only have a 2 digit suffix? That's why the number is 2.
6. This is the last step for our applications. All I need to do is define the Base Variable Name that the sequence will use to install the applications. This is the new list I mentioned in the previous step, CoalescedApps.



7. Packages follows the same process except for the suffix. It needs to be 3 digits. So the command line you use is:


cscript.exe "%deployroot%\scripts\ZTICoalesce.wsf" /CoalescePattern:Packages /CoalesceTarget:CoalescedPkgs /CoalesceDigits:3



8. On the Install Package step change the Base Variable Name to CoalescedPkgs.


Now we're all set to test our task sequence. The two logs to check if things aren't working are ZTICoalesce.log and SMSTS.Log. Here is a working example of the two logs in relation to packages.


ZTICoalese.log


SMSTS.log

You can see the ZTICoalesce.log re-orders the packages from PACKAGES051-053 to CoalescedPkgs001-003. SMSTS.log just verifies that the packages installed.

That brings this two part post to an end. I hope that all made sense.

-- Matt

SCCM OSD - Dynamically Install Applications and Packages (Part One)

Note: This is a two part post. If you want to jump straight to the example then click here.

Preamble

There are a few ways to install packages and applications as part of an operating system deployment (OSD) task sequence(TS) in SCCM. This two part post will detail an approach to installing applications and packages which I believe provides the most flexibility and robustness. There are some blogs and posts already on the Internet about this however I found that I still had to piece everything together so I decided to post an article that I hope encapsulates everything you need to know.

Note: From this point on when I mention Applications it's also inclusive of Packages. Where settings do not apply to both I will make it clear what the differences are.

Before we get too far let's discuss where this post is going. The discussion will touch on the most common methods to installing applications highlighting the pros and cons of each. I'll then talk about the dynamic variable approach and how to configure it. The TS makes use of the ZTICoalsesce.wsf script which is part of the MDT Toolkit so you must use an MDT integrated task sequence. This approach is great for task sequences where applications may differ depending on chassis, model, country, or office. It's designed so that there is minimal effort when you need to add, modify or delete software.

Still interested? Good....

Common Application Install Methods


The following is a list of the common methods used to Install Applications. I'll try to keep this brief as there is plenty of material on the Internet should you need further reading.

1. Adding applications to the list box in the Install Applications TS step.

https://docs.microsoft.com/en-us/sccm/osd/understand/task-sequence-steps#a-namebkmkinstallapplicationa-install-application 

This is easiest option to configure. Downside to this method is two fold. You will need multiple Install Applications TS steps to accommodate different software setup. Also the list box can only hold 9 entries (starting with SCCM 1702, Microsoft has expanded that to 99 entries). If you have more than that then you need to add another step.

2. Adding applications as a collection variable.

http://schadda.blogspot.com.au/2012/02/sccm-2012-deploy-multiple-applications.html

In this method you're using the Base Variable Name on the bottom of the Install Applications step and adding that as a collection variable with numbered suffix. The suffix must start from 01 for Applications or 001 for Packages and it must be unique and sequential. The problem with this method is that there is no way to re-sort your application list should you want to change the order your applications are installed. You'll have the same problem if you need to delete an application from the start or middle of the list. You will basically need to re-do the list when that happens.

3. Adding applications using the Set Dynamic Variables task sequence step.

https://docs.microsoft.com/en-us/sccm/osd/understand/task-sequence-steps#a-namebkmksetdynamicvariablesa-set-dynamic-variables

This is similar to point #2 but instead you use the Set Dynamic Variables to list your applications. It's a little bit more flexible than using collection variables as you can move variables up and down the list but it still has the same numbering rules so you'll need to re-number your variables if changes to applications are made.

Is there a better way?

 

OK, so setting Dynamic Variables is halfway to what we want but the whole sequential numbering system makes the job harder for us deployment technicians. Fortunately the people at Microsoft have given us the magic we need, ZTICoalesce.wsf which is part of the MDT Toolkit. What it does is that it will automatically re-number our applications into a sequential order. Before I go any further, here are the rules:

  1. You must have Windows ADK installed so you can use the MDT integrated task sequence. If you've only had exposure to the default SCCM task sequence then I suggest you try it out.
  2. You must add the Use Toolkit Package task sequence step somewhere before the coalesce step. ZTICoalesce.wsf is part of this package.
  3. Defining the numbered suffix in Applications and Packages is slightly different.
    • Applications will only install if the suffix is 2 numbers. e.g. If APPS is the base variable name then the numbering system is APPS01.
    • Packages will only install if the suffix is 3 numbers. e.g If PACKS is the base variable name then the numbering system is PACK001.
  4. Referencing Applications and Packages in your task sequence (or CustomSettings.ini file) is also different.
    • Applications use the actual Application name. That's all you need to enter.
    • Packages require more detail and it must be entered in particular format. That format is PackageID:NameOfProgram. That might not make much sense right now but I will show an example in Part Two.
Want to see an example? Continued in Part Two.

-- Matt

2 April 2017

Managing BitLocker's PIN - Refresh and Upgrade Scenario


If your organisation uses BitLocker's PIN protectors as part of it's encryption strategy then you'll soon find out that it becomes a small obstacle when you're doing a Refresh or Upgrade deployment. The problem lies in that the default Disable BitLocker step is inadequate for Windows 8.1 and Windows 10 and how those operating systems suspends BitLocker.

In Windows 7, when you suspended BitLocker, it remained in a suspended state until it was re-enabled, either using the command line or GUI. That behaviour has changed in Windows 8.1 (I didn't get to test Windows 8 much so perhaps it started there) and carries over into Windows 10. 

https://technet.microsoft.com/en-us/library/jj649830(v=wps.630).aspx 
https://technet.microsoft.com/en-us/itpro/powershell/windows/bitlocker/suspend-bitlocker

Ignoring the RebootCount parameter for the moment, when BitLocker is suspended, it will automatically re-enable after it's finished the next restart. And this is the underlying issue. The inbuilt Disable BitLocker task does not include a reboot count so BitLocker re-enables on next restart.

In a SCCM Refresh Scenario there will be at least two restarts. The first to restart the computer in WinPE so it can do the pre-installation tasks. The second is after it's finished applying the image. If you have used the in-built task sequence step then the deployment will halt waiting for a PIN every time the computer is restarted from the second restart on.

So what's the solution?

If you search the internet you'll see the mention of using manage-bde.exe to suspend BitLocker. That solution will do the job but you have to specify the drive letter of the volume. Then the question becomes "will that drive letter always stay the same"? The solution I prefer is this little PowerShell script below.

$OSDrive = Get-BitlockerVolume | Where-Object {$_.VolumeType -eq "OperatingSystem"}
$DriveLetter = $OSDrive.MountPoint
Suspend-Bitlocker -Mountpoint $DriveLetter -RebootCount 0

It detects the encrypted operating system drive letter automatically and then suspends BitLocker indefinitely.

All you need to do is create a package in SCCM (or add to an existing package that contains all your scripts). Disable/Remove the inbuilt Disable BitLocker step and add the following Run PowerShell Script step before the computer restarts into WinPe. In the example below, I've placed it in State Capture folder.



I add these couple of rules just to be certain that it will only run if BitLocker is detected.


At the end of the task sequence, I re-enable BitLocker.


A simple yet elegant solution.

-- Matt