Quantcast
Channel: SCCM – blog.hosebei.ch

Office365 – Manage Updates through Configuration Manager

$
0
0

Today I had the problem that some clients were failing to install the Client 365 Package from our System Center Configuration Manager (1602). I have set up the configuration for the Office 365 installation through GPO, this process is outlined on the following TechNet Article: Manage Office 365 client updates with System Center Configuration Manager
But the client did not even start to download the update:
Office 365 Update fails

I then checked the DataTransferServer.log and found the following error:
DataTransferService.log error

DTSJob {AF9F1697-4680-4BA9-A386-BB6D0E1AB03A} in state ‘DownloadingData’. DataTransferService 15.07.2016 14:45:14 11488 (0x2CE0)
DTS job {AF9F1697-4680-4BA9-A386-BB6D0E1AB03A} BITS job {D570298C-4133-4306-9814-F64B813F3D79} failed to download source file http://hosebeisccm01.deheim.hosebei.ch:80/SMS_DP_SMSPKG$/c1f4bd6a-3b93-4f97-be77-a74811d0538c/Office/Data/16.0.7070.2026/s321031.cab to destination C:\WINDOWS\TEMP\OfficeC2R2DC7895A-79AC-49DB-9DC9-8967C3131339\s321031.cab with error 0x80190194

In the usage of web Transfer-Errors, the code “0x80190194” simply means a 404. This was leading me to check the URL given:
http://hosebeisccm01.deheim.hosebei.ch:80/SMS_DP_SMSPKG$/c1f4bd6a-3b93-4f97-be77-a74811d0538c/Office/Data/16.0.7070.2026/s321031.cab to destination C:\WINDOWS\TEMP\OfficeC2R2DC7895A-79AC-49DB-9DC9-8967C3131339
I could open this URL, and I recognized that there is a File called s321033.cab, but not s321031.cab. I remind myself that I had only downloaded the English language of the Office 365 Client Update, but had missed to download the german version. After downloading the Patch again with the German Language enabled, the client found all required files to download, and the installation was done afterwards.
Mind to download all the languages you are using for the Office Updates.



ConfigMgr 1606 – Configure Client Cache Size (Configuration Manager Current Branch)

$
0
0

Hi reader,

the newest Version of System Center Configuration Manager Current Branch (1606) is rolling out these days with a lot of new features and opportunities. But one of my favorites is definetly a very practical one: How often would you like to easily change the configured Cache size of a Configuration Manager Client? Not that much, but it does happen. In the past, we were required to set a new Cache Size value with WMI (a VBScript or Powershell would have done the job), but with 1602 you can now configure the Cache size with the clients settings:
Configure Cache Size configmgr

You can find the Client settings within the Administration section, and you can configure it on the Default settings or on specific settings which you then can deploy to collections:
client settings

This is a perfect example how Microsoft reacts to customer feedback on their uservoice:

completed
How can we improve Configuration Manager?
  • 28 votes
  • 1 comment

Control cache size using client settings

It would be nice to be able to control the client cache size settings using the client settings policies. This way you have a simple way to increase it if you have a package which is larger than the initial deployed size.

This means, if you see some possible improvements, look within uservoice if somebody already mentioned this, if this is not the case, add it as suggestion. Either ways, spread your idea.


SQL 2016 – Export Maintenance Plan

$
0
0

Since I started to back up my System Center Configuration Manager Site within a SQL Maintenance Plan, I wondered how I would be able to export this Plan. To be able to restore the plan quickly, in case of failure, I wanted to export the maintenance plan. This starts by installing the Integration Services from the SQL Setup:
SQL Integration Services

After the installation the setup requires you to restart the System, but it will not force the system to a reboot. When the Integration Services are installed, you can open the SQL Server Management Studio:
SQL Server Management Studio
If you are missing the Management Studio on a 2016 Machine, this is normal, it does not come with the installation media. Refer to this Microsoft MSDN site to receive information and the download ling for the Management Studio 2016: Download SQL Server Management Studio (SSMS)
When the Management Studio is loaded, select “Integration Services” and add the Servername:
Integration Services
Within the Object Explorer, Navigate to your maintenance plan, right-click on it and select Export Package:
Export Maintenance Plan
You can then select a Location where the Package should be stored:
Maintenance Package
You will now have a reimportable package of your maintenance Plan, you can even reimport the same maintenance plan:
Integration Service


ConfigrMgr – The complete Backup (currently)

$
0
0

Motivated from my attend at IT/Dev Connection in Las Vegas, I wanted to create my complete Backup from ConfigMgr so far.
Because I was required to copy a lot of work from other people together, I decided to create a blog with each detailed step to achieve a fine Backup at the end, and I will start from the beginning, until we have reached our goal:
SQL Backup Maintenance

First make sure you can access the SQL Management Studio, and that you are able to create a Database, which is required to store some Stored Procedures from an active community contributor which I will outline later on. I have created that all on my LAB, so SQL and ConfigMgr are installed on the same virtual Machine, this may also be true for smaller Organizations.
When you have opened your SQL Management Studio, create a new Database, mine is called “DatabaseMaintenance”:
Created Database
After creating the Database you can navigate to the to the SQL Server Agent and open the node Jobs, right-click on Jobs and Select “New Job…”:
SQL Server Agent Job
Enter a name for the Job, and switch to Steps:
SQL Powershell Delete Files
Click on “New…” to add a new step to this job, make sure that you change the type to “Operating System (CmdExec)” and copy to following (modified) powershell command to the Command Text block:
powershell.exe -command "While(([math]::round(((Get-ChildItem -Path '\\deheim.hosebei.ch\hosebeiDFSroot\Backup_Folder\SCCM_BackupLocation\hosebeisccm01\SQL_Backup_S01' -Recurse) | Measure-Object -Property Length -Sum).sum / 1024 / 1024 / 1024)) -gt 10) { Remove-Item (Get-ChildItem -Path '\\deheim.hosebei.ch\hosebeiDFSroot\Backup_Folder\SCCM_BackupLocation\hosebeisccm01\SQL_Backup_S01' | Sort CreationTime | select -First 1).Fullname -Recurse -Force}"
This will delete the oldest Files within the given UNC Path, if the Size of the folder is greater than 10 Gigabyte. Be sure that the selected “SQL Server Agent Service Account” has writable access to the destination Folder, which you might to change on the given example above. The Step should then look like this:
PoSh SQL Delete Files
Close the Job by clicking OK Twice.
If you consider to use the type “PowerShell”, DARE YOU! It is not working, or only limited functionality is given. See this wonderful Blog from SQL Hammer.
Then navigate through the Management Tree and right-click on “Maintenance Plan” to select “New Maintenance Plan…”:
New Maintenance Plan
After a click on save, and by refreshing the Tree, your newly created maintenance Plan will show up. The newly created maintenance plan is not scheduled yet, keep in mind, that a scheduled maintenance plan gets disabled, if the plan is changed after activating the schedule. You will have to manually enable the Job under SQL Server Agent again.
You should now have an empty Maintenance Plan in Front of you, when you double-click on the Subplan, you can change the description or name:
Maintenance Plan Subplan
To add the first step of the maintenance Plan, open the Toolbox through View:
Maintenance Plan Toolbox
From the toolbox, double-click on “Execute SQL Server Agent Job Task”, and the step will be added to the Subplan. This first step will delete existing files from the Backup folder created in the job with the powershell Script before. Now double click on the added step:
configmgr_backup07
And select the previously created job from the list. Again, make sure that the User Account which runs the SQL Server Agent need to be able to perform those file operations on the target path:
Select Job
To rename the steps, just click on the name, and the known rename appearance will be shown. If you have finished the manipulations of the first step, Open the Toolbox again and add a step named “History Cleanup Task”, move the step an appropriate position, and connect it from the “Delete old files” step:
Cleanup Step
Click on save, the maintenance plan will be stored, we have to leave the creative process and set up our maintenance Database. This process is quite simple, and I take it from Ola Hallengren. He explains on his website how to use his work, I really want to point out that I’m a user of those as well. Just simply download the file called MaintenanceSolution.sql and run it within your SQL, mind to change the targeted Database:
Create MaintenanceDB
This will store the changes within your own database, rather than the master DB, which would work too. Now navigate to the SQL Server Agent and open the node Jobs, right-click on Jobs and Select “New Job…”:
SQL Server Agent Job
Enter the name “Index Rebuild and Statistic Refresh” and click on Steps:
Step1
Click on “New…” and enter the Name “Rebuild Index”, add the T-SQL command A from Ola Hallengren. Make sure to change the Database to your Maintenance Database:
rebuild index
Finish this step by clicking on OK. within the “New Job” Wizard click on “New…” again, and add a Step named “Statistic Refresh”, take as T-SQL command the C from Ola Hallengren:
Statistic Refresh
Click on OK twice to close the Step and finish the Job Wizard. You can now go ahead to the Maintenance Plan, and add through the toolbox a step named “Execute SQL Server Agent Job Task”, connect it with the parent step, and rename the step as you like. Double-Click the step and select the previously created Job:
Step Job
Here is the Job Task selection wizard:
configmgr_backup17
Now it is time to implement the Windows Server Update Service cleanup script, which can be download from Microsoft:
Re-index the WSUS 3.0 Database
Just copy the Script Block to the Clipboard, we will insert it in the T-SQL Statement which will be added right now. Open the Toolboox and add a “Execute T-SQL Statement Task”, connect it to the previous step, and rename it if you like:
WSUS Cleanup step
Insert the T-SQL Statement from the clipboard, check if there is a hidden char after the “GO” command (there are three), which may fail the execution:
WSUS Statement
Now it is time to back up the Databases, go to the Toolbox and add “Back Up Database Task”, connect the added Task, and Rename it if necessary:
Backup DB
Double-Click on the added Backup Task and select the Databases you like to back up (in my Case: ConfigMgr DB, SUSDB and MaintenanceDB):
Backup DB Selection
Make sure that you select compress backup within the Options Tab, and it is always a good idea to select checksum and backup integrity:
SQL Backup Options
When this is done, you can now add the step to create the zip-compressed file of the CD.Latest Folder, but first we have to create a Job for this, so navigate to the SQL Server Agent right-click on “Jobs” and select “New Job…”, name the job as you like:
Copy cd.latest
Now go ahead and select the steps, and click on “New…” to add a step to this Job. Choose a name you like for this step, and copy paste the command from Kent Agerlund (Source), make sure to change the type to Operating System:
powershell.exe -command "Add-Type -Assembly ‘System.IO.Compression.FileSystem’ -PassThru | Select -First 1 | % { [IO.Compression.ZIPFile]::CreateFromDirectory(‘d:\program files\microsoft configuration manager\cd.latest’, ‘\\deheim.hosebei.ch\hosebeiDFSroot\Backup_Folder\SCCM_BackupLocation\hosebeisccm01\SQL_Backup_S01\cd.latest_’ + (Get-Date -format ‘yyyyMMddHHmm’) + ‘.zip’) }"
CD.Latest Job
Mind to change the two folders to respect your ConfigMgr Installation and the Backup Path from your environment. For your Information: This powershell command is a fire-and-forget step, it does not wait for the powershell command to finish, the plan will continue the Maintenance Plan after the execution of the command. You can then close the Job by click on OK twice.
After the creation of this Job, you can go back to your Maintenance Plan, open the Toolbox and add a “Execute SQL Server Agent Job Task” to your Subplan. Connect this step with the following “Back Up Database Task” and rename the step if you like, your Subplan should look like the following:
Maintenance Plan
Double-Click on the added step, and select the previously created Job:
Select Job
Now you are all set, and at last, you need to schedule the maintenance plan, just click on the calendar icon wihtin you subplan:
Schedule SQL Maintenance Plan
Within the following wizard, you can configure how often this should run:
New Job Schedule

Hope this helps, and if som one can provide a one-liner for exporting al Task Sequence (see this template Link), I’m happy to update my blog post🙂


ConfigMgr – NDES Certificate Deployment fails due to Network Device Enrollment Service failure

$
0
0

I was struggling a little bit within my LAB trying to get the Network Device Enrollment Service (NDES) up and running again for the Simple Certificate Enrollment Protocol (SCEP), which is I believe not that simple, but anyway. I was really unsure what I did have changed (because I changed a lot in the last month within my LAB), that would have stopped the functionality of the Certificates to my devices, but I had a start point, the event log of the NDES Server told me the following:
The Network Device Enrollment Service cannot retrieve one of its required certificates (0x80070057). The parameter is incorrect.
The Network Device Enrollment Service cannot be started (0x80070057). The parameter is incorrect.

Network Device Enrollment Service error

I knew that Pieter Wigleven did an excellent job on his blogs to configure System Center Configuration Manager (SCCM) with SCEP based on a Windows PKI and NDES: Find Blog here
So I checked the settings Pieter is mentioning on his blogs, I did also a lot of researching, but could not find a solution for this issue, but a lot of other people with this error.
Little frustrated, I began to work on my new WiFi Solution with VLAN and Multi-SSID. When I was trying to authenticate against my Radius with a Client Certificate, the Network Policy Server told me, that the Certificate Revocation List (CRL) could not be retrieved. I was quite sure, that I was able to download the CRL, and I double checked that. But I did not check the availability of the Delta CRL, which was visible on the web site, and when I finally tried to download this file, it failed. I then remembered myself, that I had some changes made on my public IIS, and I probably forgot to set the setting “Allow double escaping” (See this Link for explanation and configuration steps):
enable double escaping
After enabling this, I was able to retrieve a Certificate through NDES again.
So if your NDES Server is throwing “The Network Device Enrollment Service cannot retrieve one of its required certificates (0x80070057). The parameter is incorrect.”, do not only check the certificates on the Server, check also the CRLs and DeltaCRLs!


ConfigMgr – Windows 10 Feature Update without a Task Sequence

$
0
0

Today I would like to talk about the upcoming update cycles you have to do, when you are using Windows 10 Current Branch or Current Branch for Business. This means, if you have started to install Windows 10 1507 (which represents the first Windows 10 Release, some may call it also RTM) in spring of last year, you will be soon required to upgrade to a newer version of Windows 10. Also if you are using Windows 10 1511, with the upcoming creators update, the 1511 version of Windows 10 will be soon unsupported, following the official guidelines.
winver.exe 1607

This means you are required to plan a rock solid update mechanism, that respects your needs in order to satisfy the business in a client perspective. One of the most important advises for planning your update infrastructure: Create steps that you can reuse whenever a new image or version of Windows 10 is released, where it is possible.
For the past it have might been the best option, to use a System Center Configuration Manager (ConfigMgr) Current Branch update Task Sequence, if you wanted to fully control all aspects of an update installation. The options within this Task Sequence are quite similar to the existent operating system deployment Task Sequences. But in larger environments or with locations that are not well-connected to a distribution point, this can be very hard to run successfully, so the Servicing model might be an option. And if you think about the regular consumers, they always update Windows 10 with the servicing model, which means that the new version gets installed like a regular Windows Update. With this information you can come to the conclusion, that Microsoft prefers the option of the servicing model. Even with a ConfigMgr Infrastructure the servicing model can be helpful, if a client can download the new Windows Version from the Windows Update source, rather than download it from a DP (ConfigMgr Distribution Point) through a company VPN.

Now you might want to ask me: But I have multiple languages to support and servicing model only updates the base language. HOW U HANDLE THAT?
Well, there is a kind of messy part, and an easy part to handle that. Let me first talk about the easy part: The easy part is as follows, you can simply use a SetupConfig.ini file which points on a folder, where the Language Packs are available, and the Windows setup will install those Language Packs automatically. The usage of a SetupConfig.ini file is well explained on this blog on windows-noob.com.
And now here comes the messy part: What if you have to support more than 20 languages? And more on: All clients have as base language en-US (English United States), and they may have one or more languages installed?
Unfortunately there does not exist an option, or I did not find it like many others, to report the installed language packs within ConfigMgr, for using it within a query based collection. But you can add a WMI class to your clients and collect this class through the hardware inventory. This process has already been documented on the systemcenterdudes.com blog.
Now you can create collections or use this information in other ways to deploy the language packs to the correct clients.

The next big Question will be: But with the new Version, I will get the Windows Store-App Candy Crush again, which I have removed from the image. With the servicing model I can’t modify the image. HOW U HANDLE THAT?
There are different options to modify the freshly installed Windows 10, and one of them you can use within a regular OSD Task sequence as well, you may just change the way it gets executed. So if you need to modify System settings like which language will be used for a default user, or how the default start menu should look like, you can use a script, which will be executed at the end of the Windows 10 upgrade. To use this option, you simply have to add the following line to your SetupConfig.ini:
PostOOBE=C:\LP\Scripts\CommandAfterInstall.bat
Obviously the script has to exist at the location, I will point out how I achieved this later in this blog.
The second option which you can use to modify the System is when the user has logged on, this method uses the SetupCompletes.cmd option and is explained on this MSDN Site.
But as stated on the MSDN site: “This script runs immediately after the user sees the desktop”
So it might not be the best option.

So let’s go on and see, how I did the Script stuff for the upgrade.
First I created a Folder where my German language pack resides and I copied the language pack inside it and my 3 other required Files as well, which I will explain immediately:
Package Folder
Now I will show you the content of “Copy_LP_de.bat”:
mkdir c:\LP
mkdir c:\LP\Scripts
mkdir c:\LP\LP
copy "%~dp0*.cab" c:\LP\LP /Y
copy "%~dp0CommandAfterInstall.bat" c:\LP\Scripts /Y
mkdir "%systemdrive%\Users\Default\AppData\Local\Microsoft\Windows\WSUS\"
copy "%~dp0SetupConfig.ini" "%systemdrive%\Users\Default\AppData\Local\Microsoft\Windows\WSUS\" /Y

This batch file can be used for every language and also if you are using feature packs or even Language Interface Packs.
Now lets talk about the “CommandAfterInstall.bat”, which is quite a short speech: You can start whatever you like (afaik). In my case, I just created a folder to be sure that the batch gets executed.
And beside the language pack, the last two lines are the most important. Those create the required WSUS folder within the Default User profile, and copies our “SetupConfig.ini” file to this location. My example of the SetupConfig.ini is quite simple:
[SetupConfig]
InstallLangPacks = C:\LP\LP
PostOOBE=C:\LP\Scripts\CommandAfterInstall.bat

SetupConfig.ini
So my example does instruct the Windows Installation to watch out in “C:\LP\LP” for language packs and will start “C:\LP\Scripts\CommandAfterInstall.bat” after the installation succeeds.
For a full list of the available parameters that you can use within the SetupConfig.ini refer to this MSDN site.

Happy updating!


ConfigMgr – Windows 10 Servicing – Step by Step

$
0
0

Today I would like to show you, how you can implement an Upgrade of a Windows 10 Installation through the Servicing Option.
I always think of two things, when I have to decide to use an Upgrade Task Sequence or the Servicing Model, and those are:

  • Do I want to use the Option that the clients will download the Windows 10 Sources from the Microsoft Update Servers?
  • When I use an Upgrade Task Sequence, I can copy most of the steps from the regular OSD Task Sequence
  • But for this blog post, I would like to show my setup for the servicing model.

    First of all, I have already written a post about the Update process in a slightly overview manner, you will find this post here: My old post

    The first step would be to determine which packages you would like to implement for the upgrade. Based on the fact, that I use English as base language, I will add the Feature on Demand (FoD) packages, and I will also add the feature package NetFx3. My Setup does also contain the German Langauge, which requires me to add the corresponding Language Pack and FoD Packages. The following picture shows the folder of my Packages which I want to include within the Windows 10 Installation:

    When this is done, you will have to decide, where you would like to store the packages and also some script files on the System Disk of the current Client. I have decided to create a folder named C:\LP, which is hidden, and two subfolders called LP and Scripts, I would also recommend to modify the default User Permissions, if you don’t want that standard users can change the scripts.

    To achieve the copy jobs which are required, I will come back to those scripts later, I have decided to use Configuration Items, rather than an Application or an Old-School Package within the Software Library. But this will require that my clients are able to access those files, because they will not download it from a Distribution Point. I am using Distributed File Services (DFS) to have a single UNC Path, where the clients can download the packages (with BITS of course).
    I have decided where my package location resides and have copied all the required packages and scripts to this location:

    Then I went on and created a Configuration item named “Windows 10 Servicing CI”:

    I only selected Windows 10 (x64):

    Within the next step of the Wizard, click on “New…” to add a setting, and the following Windows appears:

    Make sure to have selected the “Setting Type” Script, and as “Data Type” “String”, as shown in the picture above. Afterwards click on “Add Script…” within the Discovery Script Section, and the following script block windows will appear:

    Make sure that “Windows Powershell” is selected as script language. The script will simply check both file locations, and if the size is not the same, the CI will be reported as non-compliant. You may want to extend the detection script to your needs, as example if you have multiple languages and want to copy only some languages to the client. I have used the following script for this purpose (you will find a zip Download at the end of the blog as well):
    #Variables
    $LocalFolderLP = "C:\LP\LP"
    $PathToLanguagePacks = "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703"

    $Compliance = "Non-Compliant"

    #Receive transferred jobs, but not yet finished
    $bitstransfers = Get-BitsTransfer -AllUsers
    foreach($bitsjob in $bitstransfers) {
    if($bitsjob.Jobstate -eq "Transferred") {
    #End old Transfers due script execution errors
    Complete-BitsTransfer -BitsJob $bitsjob
    }
    }

    #Start Main Script
    If((Test-Path $LocalFolderLP) -eq $false) {
    $Compliance = "Non-Compliant"
    }
    else {
    #Measure both Locations
    $SizeOfLPsSource = Get-ChildItem -Path $PathToLanguagePacks -Filter *.cab | Measure-Object -property length -sum
    $SizeOfLPsDestination = Get-ChildItem -Path $LocalFolderLP -Filter *.cab | Measure-Object -property length -sum
    If($SizeOfLPsSource.sum -ne $SizeOfLPsDestination.Sum) {
    $Compliance = "Non-Compliant"
    }
    else {
    $Compliance = "Compliant"
    }
    }
    #Return the result
    $Compliance

    Close this Windows by a click on “OK”. Then go ahead and click on “Add Script…” witin he Remedation Script section, and add the following script to the script block:

    #Copy the Language Pack Files
    Function Start-LPBitsJob([System.IO.FileInfo]$CABFileToCopy, [string]$LocalLPFolder) {
    $BitsJob = $null
    $BitsJob = Start-BitsTransfer -Source $CABFileToCopy.FullName -Destination $LocalLPFolder -TransferType Download -Asynchronous -DisplayName "CAB Downloads"
    }

    #Variables
    $LocalFolderLP = "C:\LP\LP"
    $PathToLanguagePacks = "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703"

    #Start Main Script
    if((Test-Path $LocalFolderLP) -eq $false) {
    New-Item $LocalFolderLP -ItemType Directory
    }
    $MakeHidden = Get-Item "C:\LP" -Force
    $MakeHidden.Attributes="Hidden"
    if((Test-Path $LocalFolderScripts) -eq $false) {
    New-Item $LocalFolderScripts -ItemType Directory
    }

    $CABFilesToCopy = Get-ChildItem -Path $PathToLanguagePacks\* -Include *.cab
    foreach($cabFile in $CABFilesToCopy) {

    if($cabFile.length -ne (Get-Item ($LocalFolderLP + "\" + $cabFile.Name)).Length) {
    #Write-Host "not same"
    Start-LPBitsJob $cabFile $LocalFolderLP
    }
    else {#Write-Host "same"
    }
    }

    $AllBitsDownloads = Get-BitsTransfer -Name "CAB Downloads"
    $DLFinishedLoop = $false
    while ($DLFinishedLoop -eq $false) {
    $DLFinished =$true
    foreach($BITSDownload in $AllBitsDownloads) {
    if($BITSDownload.JobState -ne "Transferred") {
    $DLFinished = $false
    }
    }
    if($DLFinished -ne $false) {
    $DLFinishedLoop = $true
    }

    sleep 1
    #write-host "loop"
    }

    #Now finish all Transfers
    $AllBitsDownloads | Complete-BitsTransfer

    As you can see, I’m using a BITS Transfer to download the packages and all packages are checked (based on the size), and a specific package is only downloaded if required. For more information about starting a BITS download through Powershell consult this Microsoft document: Using Windows PowerShell to Create BITS Transfer Jobs
    Your remediation script block should look like this:

    When this is done, we can switch to the “Compliance Rule” Tab and click on “New…”:

    Fill the opened window with the required information, make sure to check the Box at “Run the specified remediation script when the setting is noncompliant”:

    By clicking on OK twice, the first setting within the configuration item is finished. Now it is time to add the setting to copy the setupconfig.ini file, which is required to instruct the Windows Upgrade to use the downloaded packages and to execute a script after the installation. For more information about the setupconfig.ini refer to this Microsoft Document: Use Setupconfig.ini to install Windows
    My SetupConfig.ini is quite simple, I’m still using the same as outlined in the old post.
    Now a click on “New…” will open again a new setting:

    In the opened window, fill out the settings as shown below:

    Add the following script to the Discovery section:

    #Path to setupconfig File
    $SourceFileLocation = "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703\SetupConfig.ini"

    $Compliance = "Not-Compliant"
    if((Test-Path -Path "$env:SystemDrive\Users\Default\AppData\Local\Microsoft\Windows\WSUS\setupconfig.ini") -eq $false) {
    $Compliance = "Not-Compliant"
    }
    elseif((Get-Item "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703\SetupConfig.ini").Length -ne (Get-Item "$env:SystemDrive\Users\Default\AppData\Local\Microsoft\Windows\WSUS\setupconfig.ini").Length) {
    $Compliance = "Not-Compliant"
    }
    else {
    $Compliance = "Compliant"
    }
    $Compliance

    My remediation script, which will copy the setupconfig.ini to the correct place does not change the folder permissions of the WSUS folder. I would recommend for your environment to change the folder, or at least the file permission, that a regular user can’t modify the setupconfig.ini File. This is my remediation script for the ini file:

    if((Test-Path "C:\Users\Default\AppData\Local\Microsoft\Windows\WSUS") -eq $false) {
    New-Item -Path "C:\Users\Default\AppData\Local\Microsoft\Windows\WSUS" -ItemType Directory
    }
    Copy-Item -Path "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703\SetupConfig.ini" -Destination "$env:SystemDrive\Users\Default\AppData\Local\Microsoft\Windows\WSUS\SetupConfig.ini" -Force

    When you have added both scripts, switch to the Compliance Rules Tab, and add a new rule by a click on “New…”, fill out the opened rule window as in the following picture:

    Make sure again to have ticked the box to run the remediation script.
    And the last CI setting will copy the scripts that are required to be executed after the Windows Upgrade is done, but before a user can logon. The process is the same like for the two settings we already have created. Here is the Discovery Script which I’m using:

    $LocalFolderScripts = "C:\LP\Scripts"
    $SourceFileLocation = "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703"

    $Compliance = "Not-Compliant"

    $AllLocalScripts = Get-ChildItem -Path $LocalFolderScripts\* -Include *.bat,*.vbs,*.ps1
    $AllSourceScript = Get-ChildItem -Path $SourceFileLocation\* -Include *.bat,*.vbs,*.ps1
    if($AllLocalScripts.Count -ne $AllSourceScript.Count) {
    $Compliance = "Not-Compliant"
    }
    $SizeOfScriptsSource = Get-ChildItem -Path $SourceFileLocation\* -Include *.bat,*.vbs,*.ps1 | Measure-Object -property length -sum
    $SizeOfScriptsDestination = Get-ChildItem -Path $LocalFolderScripts\* -Include *.bat,*.vbs,*.ps1 | Measure-Object -property length -sum
    if($SizeOfScriptsSource.sum -ne $SizeOfScriptsDestination.sum) {
    $Compliance = "Not-Compliant"

    }
    else {
    $Compliance = "Compliant"
    }
    $Compliance

    And this is the remediation script:

    Function Start-BitsJob([System.IO.FileInfo]$FileToCopy, [string]$LocalFolder) {
    $BitsJob = $null
    $BitsJob = Start-BitsTransfer -Source $FileToCopy.FullName -Destination $LocalFolder -TransferType Download -Asynchronous

    while (($BitsJob.JobState -eq "Transferring") -or ($BitsJob.JobState -eq "Connecting")) { sleep 5;} # Poll for status, sleep for 5 seconds, or perform an action.

    Switch($BitsJob.JobState)
    {
    "Transferred" {Complete-BitsTransfer -BitsJob $BitsJob}
    "Error" {$BitsJob | Format-List } # List the errors.
    default {"Other action"} # Perform corrective action.
    }
    }

    $LocalFolderScripts = "C:\LP\Scripts"
    $PathToLanguagePacks = "\\deheim.hosebei.ch\hosebeiDFSroot\Deployment\OS\Windows 10\LanguagePacks\1703"

    if((Test-Path "C:\LP\Scripts") -eq $false) {
    New-Item -Path "C:\LP\Scripts" -ItemType Directory
    }

    $ScriptFilesToCopy = Get-ChildItem -Path $PathToLanguagePacks\* -Include *.ps1,*.vbs,*.bat
    foreach($ScriptFile in $ScriptFilesToCopy) {
    if($ScriptFile.length -ne (Get-Item ($LocalFolderScripts + "\" + $ScriptFile.Name)).Length) {
    #Write-Host "not same"
    Start-BitsJob $ScriptFile $LocalFolderScripts
    }
    else {#Write-Host "same"}
    }

    When you have finished adding the third setting, your Configuration Item should look like this:

    If you click on Next, the wizard will show you the created Compliances Rules according to the settings, make sure that “Remediate” is on Yes:

    Finish the wizard by clicking on Next twice and close it afterwards. Now we need to create a Baseline and just add our Compliance Item to it:

    After a click on OK, the baseline is created and ready to be deployed on a collection. Within the deployment wizard of the baseline, make sure to tick the check box at “Remediate noncompliant rules when supported”:

    Now everything is quite good and you can create a collection based on the baseline:

    And here is my batch file which I run after the Windows 10 Upgrade:
    mkdir C:\LP\1703_OK
    powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\LP\Scripts\Remove-Apps.ps1"

    The PowerShell Script “Remove-Apps.ps1” removes Universal apps which I don’t want on the clients. This is the content of Remove-Apps.ps1:

    #Initalize Array
    $AppstoRemove = New-Object System.Collections.ArrayList

    #Add Apps to Array
    $AppstoRemove.Add("Microsoft.NetworkSpeedTest_1.0.0.23_x64__8wekyb3d8bbwe") #NetworkSpeedTest
    $AppstoRemove.Add("46928bounde.EclipseManager_2.2.1.31_neutral__a5h4egax66k6y") #Eclipse Manager
    $AppstoRemove.Add("6Wunderkinder.Wunderlist_3.6.25.0_x64__b4cwydgxqx59r") #Wunderlist
    $AppstoRemove.Add("Microsoft.MicrosoftOfficeHub_17.8017.5925.0_x64__8wekyb3d8bbwe") #Get Office Sneak App
    $AppstoRemove.Add("Microsoft.BingTranslator_4.7.0.0_x64__8wekyb3d8bbwe") #Bing Translator
    $AppstoRemove.Add("D5EA27B7.Duolingo-LearnLanguagesforFree_2017.112.1.0_x64__yx6k7tf7xvsea") #Language Learning App
    #$AppstoRemove.Add("Microsoft.SkypeApp_11.12.112.0_x64__kzf8qxf38zg5c") #Skype for Business App
    #$AppstoRemove.Add("Microsoft.Office.OneNote_17.7967.57741.0_x64__8wekyb3d8bbwe") #OneNote App

    $AppstoRemove | Remove-AppxPackage

    You might want also to configure the Language settings as they were before. Then you can use the solution from Roger Zander, to apply Language Settings with an XML: Windows 10 MUI challenge
    Here you will find a Zip-File with all my scripts used within this blog: Windows 10 Upgrade Scripts

    Now you can deploy the upcoming release to your clients, just like a regular update.

    If you think this post was useful, please leave a comment, and if you see issues or you can recommend better techniques, leave a comment as well, or get in touch with me on twitter.


    ConfigMgr – Create Office 365 Package through Console

    $
    0
    0

    Today I would like to show you, how you can easily create and deploy an Office 365 Application within Microsoft System Center Configuration Manager Console.
    Within the ConfigMgr Console navigate to the “Office 365 Client Management” Dashboard, and click on “Office 365 Installer”:

    The Installer wizard will start immediately and ask you for a name and a source location of the Application. The wizard will download all required files to this location you specify:

    As you can see, I want to create a package for the Current Channel with Version 1702. After a click on “Next”, you can decide if you want to configure the client settings, or to import it from a previous XML File:

    The following step of the wizard let you select the Office 365 Suite and which Applications should be installed with the Package. In my case, I selected to not install the OneDrive for Business Sync with Groove:

    Afterwards you can configure the settings of the Office 365 installation, you can even create a RDS installation with the option “Shared computer activation”. It seems that the wizard has an issue with the language adding, in my case I always received an error message and I was not able to add a different language.

    The wizard asks you afterwards, if you would like to deploy the package already, I decided to not deploy it:

    Afterwards you will see the summary, where you can check your configuration:

    With a click on Next, the download will be initiated:

    The wizard will download the Office 365 package in the same way as you would do through the setup.exe manually:

    And here you can see the XML created from the wizard:

    You can monitor the download, the PatchDownloader.log for the wizard will reside within the “temp” directory of the user that executes the wizard. In my case the path was:
    C:\Users\$username\AppData\Local\Temp\6
    The wizard will create a single Application for the Office 365 Suite:

    As you can see, the Uninstall command is missing, no one wants to uninstall Office 365 🙂
    And here is the “official” Office 365 detection Method from the ConfigMgr Team:

    You can distribute the Application to your distribution points and deploy the Application to a collection.
    This wizard is quite buggy yet, I had several crashes for creating the Application, but it will easily create the source files for your Office 365 Package.



    ConfigMgr – My Guide for a SCCM driven Windows 10 Installation

    $
    0
    0

    In this blog I would like to give an overview of my Windows 10 Installation, since this has changed a lot to previous versions of Windows.
    This blog will cover the following topics:

    • Windows 10 Image Customization
    • Windows 10 Unattended File
    • Windows 10 Language Pack (MUI) Integration
    • Optional: Windows 10 with .Net feature

    The blog is based on Windows 10 1703:

    Windows 10 Image Customization
    Here is nothing to do. In most of the deployments I’ve seen, we did not make changes to the image or wim-file itself. I always did this in previous versions of Windows for have languages added and Windows features as well. But starting with Windows 10, I stopped those task, and moved to the “Do everything possible within the Task Sequence”. The main reason for this is to have those steps available for OSD and a Feature Upgrade as well.
    A good reason to modify the image is, if your installation process should consume less time. Because installing language packs or other Software can stretch the installation time.

    Windows 10 Unattended File
    In earlier Versions of Windows I often used a unattended file only to set the variables for the languages, I do now the opposite, and I also use more settings within the unattend file. Due to the fact, that I always use the en-US base image, my language settings looks like the following picture:

    The language settings within the OOBE section are the same. But I do have an additions to suppress the Wireless Setup (HideWirelessSetupInOOBE), which can interrupt the task sequence progress, or at least the progress is not visible. And also the MachineOOBE will be skipped:

    With those settings I can start building the Task Sequence within System Center Configuration Manager.

    Windows 10 Language Pack (MUI) Integration
    I install the language packs within the Windows PE phase. For this, I need to create a package, containing all the .cab files that I wanted to install through the Task Sequence. This includes the language pack for Swiss-German and the Feature on Demand (FoD) packs for the same language as well. In my case, the package source content folder looks like the following picture:

    As you can see in the screenshot, I also added a batchfile to install the language packs with dism, and a XML which is later described. Here is the dism command within the batch:
    dism.exe /image:%OSD_System%\ /add-package /packagepath:%~dp0
    The variable “%OSD_System%” which is used in the command above is set through the partitioning step previous in the task sequence.
    So I can now add a command line step to my Task Sequence which I have simply created through the wizard. It is important to add the step after the windows image was applied:

    This will install all the Language Packs and other Feature on Demand Packs, which resides in the Package folder. This process is executed within the Windows PE phase of the Windows 10 Installation.
    Now, all the required Package are installed, and the system will be installed with a Base Language of US english, but with a Swiss-German Keyboard Layout (configured through the unattended.xml). The next step is to instruct Windows to use the German Language Pack as Default User Interface Language, and the regional settings should be changed to Switzerland as well. For this, I will implement the solution which Roger Zander (Twitter) is providing on his blog (see Source). I will outline the required steps below.
    The first step is to create the XML file which will be used in the next step. I just also add this XML file to my existent Language and FOD package (see Screenshot above). This is the content of the XML (copy from Rogers blog):


    <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="de-DE" />
    <gs:MUIFallback Value="en-US" />
    </gs:MUILanguagePreferences>

    <!--User Locale-->
    <gs:UserLocale>
    <gs:Locale Name="de-CH" SetAsCurrent="true" ResetAllSettings="false"/>
    </gs:UserLocale>

    <!--input preferences-->
    <gs:InputPreferences>

    <!--de-CH-->
    <gs:InputLanguageID Action="add" ID="0807:00000807" Default="true"/>

    <!--en-US-->
    <gs:InputLanguageID Action="remove" ID="0409:00000409"/>

    <!--de-DE-->
    <gs:InputLanguageID Action="remove" ID="0407:00000407"/>

    <!--fr-CH-->
    <gs:InputLanguageID Action="remove" ID="100c:0000100c"/>
    </gs:InputPreferences>

    <!--location-->
    <gs:LocationPreferences>
    <gs:GeoID Value="223"/>
    </gs:LocationPreferences>
    </gs:GlobalizationServices>

    Then add another step to your Task Sequence where you just start the following command:
    control intl.cpl,, /f:"lang_de-CH.xml"
    Make sure that you add this step after the Installation of Windows and Configuration Manager Client. This would look like the following picture:

    And then I’m mostly done with the Windows 10 Image itself. Removing Windows Store apps or other settings can be done afterwards, or within the Task Sequence too. But as written above I want to add the .Net 3.5 feature to the Task Sequence, so this leads to the last topic of this blog.

    Optional: Windows 10 with .Net feature
    I do also add the Windows 10 .Net feature within the Windows PE phase, and before the Language Packs get installed. First, you will need to create a package, that contains the payload of the .Net feature installation. Copy the SXS folder from a Windows 10 Installation Media to a Folder, from which you create a ConfigMgr package afterwards:

    Similar to the language pack package, I created a install.bat file, to start the installation with DISM, the command within the batch is outlined below:
    dism.exe /image:%OSD_System%\ /enable-feature /featurename:NetFx3 /source:%~dp0 /all
    Then create a package, and add a step to the task sequence after the Language Pack installation:

    As outlined in Rogers blog, the command will end with an exit code of 1, you should consider to add this exit code as a success-reboot required. You can add this exit code to the command line step:

    Results
    After the Task Sequence has finished, the system will welcome you with the correct language:


    The language settings are like configured within the xml:

    And also the .Net Feature is installed:

    Happy Windows 10 Deploying!


    SCCM – Configure a pointer record for your Cloud Management Gateway

    $
    0
    0

    Lets assume you want to set a pointer record (PTR) for your System Center Configuration Manager Cloud Management Gateway (CMG).

    First of all, you will need to install the “Azure PowerShell Service Management module”, and Login to your Tenant. This process is documented on the Microsoft Website:
    Installing the Azure PowerShell Service Management module

    When this is done, you may want to change the subscription, in my case it was necessary. To do so, simply show all of your subscriptions with “Get-AzureSubscription” and select the appropriate subscription with “Select-AzureSubscirtion” afterwards:

    When you have selected the correct subscription, you can list the Azure Services with “Get-AzureService”.
    With the following command, you can set the Pointer record for your CMG:
    Set-AzureService -ServiceName "YOURSERVICENAME" -ReverseDnsFqdn "HOSEBECMG01.hosebei.ch."