Thursday, January 30, 2014

Recently I was really wrestling with getting a set of install commands working for an application I was deploying through SCCM. Because I was using some variables in my command string I needed to "see" what SCCM was ultimately telling the client to run once the application downloaded and the install kicked off. I was able to determine this by logging onto one of my tests clients and navigating to this log:

C:\Windows\CCM\Logs\AppEnforce.log

Sure enough the final command string that was getting executed was not what I expected. I made some adjustments to my install string based on what i saw in the log and got it working. Hope someone else finds this useful.

Friday, January 17, 2014

I've been getting lot of questions on a previous post regarding my approach to software update structure with SCCM. I replied to a few and this generated even more questions so I felt the need to do a more lengthy response about why I do things the way I do them and what led to my approach and that led to this post. I'll start by answering the last question posted there. Yes, I clean
up superseded and expired updates by hand (for now at least) and there are
a few very good reasons why I do it that way. When I was first attempting to
implement software updates with SCCM I feel that my big initial mistake was to
chase after a strategy that focused on "total automation". During my that first approach I literally created an ADR and package for every individual
product that I wanted to patch. The ADRs ran monthly and cleaned out the expired
and superseded stuff automatically. Sounds great right? In practice what I
actually discovered was this approach works great for something simple like a
daily Endpoint Protection update (because in that scenario you really only have
to consider about 3-4 small patches a day tops). You try to do that with all
the security, critical, service pack, etc. updates for multiple Windows
versions going back to say 2003 and you run into several problems.

First you have a *lot* more patches to deal with in your
software update group(s). Every time your SCCM clients kick off a software
update evaluation cycle they have to look through all those updates and
determine if any apply to the device upon which they are running. At a
Microsoft conference last year I learned that this can cause high CPU
utilization on your target machines. Still that’s not too bad because it only
has to run once against the software update group provided the update group doe
not change after that initial run. Ah but there’s the rub, I also learned that
every time the ADR runs it automatically changes the content in your software
update group! Do that every Patch Tuesday and your clients have to once again
parse or scan that update group which (again) can hit your CPUs pretty hard. To
put it in perspective, think about how many times we hear users complain about
"slow computers" in our line of work. You don’t want to introduce
something hat will hammer CPU utilization on your Servers or User PC multiple
times a month.

Second by having a bunch of ADRs (I had a total of 12) that
were constantly changing and updating the content in my software update groups
I discovered I was putting a lot of load on my primary SCCM server in the weeks
following patch Tuesday. The reason there should be obvious as it was
constantly downloading patches and cleaning up software update groups based on
those ADRs. So by chasing total automation I was (in fact) causing lot of
performance issues on both my clients and my servers. Also it really made no
sense to have ADRs that constantly ran against groups with updates that go way
back in the past (they almost never change unless Microsoft expires or
supersedes them). I came to realize that year-based static update groups with a
single monthly ADR were the best choice for dealing with the performance and
organizational issues I was facing. The reason being is I typically only have
to change the older groups once a quarter (sometimes longer).So (usually) I only have to worry about the
updates in my most recent year-based group or my monthly groups (I usually keep
monthly groups up to three months in the past before moving the updates from
the oldest group into a year-based group).

Finally I learned another valuable lesson about the ADRs. No
matter how well you craft your download rules they will inevitably screw
something up. Either they will download something you don't want or remove
something you want to keep. Its much better to have your monthly ADRs
downloading updates into a test group and then (once you've verified what it
downloaded) you can then move the contents of that test group into your static
update group that targets production machines. Coincidentally this solves the
"Expired and Superseded" issue through attrition as it forces you to
do a "monthly visual audit" on your update groups when you open the
console up after patch Tuesday to see what your ADR downloaded. If your static
groups contain superseded or expired updates you'll see that the icon next to
their names has changed to reflect that. At that point its child's play to just
open the group and remove the older updates by editing their membership.

So that’s a pretty big reply to the questions I was being asked and (honestly)
a lot of it is just what I’ve discovered through using SCCM 2012 in the past
year. There may be a better way to do it, but this one works for me. I really
struggled a lot with this at first and I hope I'm posting this big response in an effort to help others avoid some of my own pain. SCCM is a really complicated animal and I just think its a bad idea to go into it "set it and forget it approach". If it were really that easy we wouldn't need SCCM admins right? The main point I’d like to get across though is sometimes a 100%
automated solution just doesn't make sense. SCCM can automate a lot of
things for you but even with the advent of the autopilot feature on an airplane we still need pilots at
the helm. Focus on design paradigms that automate the most time consuming, tedious or repetitive steps. Then if you find yourself still stuck with a
manual step, try to make it something you can do very quickly (like at the
touch of a button). I hope that makes sense and that others find it helpful. If there are any counterpoints to this philosophy or if anyone just has better ways of approaching this I'd love to hear about it in the comments section.

UPDATE: Someone requested a screenshot of my SUGs. I've added it below. Like I said we roll about 2-3 months in the past on our monthly deltas and once we achieve around 90% I move those to a year-based group. I've highlighted the delta and year-based groups in the screenshot. The other groups listed there are "special case" groups:

Friday, January 10, 2014

I recently needed to set some conditions in my MDT CustomSettings.ini file to pre-check certain applications during an image deployment. Those of you that have used this feature know that you can get the GUID from any application in MDT by right-clicking it within the MDT Workbench view and choosing properties. The GUID appears at the bottom of the window that opens and it can then be copied and pasted into then CustomSettings.ini like so:

Applications001={GUID1}Applications002={GUID2}

Thats fine and dandy, but what are the limitations of this process? What syntax is permissible? I won't go into the details but some recent issuues froece me to ask those quetions. Here's the answer I got from Keith Garner on the MDT Technet forums:

Numbers may be between 1 and 999

You can start at any number within the CS.ini *HOWEVER* when reading the list, MDT will always start at 1, and if it comes across any missing number it will ignore the rest. So if you inputted Var10, without using Var1 through Var9, then Var10 might as well not existed.

You may choose to *not* prefix a zero to the start, or you may choose to prefix some zeros, as long as the number is 3 digits long, like: 001, 010, 100.

Valid:Applications1=GUIDApplications10=GUIDApplications010=GUID

Not Valid:Applications01=GUIDApplications0001=GUID

I did some testing on my own and (as expected) these rules also apply to MandatoryApplications, WMU_EXCLUDEID and WMU_EXCLUDEKB. All good info to know if you are customizing these settings in CustomSettings.ini!