Reading Task Sequence Variables in WinPE

Now and then you may have a need to read a task sequence variable during the OSD process. Today was one of those days. I had just modified a step in my task sequence and used the variable %OSDisk%. Well, the task failed. So……I put a pause in the task sequence and used PowerShell to find the variable. Turns out, there isn’t an OSDisk variable once the OS is dropped.

To see the variables and their values:

· Your WinPE boot image needs to have PowerShell on it

· In WinPE hit F8 to open a command prompt

· Type PowerShell to….well, you know, open PowerShell!!

$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment

Foreach ($i in $TSEnv.GetVariables()) {“$i” + ‘ = ‘ + $TSEnv.Value(“$i”) | Out-File FilePath X:\Windows\Temp\SMSTSlog\TSVar.log –append}

At this point you can use CMTrace to open and view the file.

If you just want to see the value of one TS Variable: $TSEnv.Value(“OSDTargetSystemDrive”) for example.

Notes: The log file created has a ton of duplicate variables and values. Not sure why, and really don’t care either!! All I wanted to do was find the value for where the Operating System is. I have no idea if I will ever need to query TS Variables again, but good to know that I can!

Windows 10 Servicing

What is servicing

Windows as a service was introduced with the release of Windows 10. It seems that every time a product is released ‘as a service’ people get excited. Disaster Recovery as a service. Beer as a service. But what does it mean?

There are a few concepts that we need to learn regarding Windows as a service.

Feature Updates – These are released twice per year around March and September to coincide with Office and ConfigMgr releases. For example: Windows 10 1511, 1607, 1703. These add new features to the operating system. In the past we would have to wait for a service pack or an entirely new operating system to be delivered to meet the business needs.

Quality Updates – These are released at least monthly and are cumulative. When people ask me if they need to apply last month’s cumulative update before this months I tell them to look up the word cumulative! As the name implies, these updates grow bigger each month. The updates include both security fixes and non-security fixes. (Note: If you have Windows 10 1607 CU April 2017 or Windows 1703 you can deliver what are called express updates. These are just the differentials from the last cumulative update.

https://docs.microsoft.com/en-us/sccm/sum/deploy-use/manage-express-installation-files-for-windows-10-updates

Insider Preview – These are builds that are not production ready. They give systems administrators a chance to preview and test in their environment. You should have a small subset of your computers in the preview ring, and if you can get a small group of users outside of IT to join the fun on a secondary PC, it would be helpful.

Service Branches – These allow organizations to choose when to deploy the newest features of the newest build. The newest build will be called CB or Current Branch. You might want to deploy this build to your testing area and your IT Department and a few candidates from other business units on secondary machines. Next is CBB or Current Branch for Business. A CB build will turn into CBB after four months. For example: Windows 1703 is the CB as of March 2017. Around July of 2017 Windows 1703 will be CBB. Basically CB + 4months = CBB. Then there is LTSB – Long Term Service Branch. This is used to provide support for critical machines that can’t upgrade to CB or CBB anytime soon.

Microsoft will support the CB builds for exactly 18 months after they are released

The release cadence is this:

Engineering Builds – 1,000’s of machines

Microsoft Internal Validation – 100,00’s of machines

Microsoft Insider Preview – 1,000,000’s of machines

The above process repeats for six months. At that time it is released as Current Branch

After four months of Current Branch it is then declared as CBB.

Rinse and repeat.

There will always be two builds that are CBB. Example:

· 1507 went through insider preview and entered CB in July 2015.

· 1511 CB was released a bit after 1507 entered CBB

· 1607 CB was ready for CBB in November 0f 2016. That starts the countdown for 1507 60 day grace period.

Jason Sandys MVP has a great post about what CB and CBB are:

http://home.configmgrftw.com/windows-10-servicing-configmgr-confusion/

clip_image002[8]

Still not getting it?

CB = Current Branch
CBB = Current Branch for Business
CBBJOVLTCVCBB = Current Branch for Business Just One Version Lower Than Current Version Current Branch for Business

NMPFTV = No More Patches For This Version
m = months
WWCBB = What Was Current Branch for Business
v = version

CB + 4m = CBB

CBB – 1v = CBBJOVLTCVCBB

CBB – 2v = WWCBB

WWCBB + 4m = NMPFTV

But wait…there’s more! Microsoft is changing the name from Current Branch to Semi-Annual Branch.

Monthly Channel = CB

Semi-Annual Channel = CBB

So, our new formulas look like this:

MC + 4m = SAC

SAC -1v = SACJOVLTCVSAC

SAC- 2v = WWSAC

WWSAC + 4m = NMPFTV

Why?

Did you enjoy troubleshooting Windows 7 patches and trying to figure out what patches to install and what patches to not install? Most organizations took a selective approach to software updates. This could result in newer updates not working since Microsoft tests all of their updates on a fully patched machine. Think of disk fragmentation. An optimized disk doesn’t have any fragmentation. That would be similar to a fully patched machine.

With Windows as a Service Microsoft is ensuring that you can stay up to date with the latest features and security updates while maintaining consistency and reliability.

More reading:

https://docs.microsoft.com/en-us/windows/deployment/update/waas-quick-start

Much more reading:

https://docs.microsoft.com/en-us/windows/deployment/update/waas-overview

Don’t like reading?

https://channel9.msdn.com/events/speakers/Michael-Niehaus

http://aka.ms/W10-1703-resources

Initial Setup

Make sure you have checked ‘Upgrades’ in the Software Update Point Component Properties in SCCM. If you are running Server 2012 R2 you will need a hotfix. The hotfix is listed in a prompt when you select Upgrades. If you’re using Server 2016, you still get this prompt, but you can safely ignore it.

clip_image004[6]

You can check the success of the upgrades synchronization by looking in SCCM > Software Library > Windows 10 Servicing > All Windows 10 Updates

clip_image006[6]

If this node is empty you will want to start troubleshooting by looking at the Wsyncmgr.log file. Troubleshooting is beyond the scope of this document.

Create Target Collection(s)

In this document we will be upgrading to the latest Windows 10 branch which is 1703.

Create a collection called “Windows 10 – Upgrade to CB” with the following WQL statement:

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,
SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,
SMS_R_SYSTEM.Client
from SMS_R_System
where SMS_R_System.OperatingSystemNameandVersion
     like “Microsoft Windows NT Workstation 10.0%” and SMS_R_System.Build < “10.0.15063”

You may want to create another collection for the current branch machines called “Windows 10 – CB” with the following WQL statement

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,
SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,
SMS_R_SYSTEM.Client
from SMS_R_System
where SMS_R_System.OperatingSystemNameandVersion
     like “Microsoft Windows NT Workstation 10.0%” and SMS_R_System.Build = “10.0.15063”

As you can see, these collections can be adjusted for the next Windows 10 branch release quite easily.

Here is a link to the Windows 10 build numbers:

https://technet.microsoft.com/en-us/windows/release-info.aspx

Upgrading to Current Branch

SCCM provides us with two different ways to deploy the latest Windows 10 branch. One is through the Servicing Plans type deployment. The other is deployment via Task Sequence. We will look at both ways below.

Windows 10 Servicing

In the SCCM console go to Software Library and expand Windows 10 Servicing.

Right click Servicing Plans and select Create Servicing Plan

Provide a name for the Servicing Plan

clip_image008[6]

Provide a target collection.

clip_image010[6]

Select the deployment ring that applies to you.

clip_image012[6]

Select the property filters for the deployment.

clip_image014[6]

Configure a schedule for the deployment

In this example the deployment is made available right away and will become mandatory in six months.

clip_image016[6]

Configure the end user experience

clip_image018[6]

Create or select a deployment package

clip_image020[6]

Finish creating the plan. During this time the updates will be downloaded.

In this example we will upgrade a Windows 10 1511 machine to 1607 using SCCM Servicing. Deploying the update via servicing puts the deployment in the Updates node in the Software Center

clip_image022[6]

Here used to be the maddening thing about Windows 10 Servicing via ConfigMgr prior to ConfigMgr 1702. Let’s see what happens if we just select the Feature Update to Windows 10 Pro, version 1607, en-us. When we do this, we are brought to a different screen.

clip_image024[6]

Now, let’s select Install…and….oh sweet Jesus….look at that message! “When you install a new operating system, all the existing data on your computer will be removed.” This is not a very good message for your end users!! Those who read it will panic and hit the cancel button and perhaps call the service desk. The message is incorrect. All we are doing is upgrading the operating system and that is all that will happen when “install operating system” is clicked.

clip_image026[6]

Now would be a good time to introduce you to ConfigMgr UserVoice. https://configurationmanager.uservoice.com You can vote or submit requests for chagnes in ConfigMgr. As a result, we now have a MUCH better dialog box (see below) due to this: https://configurationmanager.uservoice.com/forums/300492-ideas/suggestions/8469997-make-all-dialogs-shown-to-the-end-user-customizabl

In ConfigMgr 1702 the message is so much nice. Perhaps, it is even shinny:

clip_image028[6]

Task Sequence

The other way to deploy the latest Windows 10 branch is to use a task sequence. The big benefit of this method is that you can add other items to the sequence, such as a cumulative updates, pre-flight checks, drivers, and custom messages

Copy your Windows 10 media to a folder. In SCCM go to Software Library > Operating Systems. Right click on Operating System Upgrade Package and point to the directory where you copied the Windows 10 media. Distribute to your DP’s

We will also want to create a package for the latest Cumulative Update. Go to this link and find the latest CU. https://support.microsoft.com/en-us/help/4000825/windows-10-update-history

For Windows 10 1607:

As of this writing the latest CU is KB4015217. But, for Windows 10 1607 there is a Service Stack update released that needs to be applied first. Be sure to read the requirements for the KB articles! If you look at KB3206632 you will see that there is a prerequisite of KB3199986.

Start with the Servicing stack KB3199986

I like to put the link to the CU’s into the package comments. Also, I put the KB article under version. You will need to update this package if another Servicing Stack update comes out.

clip_image030[6]

The program will look like this: wusa.exe windows10.0-kb3199986-x64_5d4678c30de2de2bd7475073b061d0b3b2e5c3be.msu /quiet /norestart

Note: You will need to update the program with the latest CU each time you update the package.

Now it’s time to create the package for the latest Windows 10 1607 CU KB4015217

clip_image032[6]

The program will look like this: wusa.exe windows10.0-kb4015217-x64_60bfcc7b365f9ab40608e2fb96bc2be8229bc319.msu /quiet /norestart

Note: You will need to update the program with the latest CU each time you update the package.

In SCCM navigate to Software Library > Operating Systems

Right click Task Sequences and select ‘Upgrade an Operating System from an Upgrade Package’

clip_image034[6]

Provide a name. I called mine “Upgrade to Windows 10 1607”

Select the Upgrade Package and Windows Edition if applicable

For the ‘Include Updates’ screen I select ‘Required for installation – mandatory updates’

Select any applications you want to install and finish the Task Sequence

Now, right click the Task Sequence and select Edit

Add the Windows 10 Servicing Stack and Cu packages before the Install updates task.

Your Task Sequence should look something like this:

clip_image036[6]

The next thing is to deploy the Task Sequence to a collection

Your end users will be prompted that there is new software to install.

In the Software Center they will select Operating Systems and then select the Task Sequence you just deployed.

clip_image038[6]

clip_image040[6]

Prior to ConfigMgr 1702 your users will see the following message once they click on install.

clip_image042[6]

Again, this wording is completely wrong. The existing data on the machine will remain intact.

Once you are at ConfigMgr 1702 your users will see this:

clip_image044[6]

But, wait….there is more!!! In ConfigMgr 1702 you can customize the message your end users receive during task sequences.

Open the properties of a task sequence and select the User Notification tab

clip_image046[6]

This is how it will look for your end users:

clip_image048[6]

Task Sequence Options

As you can see, Task Sequences offer a lot more flexibility than servicing. There is much more that can be done.

Compatibility Scan

clip_image050[6]

Pre Flight Check

There are several things to check for before upgrading the Operating System. Below are a few, however, in every environment is different. If the task sequence fails, investigate the failure and add a new check in the ‘pre flight’ check group to address the failure.

Troy Martin @TroyMartinNet has a great post on creating OSD Preflight checks.  https://www.1e.com/blogs/2014/10/07/including-pre-flight-checks-in-your-ultimate-task-sequence-2/

Here I will simplify (hopefully) some of the highlights of his post:

  • Restart Computer – Is User Logged-Off
    • Add a Restart Computer task with the following options
      • If NONE of the conditions are true – WQL select __relpath from win32_process where caption = ‘explorer.exe’

  • Restart Computer – Is User Logged-On
    • Add a Restart Computer task with the following options
      • WQL select __relpath from win32_process where caption = ‘explorer.exe’

  • Set Pre-Flight Check Variable
    • Add a Set Task Sequence Variable step
      • Task Sequence Variable: PreFlightCheck
      • Value: PASSED

  • Check to see if the machine is connected to a wired network
    • Create a new folder called ‘Check if connected to wired network’
      • Options: Task Sequence Variable PreFlightCheck equals PASSED
    • Add a Set Task Sequence variable with the following properties and options.

clip_image052[6]

    • WMI Query
      • Namespace: Root\CIMV2
      • WQL: Select * from Win32_NetworkAdapter WHERE NetConnectionId like ‘%Ethernet%’ AND AdapterType LIKE ‘%ethernet%’ AND NetConnectionStatus=2 and NOT Name like ‘%virtual%’
    • Add a Set Task Sequence variable with the following
      • Properties
        • Task Sequence Variable Name: PreFlightCheckIsOnWired
        • Value: FAILED
      • Options
        • Variable IsOnWired exists
        • Variable IsOnWired not equals TRUE
      • Add a Set Task Sequence variable with the following
        • Properties
          • Task Sequence Variable Name: PreFlightCheck
          • Value: FAILED

Checks to see if USB drives are connected

  • Create a new folder called ‘Check if USB drive is connected to computer’
    • Options: Task Sequence Variable PreFlightCheck equals PASSED
    • Add a Set Task Sequence variable with the following properties and options.

clip_image054[6]

      • WMI Query
        • Namespace: Root\CIMV2
        • WQL: Select * from Win32_DiskDrive WHERE MediaType=’External Hard Disk Media’
      • Add a Set Task Sequence variable with the following
        • Properties
          • Task Sequence Variable Name: PreFlightCheckIsUSBDriveAttached
          • Value: FAILED
        • Options
          • Variable IsUSBDriveAttached exists
          • Variable IsUSBDriveAttached equals TRUE
      • Add a Set Task Sequence variable with the following
        • Properties
          • Task Sequence Variable Name: PreFlightCheck
          • Value: FAILED

  • Checks to see if computer is running on battery
    • Create a new folder called ‘Check if computer is running on battery’
      • Options: Task Sequence Variable PreFlightCheck equals PASSED
      • Options: WMI Query: Select * from Win32_Battery where Batterystatus > 0
    • Add a Set Task Sequence variable with the following properties and options.

clip_image056[6]

    • WMI Query
      • Namespace: Root\WMI
      • WQL: Select * from BatteryStatus where PowerOnline = ‘False’
    • Add a Set Task Sequence variable with the following
      • Properties
        • Task Sequence Variable Name: PreFlightCheckIsOnBattery
        • Value: FAILED
      • Options
        • Variable IsOnBattery exists
        • Variable IsOnBattery equals TRUE
    • Add a Set Task Sequence variable with the following
      • Properties
        • Task Sequence Variable Name: PreFlightCheck
        • Value: FAILED

In the Check Readiness or Upgrade the Operating System steps make sure to put a condition that the PreFlightCheck = Passed.

clip_image058[6]

Troubleshooting

Your best bet for success in troubleshooting is understanding both how the process works, and where to look when things go wrong.

Windows Servicing Troubleshooting

Here’s an example of the Scan process and logs to check

Client SW Update Scan Process/Issues

1. The client sends a WSUS Location Request to the management point

2. Scan agent requests the scan and WUAHandler initiates the scan

3. Windows Update Agent (WUA) starts the scan against the WSUS computer

4. WUAHandler receives results from Windows Update Agent and marks the scan as complete

5. WUAHandler parses the scan results

6. Update Store records the status and raises a state message for each update in WMI

7. State messages are sent to the management point

Logs for this step:

Scanagent.log

LocationServices.log

CCMMessaging.log

MP_Location.log

WUAHandler.log

WindowsUpdate.log

UpdateStore.log

StateMessage.log

Logs to check

Server Side

SUPSetup.log

WCM.log

WUSSyncXML.log

objreplmgr.log

ruleengine.log

WSUSCtrl.log

PatchDownloader.log

wsyncmgr.log

WUSSyncXML.log

MP_Location.log

Client Side

ScanAgent.log

LocationServices.log

CCMMessaging.log

WindowsUpdate.log

WUAHandler.log

UpdatesStore.log

StateMessage.log

PolicyEvaluator.log

RebootCoordinator.log

UpdatesHandler.log

ServiceWindowManager.log

UpdatesDeployment.log

SmsWusHandler.log

ccmperf.log

Questions about these log files can be answered by going to this link:

https://docs.microsoft.com/en-us/sccm/core/plan-design/hierarchy/log-files

Here’s a troubleshooter that you can walk through if you’re using the Servicing (non-task sequence) approach. It’s the same as troubleshooting software updates.

https://support.microsoft.com/en-us/help/10680/software-update-management-troubleshooting-in-configuration-manager

As you can see, the troubleshooting for Servicing is pretty much the same as for Software Updates.

Task Sequence Troubleshooting

If you’re doing Task Sequence model, you’ll check your task sequence log files the same way that you would for OS Deployment, however you can get information about what went wrong during setup by checking the following directories on the client:

$Windows.~BT\Sources\Panther\setupact.log

$Windows.~BT\Sources\Rollback\setupact.log

Windows\Panther\Unattend\GC

Windows\Panther

Why setup logs to these locations, details about each step, and reading the logs/error codes are beyond the scope of this session. Just know that what you get from task sequence logs may not be enough to determine what went wrong and how to fix it.

SCCM with SSL….this can sometimes be a bit tricky!

If you follow the guide for creating and deploying certificates you may run into an issue with the SCCM Reporting Point piece of the picture.

https://technet.microsoft.com/en-us/library/gg682023.aspx

When creating the ConfigMgr Web Server Certificate make sure you create a Common Name using the site servers FQDN.  If you do not do this, you will be able to see the cert in IIS, but not when you configure SSRS for SSL.

 

SCCM Software updates automation

Software Updates synchronize daily at 14:00

Software updates classifications:

  • Select the Classifications you want SCCM WSUS to synchronize
  • Select the Products you want SCCM WSUS to synchronize

 

  • Create collections for Software Updates
    • Device Collections > Workstation Clients > Software Updates

All collections are based off of the All Workstation Clients collection

  • Software Updates Workstation – Monday
    • SCCM Resource ID %0 or %1
      • Maintenance Window – Software Updates only – 19:00-07:00
  • Software Updates Workstation – Tuesday
    • SCCM Resource ID %2 or %3
      • Maintenance Window – Software Updates only – 19:00-07:00
  • Software Updates Workstation – Wednesday
    • SCCM Resource ID %4 or %5
      • Maintenance Window – Software Updates only – 19:00-07:00
  • Software Updates Workstation – Thursday
    • SCCM Resource ID %6 or %7
      • Maintenance Window – Software Updates only – 19:00-07:00
  • Software Updates Workstation – Friday
    • SCCM Resource ID %8 or %9
      • Maintenance Window – Software Updates only – 19:00-07:00

Created saved searches in the Software Updates > All Software Updates node

All saved searches have the following rules

  • Expired = No
  • Metadata Only = No
  • Superseded = No
  • Severity = Critical or Important
  • Update Classification = Critical or Security
  • Title = does not contain Itanium
    • 2000 – 2010 – Critical and Important
    • 2011 – Critical and Important
    • 2012 – Critical and Important
    • 2013 – Critical and Important
    • 2014 – Critical and Important
    • 2015 – Critical and Important

Created saved searches in the Software Updates > All Software Updates node

All saved searches have the following rules

  • Expired = No
  • Metadata Only = No
  • Superseded = No
  • Severity = Critical or Important
  • Update Classification = Critical or Security
  • Title = does not contain Itanium
  • Required >= 1
  • Deployed = NO
    • 2000 – 2010 – Critical and Important – Required Not Deployed
    • 2011 – Critical and Important – Required Not Deployed
    • 2012 – Critical and Important – Required Not Deployed
    • 2013 – Critical and Important – Required Not Deployed
    • 2014 – Critical and Important – Required Not Deployed
    • 2015 – Critical and Important – Required Not Deployed

Created saved search in Software updates > All Software updates node

Endpoint Protection

  • Expired = No
  • Metadata Only = No
  • Superseded = No
  • Product = Forefront Endpoint Protection 2010

Created Deployment Packages for Software Updates

  • 2000 – 2010 – Critical or Important
  • 2011 – Critical and Important
  • 2012 – Critical and Important
  • 2013 – Critical and Important
  • 2014 – Critical and Important
  • 2015 – Critical and Important

Created Automatic Update Rule

  • Workstations – 2015 – Critical or Important – ADR

This rule will create a new software update group each time it is run

At the end of 2015 there should be 12 software update groups for this rule

The rule once on the 2nd Tuesday of each month at 17:00

This rule targets the BETA workstations collection

  • Date released or revised = Last month
  • Severity = Critical or Important
  • Superseded = No
  • Update Classification = Critical or Security

Created Automatic Update Rule

  • Endpoint Protection – ADR

This rule will add to an existing software update group each time it is run

The rule runs after every Software Update Synchronization

  • Product = Forefront Endpoint Protection 2010
  • Superseded = no

Created Software Update Groups based on the above saved searches

  • 2000-2010 – Critical or Important
  • 2011 – Critical or Important
  • 2012 – Critical or Important
  • 2013 – Critical or Important
  • 2014 – Critical or Important
  • 2015 – Critical or Important 2015-01-13
  • 2015 – Critical or Important 2015-02-10

Created PowerShell script to automate software updates process

The process for Software Updates is as follows:

  • All Software Updates will be deployed to the Device Collection > Departments > All Workstation Clients – BETA
  • All Software Updates will be deployed to the Device Collection > Workstation Clients > All Workstation Clients collection for PRODUCTION pushes

The following SQL Agent jobs need to be created

2nd Tuesday of the Month

        • 14:0
        • SQL Server Agent job “Set-CMSoftwareUpdatesDeploymnet -Beta -EnableMaintenanceWindows” runs as a domain account SQL server agent PowerShell proxie
          • This sets all of the Software Update Group deployments to the BETA collection and instructs the deployment to respect maintenance windows
        • 14:00
          • Software Update Point Synchronization runs (daily)
          • 14:00 + [however long it takes the synchronization process to run] – Automatic Deployment Rule “Workstations – 2015 – Critical or Important – ADR” runs
            • This will create a new Software Update Group deployed to the BETA collection that respect Maintenance Window

3rd Tuesday of the Month

      • 18:00
      • SQL Server Agent job “Set-CMSoftwareUpdatesDeploymnet -Production -EnableMaintenanceWindows” runs as a domain account SQL server agent PowerShell proxi
        • This sets all of the Software Updates Group deployments to “All Workstation Clients” collection and instructs to deployment to respect maintenance windows

1st Tuesday of the Month

    • 18:00
      • SQL Server Agent job “Set-CMSoftwareUpdatesDeploymnet -Production -DisableMaintenanceWindows” runs as a domain account SQL server agent PowerShell proxie
        • This sets all of the Software Updates Group deployments to “All Workstation Clients” collection and instructs to deployment to ignore maintenance windows

2nd Tuesday of the month

    • 17:00
      • SQL Server agent job “Start-CleanCMSoftwareUpdateGroup” runs as a domain account SQL server agent PowerShell proxie
      • This script calls scripts on the SQL server
        • This scripts cleans out Expired and Superseded updates from all Update Groups and Packages except for Endpoint protection update groups and packages.
          • NOTE: The script doesn’t work with Endpoint protection updates.

 

[CmdletBinding()]
Param
    (
    [Switch]$Beta, # This switch will target the software updates to the Beta collection,
    [Switch]$Production, #This switch will target the software updates to the Production collection
    [Switch]$EnableMaintenanceWindows, #This switch will cause the deployment to respect a clients maintenance windows
    [Switch]$DisableMaintenanceWindows, #This switch will cause the deployment to over-ride a clients maintenance windows
    [Parameter(Mandatory=$True, Position=1)]
        [string]$SCCM_Server #This parameter is the NETBios or FQDN of the SCCM Site Server
    )
    
    $BetaCollectionName = "BETA"
    $ProductionCollectionName = "All Workstation Clients"

    #$BetaCollectionName = "Beta"
    #$ProductionCollectionName = "Production"

    $PSVersion = $host.Version.Major
    Write-Verbose "PowerShell version is : $PSVersion"

    Write-Verbose "Determining SiteCode for Site Server: '$($SCCM_Server)'"

    If ($PSVersion -ge 3)
        {
        $SCCM_CimSession = New-CimSession -ComputerName $SCCM_Server
        $SiteCodeObjects = Get-CimInstance -CimSession $SCCM_CimSession -Namespace "root\SMS" -Class SMS_ProviderLocation -ErrorAction Stop
        }
    Else
        {
        $SiteCodeObjects = Get-WmiObject -ComputerName $SCCM_Server -Namespace "root\SMS" -Class SMS_ProviderLocation -ErrorAction Stop
        }

    foreach ($SiteCodeObject in $SiteCodeObjects) 
        {
        if ($SiteCodeObject.ProviderForLocalSite -eq $true) 
            {
            $SCCM_SiteCode = $SiteCodeObject.SiteCode
            Write-Verbose "SiteCode: $($SCCM_SiteCode)"
            }
        }

    If ($EnableMaintenanceWindows)
        {
        $RebootOutsideOfServiceWindows = $FALSE
        $OverrideServiceWindows = $FALSE
        Write-Verbose "RebootOutsideOfServiceWindows = $RebootOutsideOfServiceWindows"
        Write-Verbose "OverrideServiceWindows = $OverrideServiceWindows"
        }
    If ($DisableMaintenanceWindows)
        {
        $RebootOutsideOfServiceWindows = $TRUE
        $OverrideServiceWindows = $TRUE
        Write-Verbose "RebootOutsideOfServiceWindows = $RebootOutsideOfServiceWindows"
        Write-Verbose "OverrideServiceWindows = $OverrideServiceWindows"
        }
    If ($Beta)
        {
        If ($PSVersion -ge 3)
            {
            $BetaCollectionID = Get-CimInstance -CimSession $SCCM_CimSession -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_Collection where name = '$($BetaCollectionName)'"
            }
        else
            {
            $BetaCollectionID = Get-WmiObject -computername $SCCM_Server -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_Collection where name = '$($BetaCollectionName)'"
            }
        $TargetCollectionID = $BetaCollectionID.CollectionID
        Write-Verbose "Beta collection name = $($BetaCollectionID.name) and collectionID = $($BetaCollectionID.CollectionID)"
        Write-Verbose "TargetCollectionID = $TargetCollectionID"
        }
    If ($Production)
        {
        If ($PSVersion -ge 3)
            {
            $ProductionCollectionID = Get-CimInstance -CimSession $SCCM_CimSession -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_Collection where name = '$($ProductionCollectionName)'"
            }
        Else
            {
            $ProductionCollectionID = Get-WmiObject -computername $SCCM_Server -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_Collection where name = '$($ProductionCollectionName)'"
            }
        $TargetCollectionID = $ProductionCollectionID.CollectionID
        Write-Verbose "Production collection name = $($ProductionCollectionID.name)  and collectionID = $($ProductionCollectionID.CollectionID)"
        Write-Verbose "TargetCollectionID = $TargetCollectionID"
        }    
    
    If ($PSVersion -ge 3)
        {
        $SMS_UpdateGroupAssignment = Get-CimInstance -CimSession $SCCM_CimSession -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_UpdateGroupAssignment"
        }
    Else
        {
        $SMS_UpdateGroupAssignment = Get-WmiObject -ComputerName $SCCM_Server -Namespace "ROOT\SMS\Site_$($SCCM_SiteCode)" -Query "Select * from SMS_UpdateGroupAssignment"
        }
    $SoftwareUpdateDeployents = $SMS_UpdateGroupAssignment | where {$_.AssignmentName -notlike "*Endpoint*" -and $_.AssignmentName -like "*Workstation*"}
    Foreach ($Deployment in $SoftwareUpdateDeployents)
        {
        Write-Verbose $Deployment.AssignmentName
        If ($RebootOutsideOfServiceWindows -ne $NULL -and  $OverrideServiceWindows -ne $NULL)
            {
            $Deployment.RebootOutsideOfServiceWindows = $RebootOutsideOfServiceWindows
            $Deployment.OverrideServiceWindows = $OverrideServiceWindows

            If ($PSVersion -ge 3)
                {
                Set-CimInstance -CimSession $SCCM_CimSession -CimInstance $Deployment -OperationTimeoutSec 60
                }
            Else
                {                      
                $Deployment.put()
                }
            Write-Verbose "$($Deployment.AssignmentName) RebootOutsideOfServiceWindows is set to $($Deployment.RebootOutsideOfServiceWindows)"
            Write-Verbose "$($Deployment.AssignmentName) OverrideServiceWindows is set to $($Deployment.OverrideServiceWindows)"
            }
        If ($ProductionCollectionID -or $BetaCollectionID)
           {
           $Deployment.TargetCollectionID = $TargetCollectionID
           If ($PSVersion -ge 3)
               {
               Set-CimInstance -CimSession $SCCM_CimSession -CimInstance $Deployment -OperationTimeoutSec 60
               }
            Else
                {
                $Deployment.put()
                }
            Write-Verbose "$($Deployment.AssignmentName) target collectionID is set to $($Deployment.TargetCollectionID)"
            }
        }

SCCM–WSUS Maintenance

http://blog.coretech.dk/kea/house-of-cardsthe-configmgr-software-update-point-and-wsus/

Increased the Private Memory Limit (KB) to 6291456 (6GB) on the WSUS Server

  • Open IIS
  • Select Application Pools
  • Right click the WSUS app pool and select Advanced Settings
  • Find the Private Memory Limit (KB) setting and adjust.
    • Example:  Your server has 8GB.  You might want to provide a memory limit of 5GB on the WSUS App Pool.
      • Open Powershell
      • Type:  5GB / 1KB
      • Copy the answer into the Private Memory Limit (KB) setting
    • Right click the App Pool and select recycle

Ensure that the WSUS database is being indexed.  See the foloowing post:  https://emptygarden.info/2015/05/10/sql-maintenance-with-olas-script/

Create a new SQL Server Agent job to cleanup the WSUS server.  This job will be a powershell script.  So, we will need to create a SQL server credential to accomplish this.

  • Create SQL Server Credntial
    • Open SQL Server Management Studio
    • Expand Security
    • Right click on Credentials
      • Enter in a credential that has rights to run the PowerShell command below
  • Map the SQL Server Credential to a SQL Server Agent Proxy
    • In SQL Server Management Studio expand SQL Server Agent
    • Right click Proxies
    • Select New Proxie
    • use the credential you created above and map it to a PowerShell command

 

Create a new SQL Server Agent job that runs a PowerShell script using the above Proxie.

Enter the following as the PowerShell command

PowerShell.exe -command “invoke-command –computername [SCCM WSUS server] -scriptblock {Get-WsusServer | Invoke-WsusServerCleanup –CleanupObsoleteUpdates -CleanupUnneededContentFiles -CompressUpdates -DeclineExpiredUpdates -DeclineSupersededUpdates}”

Have the SQL Server Agent job save the results to a text file.

Runs Daily at 22:30

SQL maintenance with Ola’s script

Steve Thompson (MVP) has an excellent blog describing how to implement SQL maintenance scripts for SCCM.  https://stevethompsonmvp.wordpress.com/2013/05/07/optimizing-configmgr-databases/

As you know, there is a a SCCM Site Maintenance job titled Rebuild Indexes.  Steve Thompson goes into some detail on his blog about why this doesn’t work…..at all!!

Enter:  Ola Hallengren SQL scripts:   https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html

Basically:

  • Create a database and table to track the results of the indexing / statistics process
		-- USE [master]
		GO
		
		IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'CMMonitor')
		DROP DATABASE [CMMonitor]
		GO
		
		-- USE [master]
		GO
		
		-- CREATE DATABASE [CMMonitor] ON  PRIMARY 
		( NAME = N'CMMonitor', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\CMMonitor.mdf' , SIZE = 10240KB , MAXSIZE = UNLIMITED, FILEGROWTH = 10240KB )
		 LOG ON 
		( NAME = N'CMMonitor_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\CMMonitor_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 5120KB )
		GO
		
		ALTER DATABASE [CMMonitor] SET COMPATIBILITY_LEVEL = 100
		GO
		
		IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
		begin
		EXEC [CMMonitor].[dbo].[sp_fulltext_database] @action = 'enable'
		end
		GO
		
		ALTER DATABASE [CMMonitor] SET ANSI_NULL_DEFAULT OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET ANSI_NULLS OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET ANSI_PADDING OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET ANSI_WARNINGS OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET ARITHABORT OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET AUTO_CLOSE OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET AUTO_CREATE_STATISTICS ON 
		GO
		
		ALTER DATABASE [CMMonitor] SET AUTO_SHRINK OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET AUTO_UPDATE_STATISTICS ON 
		GO
		
		ALTER DATABASE [CMMonitor] SET CURSOR_CLOSE_ON_COMMIT OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET CURSOR_DEFAULT  GLOBAL 
		GO
		
		ALTER DATABASE [CMMonitor] SET CONCAT_NULL_YIELDS_NULL OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET NUMERIC_ROUNDABORT OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET QUOTED_IDENTIFIER OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET RECURSIVE_TRIGGERS OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET  DISABLE_BROKER 
		GO
		
		ALTER DATABASE [CMMonitor] SET AUTO_UPDATE_STATISTICS_ASYNC OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET DATE_CORRELATION_OPTIMIZATION OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET TRUSTWORTHY OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET ALLOW_SNAPSHOT_ISOLATION OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET PARAMETERIZATION SIMPLE 
		GO
		
		ALTER DATABASE [CMMonitor] SET READ_COMMITTED_SNAPSHOT OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET HONOR_BROKER_PRIORITY OFF 
		GO
		
		ALTER DATABASE [CMMonitor] SET  READ_WRITE 
		GO
		
		ALTER DATABASE [CMMonitor] SET RECOVERY SIMPLE 
		GO
		
		ALTER DATABASE [CMMonitor] SET  MULTI_-- USER 
		GO
		
		ALTER DATABASE [CMMonitor] SET PAGE_VERIFY CHECKSUM  
		GO
		
		ALTER DATABASE [CMMonitor] SET DB_CHAINING OFF 
		GO
  • Download the ‘MaintenanceSolution.sql’ script from here: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
    • Change the — USE [Master] line to — USE [CMMonitor]
  • Optional:  Delete the following SQL Agent Jobs that were created using the above script
    • All Backup jobs
    • Output File Cleanup job
    • SP_Delete_backuphisorty job
    • Syspolicy_purge_history job
  • Schedule the CommandLog Cleanup job
    • Weekly – Sunday – 21:00
  • Schedule the DatabaseIntegrityCheck – System Databases job
    • Daily at 22:00
  • Schedule the DatabaseIntegrityCheck – User databases job
    • Daily at 22:00
  • Edit the IndexOptimize – User_Databases job
    • Rename the Step 1 to “IndexOptimize – CM_[SITE CODE] and SUSDB”
    • Modify the step to be a T-SQL type
    • Edit the comand:
EXECUTE dbo.IndexOptimize

@Databases = "CM_[SCCM SITE CODE], SUSDB",

@FragmentationLow = NULL,

@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',

@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',

@FragmentationLevel1 = 10,

@FragmentationLevel2 = 40,

@UpdateStatistics = 'ALL',

@OnlyModifiedStatistics = 'Y',

--@SortInTempdb = 'Y',

@LogToTable = 'Y'

  • Schedule the job
    • Daily at 23:30

SQL Database Files

Today I encountered a little bit of a misconfiguraiton on the SQL Server for SCCM and WSUS.  The database files (.MDF) and log files (.LDF) were on the same drive.  That is not good for performance.  Ideally we would want a separate drive for the data files, log files, tempDB, and TempDB log file.  NOTE:  Depending on how many processors you have you may want to create multiple TempDB files on different drives.

Pretty easy to move all the databases.

  1. Look up how to move the Master database.  You will use SQL Configuration Manager to do this
  2. Start moving the system databases and then the user databases.  Plenty of information on the net in regards to this.  Basically it is an Alter Database command
  3. Stop SQL Server
  4. Move the files
  5. Start SQL Server

I’m back!

Hi everyone, the EmptyGarden blog is back and alive. 

I just started a new job with Concurrency and thus will be blogging quite a bit…hopefully.

Following me on Twitter too:  @TheEmptyGarden