How to handle Windows 10 App language updates – implemented with SCCM

Logbook of the Captain – sidereal time: 2018.08.14

Since one customer came up with the need of some Windows 10 apps in the deployed image, I was searching for the easiest but securest way of deploying the apps with the correct preferred language of the client.

On the one hand I want to deploy the updates for the apps (only available via Windows Store), but on the second hand I need to find a way to restrict the ability for the users to install and use apps by themselves.

Attention: All my ideas were implemented with ConfigMgr, AD and Powershell

So what did I do?

  1. make shure, the default user have one preferred language
  2. Define folders, where users are allowed to execute scripts, executables or packaged apps (Win 10 Apps)
  3. Disable Access to the main-partition for the authenticated users (when needed, they get explicit access to the folders they need)
  4. Create Applocker rules for scripts, executables and packaged apps and allow only the in step 1 defined folders and apps
  5. Create Scheduled Task for the logon of the first user with the trigger script that includes the start of the update process
  6. Ensure that access to the store is defined via policy

So lets start!

I always include all needed language packs in my image via capture task sequence, i.e. with the following PowerShell function (It’s a “Run commandline” step with language packs in subfolder LP_Win10 of the package attatched):

#.SYNOPSIS
# Install all available language packs in attatched configmgr package folder
#.DESCRIPTION
#
function Install-LanguagePacks(){
  BEGIN{$Global:FunctionName = $myinvocation.mycommand.name}
  PROCESS{
     try{
         #prepare variables
         Write-Host -Value "Install windows Language Packs - Start"
         $source = ".\LP_Win10\"
         $array = @(Get-ChildItem $source -Filter *.cab)
         $cabs = $array.Name
         Write-Host -Value "Following Cab-Files available: $cabs"
              foreach ($cab in $cabs){
                    $pathtocab = $source + $cab
                    $block = { cmd.exe /c DISM.exe /online /Add-Package /PackagePath:$pathtocab }
                    Write-Host -Value "Running the Command: $block"
                    Invoke-Command -ScriptBlock $block
                    Write-Host -Value "Successfully integrated $cab into Windows image"
        }
     } catch {
              $ErrorExceptions = $Global:Error
              foreach($ErrorException in $ErrorExceptions){
                                      Write-Host ($ErrorException)
                                      }
              $Global:Error.Clear()
              Exit -1
             }
     Write-Host "Install windows Language Packs - FINISH"
    }
  END{}
}

@Step1 ( make shure, the default user have one preferred language ):

In the deployment task sequence you can define the target language with the help of a variable. how the variable is filled is up to you. For example, via a UI or a collection variable.

With the following function you can determine the name of the variable for the language via the parameter “CustVariable”. This variable must be part of the collection i.e.

#.SYNOPSIS
# Sets the language settings via a given collection variable
#.DESCRIPTION
#
function Set-LanguageByCollectionVariable(){
    param(
    [Parameter(Mandatory=$True)][string]$CustVariable
    )
        BEGIN{$Global:FunctionName = $myinvocation.mycommand.name}
        PROCESS{
            try{
            	Write-Host "Set language by collection variable - START"
                Write-Host "Use Custom Variable for Collection with Language: $CustVariable"
                $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
                $Language = $tsenv.Value($CustVariable)
                Write-Host "ConfigFile (TS-Var): $Language"
                $XMLFile = ("$LocationPath\" + $Language + ".xml")
                Write-Host "XMl file: $XMLFile"
                $FileName = "control.exe"
	        $Arguments = "intl.cpl,, /f:`"$XMLFile`""
                Write-Host "Running following command: $FileName $Arguments" -Value "Running following command: $FileName $Arguments"
		Start-Process $FileName $Arguments -Wait
               } catch {
                    $ErrorExceptions = $Global:Error
                    foreach($ErrorException in $ErrorExceptions){
                        Write-Host ($ErrorException)
                        }
                    $Global:Error.Clear()
                    Exit -1
                    }
                    Write-Host "Set language by collection variable - FINISH"
		}
        END{}
}

The script will execute the command and apply the xml included in atteched package. it selects the xml by the name of the variable, so in my example the XML files in the packages are:

en-US.xml

de-DE.xml

the xml has to look something like that for english i.e.:

<gs:GlobalizationServices xmlns:gs=”urn:longhornGlobalizationUnattend”>
<!– User List –>
<gs:UserList>
<gs:User UserID=”Current” CopySettingsToSystemAcct=”true” CopySettingsToDefaultUserAcct=”true”/>
</gs:UserList>
<!– Display Language –>
<gs:MUILanguagePreferences>
<gs:MUILanguage Value=”en-US” />
</gs:MUILanguagePreferences>
<!– System locale –>
<gs:SystemLocale Name=”en-US”/>
<!– User Locale –>
<gs:UserLocale>
<gs:Locale Name=”en-US” SetAsCurrent=”true”/>
</gs:UserLocale>
<!– Location –>
<!– GeoIDs: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_locations.asp –>
<gs:LocationPreferences>
<gs:GeoID Value=”244″/>
</gs:LocationPreferences>
<!– Keyboard preferences –>
<gs:InputPreferences>
<!–en-US–>
<gs:InputLanguageID Action=”add” ID=”0409:00000409″ Default=”true”/>
<!–de-DE–>
<gs:InputLanguageID Action=”remove” ID=”0407:00000407″/>
</gs:InputPreferences>
</gs:GlobalizationServices>

After applying this, all users logging in for the first time getting this language.

@Step2 (Define folders, where users are allowed to execute scripts, executables or packaged apps):

As a rule, standard directories are something like ProgramFiles or Windows folders (but these are defined as default rules in Applocker anyway). Think about which directories you still need! I always put under C: \ a folder with the name ClientMgmt, in the folder I include the following folders: AdminTools, Logs, Temp and Scripts. These will be released later in order to be able to execute them as user items from there.

@Step3 (Disable Access to the main-partition for the authenticated users (when needed, they get explicit access to the folders they need)):

I prefer to take away the C: \ partition permission of the Authenticated Users. The normal user now have only read permissions at the C:\ drive. Each additional writing access to the C: \ disk can now be entered separately. This increases safety many times over, but also means expenses.

You can achieve this goal with the following PowerShell code:

#Set Permissions to ClientMGMT Folder
$Clientmgmt = "$($env:SystemDrive)\ClientMgmt"
$ACL = Get-Acl -Path $Clientmgmt
$accessrule = New-Object System.Security.AccessControl.FileSystemAccessRule("Users","Read",,,"Allow")
$ACL.RemoveAccessRuleAll($accessrule)
Set-Acl -Path $Clientmgmt -AclObject $ACL
icacls C:\ /remove:g *S-1-5-11

@Step4 (Create Applocker rules for scripts, executables and packaged apps and allow only the in step 1 defined folders and apps):

The Applocker policys for executables and scripts should look like the following. Define them under Computer\Policies\Windows Settings\Security Settings\Application Control Policies. Right Klick in each of them (Appx Rules, Executables, scripts) and create Default Rules, then add your own. After rules are created you have to enforce them via the main config (root entry in policy). If you have problems, use the way the guys from ccmexec did it for the built-in apps:

https://ccmexec.com/2015/08/blocking-built-in-apps-in-windows-10-using-applocker/

We now allow in the appx policy all the apps we want to run, everything should look something like this:

20180814-GPO_Applocker1

20180814-GPO_Applocker2

Go sure, the application Identity Service is also enabled via your gpo

@Step5 (Create Scheduled Task for the logon of the first user with the trigger script that includes the start of the update process):

I’ve created a script, that will be used by the scheduled tasks. This script can be copied locally in a task sequence step under C:\ClientMgmt\Scripts and will then be executed by the scheduled task. Code should look something like that:

# Get all the provisioned packages
$Packages = (get-item 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Applications') | Get-ChildItem

# Filter the list if provided a filter
$PackageFilter = $args[0]
if ([string]::IsNullOrEmpty($PackageFilter))
       { echo "No filter specified, attempting to re-register all provisioned apps." }
else{
      $Packages = $Packages | where {$_.Name -like $PackageFilter}
       if ($Packages -eq $null)
        {
         echo "No provisioned apps match the specified filter."
         exit
        }
        else {
           echo "Registering the provisioned apps that match $PackageFilter"
        }
}

ForEach($Package in $Packages)
{
	# get package name & path
	$PackageName = $Package | Get-ItemProperty | Select-Object -ExpandProperty PSChildName
	$PackagePath = [System.Environment]::ExpandEnvironmentVariables(($Package | Get-ItemProperty | Select-Object -ExpandProperty Path))
        # register the package
        echo "Attempting to register package: $PackageName"
        Add-AppxPackage -register $PackagePath -DisableDevelopmentMode
}

$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_EnterpriseModernAppManagement_AppManagement01"
$wmiObj = Get-WmiObject -Namespace $namespaceName -Class $className
$result = $wmiObj.UpdateScanMethod()

your scheduled task schould look like this (my Script name is “reinstall-preinstalledApps.ps1”):

20180814-gpo_scheduledtask1

20180814-GPO_scheduledtask2

@Step6 (Ensure that access to the store is defined via policy):

The Options in the GPO for the store should be like this (ATTENTION: The other Settings in this policy folder should set to “Not configured”!!!):

20180814-GPO_storesettings

Finish 🙂

Captain over and out…

What to use – SCCM hierarchy or standalone Primary site?

Logbook of the Captain – sidereal time: 2017.07.25

By designing ConfigMgr infrastructures, the time has come in projects (hopefully at the beginning), where you have to decide between two different types of ConfigMgr infrastructures:

Standalone primary site or hierarchy

But what do you have to use in which situation? Probably the opinions tend to differ sharply.

First of all: Use Microsoft guides to get the visions the manufacturer want to provide: https://docs.microsoft.com/en-us/sccm/core/understand/fundamentals-of-sites-and-hierarchies

Second of all: There is a good method to decide, what is really needed in your infrastructure. Technically there are no reasons to use a hierarchy than having more than 150k Clients in your network. Everything can be done by a single primary site. Keep in mind, that using an hierarchy increase the complexity of the system in connection with maintenance etc.

Third of all: Keep in mind which situation may require a rethink. German customers i.e. are completely different and want to split infrastructure to seperate site servers physically, while insisting on this fact due to company compliance or something else.

My experience with ConfigMgr tells another story. The experiences with hierarchies in projects and at customers networks are very good. We use security scopes and modified security roles to seperate control inside the System and between site Servers. But you have to keep also in mind, data will be synchronized through the whole infrastructure and can not be seperated by using different site servers.

Some weeks ago I’ve discussed a question in connection with an hierarchy error with some guys via Microsoft TechNet Forum. Unfortunately, my error was not solved, because first the discussion came up: “Why I use a hierarchy and please only use standalone primary site, it provides all you will need.” (Different colleagues tell same stories about TechNet questions and discussions and were shocked by the behavior of the responding People, because they seemed almost obsessed with their own opinion).

Long story short: My answer is yes, you can only use standalone Primary sites, but why not to use hierarchy if it fits. I would only use a hierarchy if it meets the conditions of the customer and the administrative effort is achievable. Apart from this, a hierarchy does not make sense if it is less than i.e. 2000 Clients. It also makes no sense to build individual primary sites in a hierarchy  for each department or something else. For example, to set up secondary sites in order to be able to act even more granularly is likewise not useful. This increases unnecessarily the complexity.

Captain over and out…

SCCM Collection WQL Query – Include Device’s Primary User Full Name

Logbook of the Captain – sidereal time: 2017.07.05

Sometimes you’ll asking yourself about things you are thinking you are not able to do, but after some hours you’ll reach the destination and everything works like ordered by customers.

One of the customers I’ve worked for trying to sort computer objects in “ConfigMgr” to device collections by using department name. But they do not use “Active Directory” attributes or something else to gather the data for department ID’s. They are using the “Display Name” in “Active Directory” and append the department in brackets like:

lastname, forename (department)

But what is the challenge at sorting the clients by properties like display name? The display name of an user in “Active Directory” will be imported into “ConfigMgr” as an user object, but you want to return a value containing an client object. Nevertheless there is another challenge: Try to get the primary user of some devices is no problem while enabling the “User Device Affinity” function from “ConfigMgr” via “Client Settings”. The WMI class we want to use only returns the Pre Win 2000 name like “domain\username”. You have to translate the return value into the display name or also called user full name in “ConfigMgr WMI Library”. So what to do?

Create a “Client Settings Set” in “ConfigMgr” with “User and Device Affinity” functions enabled and customize the Settings like you need:

05-07-2017 14-18-41

(I choose 60 minutes for usage in a period of one day, caused on the situation we have to identify users on streamed machines in a short period of time)

Now enable the user discovery to use the affinity functions :

05-07-2017 14-21-48

From now the affinity in “ConfigMgr” is enabled and ready to use. Create now the collection with the following query:

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 JOIN SMS_UserMachineRelationship ON SMS_R_System.Name=SMS_UserMachineRelationship.MachineResourceName  JOIN SMS_R_User ON SMS_UserMachineRelationship.UniqueUserName=SMS_R_User.UniqueUserName  Where SMS_R_User.UniqueUserName in (select UniqueUserName from SMS_R_User where SMS_R_User.FullUserName is like “%Department%”)

Please replace the bold word with your parameter.

Captain over and out…

SCCM Report Error: Could not connect to the SMSDB. Service Principal Name is incorrect

Logbook of the Captain – sidereal time: 2017.06.07

From now I’ve installed so many servers with System Center Configuration Manager site in different constellations. It seems to be about 150 different servers in different domains, on different platform versions, productive and non-productive, on my own environment or on the customers environment. But last week I ran into an error I don’t understand until now.

I’ve installed an standalone primary site with Current Branch 1702 of Microsoft’s ConfigMgr and everything seems to be ok. We’ve migrated the content from an old ConfigMgr Standalone Primary Site and went to be sure that everything works like expected. One of the last things on my checklist: install the Reporting Services Point.

For understanding the environment:

  • Domain Level: 2008 R2
  • Server 2016 (with actual patches)
  • SQL Server 2016 SP1 locally installed
  • SCCM Current Branch 1702

As known I’ve installed SQL Server including Reporting Services. Microsoft recommends to install the SQL Server with Domain Accounts for running services. In this case you must register service principal names (SPN) for this services. Every time I’ve installed the services with different Users.One user for the Engine and one for reporting. Because of time issues I’ve only got one user for all services from the customer.

Reporting Services (native) installed correctly by SQL server setup and SQL  server services running as expected. SPNs would registred correctly by following the Microsoft Guideline: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/register-a-service-principal-name-for-kerberos-connections

Register SPNs for SQL Engine:

  • setspn.exe -a MSSQLSrv/NetBIOSName:1433 Domain\Serviceusername
  • setspn.exe -a MSSQLSrv/FQDN:1433 Domain\Serviceusername

Register SPNs for SQL Reporting Services:

  • setspn.exe -a http/NetBIOSName:80 Domain\Serviceusername
  • setspn.exe -a http/FQDN:80 Domain\Serviceusername

Later on (after installing reporting services point) I’ve want to test a report from ConfigMgr Console and ran into the error described in the title of this blog post. The Report crashed not because the reporting services could not reached the files on IIS, they crashed caused trough authentication error after connecting to the SMSDB.

After searching some hours on the internet and testing the connection and the issues I’ve decided to

  • delete the reporting databases
  • delete SPNs for reporting services
  • reinstall MS SQL reporting services with an second user (completely new user in AD)
  • and reinstall SCCM Role (reporting services point

After the reinstallation of described components everything worked fine.

BUT WHAT WENT WRONG?

I’ve installed the system as I did the other 149 times. This is the point in the life of a consultant who you are at the edge of madness. I hope I can adjust the error again and find the cause of the error. For an immediate solution, a reinstallation is sufficient, but does not satisfy the consultants brain.

Captain over and out…

 

 

Automate Repair of App-V Client after App-V Service does not Start

Hey Folks,

after appearance of the following Error at one of my customer, I decided to automate the Repair in Case of applying the Solution to many different Terminalservers remote.

The Error we get was the following:

Windows could not start the Microsoft App-V Client on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 3.

image

You’ll also see an event similar to the following:

Log Name: System
Source: Service Control Manager
Event ID: 7024
Level: Error
User: N/A
Description: The Microsoft App-V Client service terminated with service-specific error The system cannot find the path specified..

Event Xml:

7024

CAUSE

Generally we see these errors when App-V packages are manually deleted from the App-V cache (C:\Programdata\App-v). To demonstrate this, I reproduced this in my environment by deleting packages from the App-V cache and then taking a Process Monitor trace of “APP-V Client Service”. As seen below, we get ‘PATH NOT FOUND’ instances for the missing packages.

image

Note that the App-V cache is not the only locations where information about packages is stored; it is also stored in the registry at this location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AppV\Client\Packages

Here’s what they looked like on my computer:

image

Although I deleted the packages from the App-V cache, the information in the registry hive still exists, thus Appvclient.exe is trying to write data to the cache and getting the error ‘PATH NOT FOUND’.

RESOLUTION

If for whatever reason you manually deleted packages from the App-V cache, you need to be sure to remove the information regarding the same App-V packages from the registry hive at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AppV\Client\Packages

Keep in mind that Microsoft does not normally recommend that you delete anything from the App-V cache, however if you find yourself in a situation where you need to do this, we have steps on how to do it in the KB article below.

KB2768945 – How to remove a cached copy of an unpublished package in Microsoft App-V v5 (http://support.microsoft.com/kb/2768945)

NOTE: THESE STEPS SHOULD ONLY BE IMPLEMENTED IN THE SCENARIO WHERE PACKAGES ARE DELETED FROM THE APP-V CACHE. IT IS HIGHLY RECOMMENDED TO VERIFY WHETHER PACKAGES ARE DELETED FROM THE APP-V CACHE BEFORE PERFORMING THE ACTION PLAN ABOVE.

Thanks to Keshav Deo Jain, who detect this error and solution! (https://blogs.technet.microsoft.com/appv/2014/09/03/support-tip-the-app-v-client-service-fails-to-start-and-logs-event-id-7024/)

So why to automate? My Customer got the problem described with many of it’s Terminalservers (about 40 Servers). Because of this I automate the Solution described by Keshav with PowerShell:


#———————————————————————–#
# Scriptname: App-vRepairClientCache #
# Creator: Matthias Meißner – Login Consultants Germany GmbH #
# Date: 2017/04/13 #
# Actual Ver.: 0.0.0.4 #
# Version History: #
# 0.0.0.1 MM Initial Version by Matthias Meißner #
# 0.0.0.2 MM Add Remove-AllPermissions Function #
# 0.0.0.3 MM Add Foreach-Loop to read Data from CSV #
# 0.0.0.4 MM Add Foreach-Loop and Read WMI to delete users Cache #
#———————————————————————–#
# Description: #
# Script is reading CSV File including Server FQDN and reset ACL for #
# App-V Client Cash to delete cash. #
#———————————————————————–#
# CSV File must be located in same directory as the running script and must be structured like this:
#
# Servername
# Server1
# Server2
# ……
#Declare Variables (you have to configure the following two Variables to meet requirements of your own infrastructure)
$Username = 'Domainname\executionAccountname'
$KnownFolders = 'App-VCachefolder'
#Import App-V Module
Import-Module C:\Program Files\Microsoft Application Virtualization\Client\AppvClient\AppvClient.psd1
#Import CSV
$Servers = Import-CSV '.\Import.csv' Delimiter ';'
#Run Remote Powershell Command for each Server defined in CSV
foreach ($Servername in $Servers) {
$takename = $Servername.Servername
Invoke-Command ComputerName $takename ScriptBlock {
Function Remove-AllPermissions () {
Param(
$Folders
)
BEGIN {
$FunctionName = $myinvocation.mycommand.name
Write-Host "$FunctionName – Removes permissions from given directory – START"
}
PROCESS {
$acls = Get-Acl path $folders
$outputObject = @()
Write-Host "$FunctionName – removing permissions from folder $Folders"
Foreach($acl in $acls) {
$folder = (convert-path $acl.pspath)
Foreach($access in $acl.access) {
$acl.RemoveAccessRule($access) | Out-Null
} # end foreach access
Set-Acl path $folder aclObject $acl
$i++
}
}
end{Write-Host "$FunctionName – Removes permissions from given directory – Finish"}
}
Write-Host 'Permissions will be set….:'
Remove-AllPermissions ($KnownFolders)
Write-Host 'Stopping App-V Client Service….'
net stop AppVClient
Write-Host 'Remove Client Packages….'
Get-AppvClientPackage All | Remove-AppVClientPackage
Write-Host 'Stopping App-V Client Service….'
net stop AppVClient
Write-Host 'Delete Registry Hive: HKLM:\SOFTWARE\Microsoft\AppV\Client\Packages'
Remove-Item Path HKLM:\SOFTWARE\Microsoft\AppV\Client\Packages force recurse
Set-Location Path env:
Write-Host 'Removing App-V5 Client Cache directory'
Remove-Item ($KnownFolders + '*') recurse
Write-Host 'Get all user accounts loaded locally…'
$loggedonUsers = Get-WmiObject Class Win32_UserAccount
foreach ($Name in $loggedonUsers) {
$handleuser = $Name.Name
Write-Host "User AppData for User '$handleuser' will be deleted"
$beginningstring = 'C:\Users\'
$UserAppData = $beginningstring + $handleuser + '\AppData'
$PathCatalog = "$UserAppData\Roaming\Microsoft\AppV\Client\Catalog\Packages"
$PathRoamingVFS = "$UserAppData\Roaming\Microsoft\AppV\Client\VFS"
$PathINT = "$UserAppData\Local\Microsoft\AppV\Client\Integration"
$PathClientVFS = "$UserAppData\Local\Microsoft\AppV\Client\VFS"
if (Test-Path $PathCatalog){
Write-Host "Deleting the App-V Catalog Path for User $handleuser"
$PathCatalogfinal = $PathCatalog + '\*'
Remove-Item $PathCatalogfinal recurse
} else { Write-Host "Path to App-V Catalog for User $handleuser does not exist"}
if (Test-Path $PathRoamingVFS){
Write-Host "Deleting the App-V Roaming VFS Path for User $handleuser"
$PathRoamingVFSfinal = $PathRoamingVFS + '\*'
Remove-Item $PathRoamingVFSfinal recurse
} else { Write-Host "Path to App-V Roaming VFS for User $handleuser does not exist"}
if (Test-Path $PathINT){
Write-Host "Deleting the App-V Integration Path for User $handleuser"
$PathINTfinal = $PathINT + '\*'
Remove-Item $PathINTfinal recurse
} else { Write-Host "Path to App-V Integration for User $handleuser does not exist"}
if (Test-Path $PathClientVFS){
Write-Host "Deleting the App-V Client VFS Path for User $handleuser"
$PathClientVFSfinal = $PathClientVFS + '\*'
Remove-Item $PathClientVFSfinal recurse
} else { Write-Host "Path to App-V Client VFS for User $handleuser does not exist"}
}
Write-Host 'Starting App-V Client Service….'
net start AppVClient
Write-Host 'Get App-V Publishing Server and starting sync….'
Get-AppvPublishingServer | Sync-AppvPublishingServer
} credential $Username
}

https://gist.github.com/anonymous/d7dd57c6f4b1dd0c412fdd4638d63bc7.js

CU4 for System Center 2012 Configuration Manager SP2 and System Center 2012 R2 Configuration Manager SP1 released by Microsoft

https://support.microsoft.com/en-us/kb/3195483

Issues that are fixed

Mobile device management

1. Synchronization of the Exchange Connector fails, and errors that resemble the following are logged in the EasDisc.log file:

ERROR: [MANAGED] Exception: An item with the same key has already been added.
ERROR: Failed to check status of discovery thread of managed COM. error = The parameter is incorrect.
INFO: Total number of devices discovered 0

This issue occurs in environments when the same account name exists across multiple domains. For example, user1@contoso.com and user1@domain2.contoso.com.

Site Systems

1. The SMS Executive service stops unexpectedly when the SMS_Despooler component is trying to delete a file. Errors that resemble the following are recorded in the Despool.log file on the site server:

::DeleteFileW failed for D:\SCCMContentLib\FileLib\1E69\{guid}.SIG
RemoveFile failed; 0x80070002
CFileLibrary::AddFile failed; 0x80070002
CContentBundle::ExtractContentBundle failed; 0x80070002
~Failed to extract contents to the content library. 0x80070002
~Failed to extract package contents from C:\PROGRAM FILES\MICROSOFT CONFIGURATION MANAGER\INBOXES\DESPOOLR.BOX\RECEIVE\PKG12345.TRY. Error = 2

After this error sequence is recorded, the SMS Executive service may stop.

2. The SMS Executive service stops unexpectedly when it processes certificate data. When this occurs, the last entry in the certmgr.log file contains entries that resemble the following:

RetrievePfxData – WHERE UserItemKey={itemkey} and IsTombstoned=0

3. The Delete Aged Status Messages maintenance task incorrectly removes records from the Update_ComplianceStatus table. This results in inaccurate status reporting for updates older than 6 months.

4. CPU usage on the SQL server for a given site may spike under load from many user policy requests in a short period.

Administrator Console

1. The Available software updates count in the Schedule Updates Wizard shows an incorrect count of updates for Windows 10-based client images.

Operating System Deployment

1. 3151994 The SMSTSRebootDelay variable doesn’t work for multiple restarts in System Center 2012 Configuration Manager

2. The Task Sequence execution engine times out in two minutes, instead of running up to a defined maximum.

3. 3183710 The Install Application task does not use content from the pre-staged media in System Center 2012 Configuration Manager

Non-windows clients

1. 3155424 Mac inventory data isn’t processed in System Center 2012 Configuration Manager

Software distribution and content management

1. Software distribution content is not extracted to a secondary drive when the primary drive of a distribution point has insufficient free space. Errors that resemble the following are recorded in the despool.log on the site server:

Extracting content ABC00001.1
::DeleteFileW failed for H:\SCCMContentLib\FileLib\…
RemoveFile failed; 0x80070002
CFileLibrary::AddFile failed; 0x80070002
CContentBundle::ExtractContentBundle failed; 0x80070002
~Failed to extract contents to the content library. 0x80070002
~Failed to extract package contents from E:\SCCM\INBOXES\DESPOOLR.BOX\RECEIVE\{PKG_File}. Error = 2

2. All content distribution can stall if one distribution point is in a problem state. For example, if the IIS Admin Service (inetinfo.exe) is hanging on one distribution point, all other distribution points will wait for the problematic distribution point to come back online. A message pattern resembling the following is logged in the distmgr.log file on the site server, repeating approximately every two minutes:

There are still 1 DP threads active for package ABC00139, waiting for them to complete. SMS_DISTRIBUTION_MANAGER 12608 (0x3140)
There are still 1 DP threads active for package PRI00290, waiting for them to complete. SMS_DISTRIBUTION_MANAGER 14128 (0x3730)
There are still 1 DP threads active for package ABC0013B, waiting for them to complete. SMS_DISTRIBUTION_MANAGER 8348 (0x209C)
There are still 2 DP threads active for package ABC000C4, waiting for them to complete.

3. Redistributing a package to a remote distribution point at a secondary site results in all distribution points for that site receiving the package. This issue occurs when the secondary site was recovered, and the original database was lost.

4. If the Configuration Manager Content Library (SCCMContentLib) spans multiple drives and one of those drives is full, content distribution may fail. Errors that resemble the following are recorded in the distmgr.log file:

~Use drive D for storing the compressed package.
CContentBundle::AddContentDefinitionItems failed; 0x80070003
CDistributionManager::AddContentToBundle failed; 0x80070003
CDistributionManager::CreatePackageBundle failed; 0x80070003
~Error creating package bundle to send copy of package ABC000A2 to site PRI.
STATMSG: ID=2333 SEV=I LEV=M SOURCE=”SMS Server” COMP=”SMS_DISTRIBUTION_MANAGER”

Client

1. Software center incorrectly displays a status of Waiting to install when it should display Waiting for next available maintenance schedule.
2. Network errors can result in the Location Services component of the SMS Agent Host (ccmexec.exe) generating a sharp increase in CPU activity on client computers.

Software Updates Management

1. Software updates are expired incorrectly based on their creation date instead of their supersedence date.

Additional changes that are included in this update

Vulnerability Assessment

1. The Vulnerability Assessment Overall Report is added to the new Vulnerability Assessment folder in the Administrator Console.

Note: The System Center Configuration Manager Vulnerability Assessment Configuration Pack is still required.

Supported operating systems

1. This update requires the latest release of the Clients for Additional Operating Systems.

2. Ubuntu Linux 16.04 can be targeted for software distribution.

Client

1. Multiple client components are upgraded to remove a dependency on the Visual C++ 2005 runtime.

Note: For the dependency to be removed, the client must be upgraded by using the client setup file, CCMSetup.exe. This is typically invoked through the built-in automatic update feature, or through the client push installation that uses the option to “Always install the client software” enabled. For more information, see How to install clients on Windows-based computers in Configuration Manager.