Deploying Microsoft .NET Framework 3.5 SP1 with System Center Configuration Manager

Today’s topic demonstrates building a Configuration Manager Application package with multiple deployment types. I assume familiarity with the basics of building ConfigMgr Applications here, so if you need some remedial reading, please review the Deploy and manage applications with System Center Configuration Manager topic on TechNet.

I will also be using Robocopy in this post. The documentation on TechNet is out of date for the most recent Windows versions, and it is incomplete. Run robocopy /? at a command prompt to get the usage information for your version of Windows. There are some excellent answers with links to better documentation on Super User.

The .NET Framework 3.5 is a prerequisite for Microsoft Office 2013 and 2016 as well as many other commercial and internal applications. It was a built-in operating system component in Windows 7, but in Windows 8 and higher, it is a Feature on Demand and is not included by default. It is still an operating system component, but its installation status is “Disabled with Payload Removed”. You can see this for yourself by running the following command from an administrative command prompt in Windows 8/Server 2012 or higher. On a Windows 8.1 installation, for example, the command and its output will be:

C:\>Dism /Online /Get-FeatureInfo /FeatureName:NetFx3

Deployment Image Servicing and Management tool
Version: 6.3.9600.17031
Image Version: 6.3.9600.17031

Feature Information:

Feature Name : NetFx3
Display Name : .NET Framework 3.5 (includes .NET 2.0 and 3.0)
Description : .NET Framework 3.5 (includes .NET 2.0 and 3.0)
Restart Required : Possible
State : Disabled with Payload Removed

Custom Properties:

FWLink : http://go.microsoft.com/fwlink/?LinkId=296822

The operation completed successfully.

The easy way for consumers to get the .NET Framework 3.5 on these platforms is to turn the feature on in Windows Features (same steps as in Windows 7), and Windows will then download the component from Windows Update.

The stated reason for this change was to decrease the Windows image size (install.wim). This is true: The Microsoft-supplied Windows images are indeed smaller for excluding .NET 3.5. Microsoft included all of the required files for .NET 3.5 in the sources\sxs folder in the ISO files and on the physical media that it distributes though, so this change really didn’t reduce the total size of the files that Microsoft delivers, and it made more work for you and me! There are options in Dism to install the .NET Framework 3.5 (hereafter, “NetFx3″—its feature name). (Note that feature names are case sensitive when used with Dism!) The following command installs NetFx3 from Windows Update just as if we had checked the box in Windows Features:

Dism /Online /Enable-Feature /FeatureName:NetFx3 /All

The following command installs NetFx3 using source files copied from the Windows installation media to the \\myserver\myshare file share:

Dism.exe /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:"\\myserver\myshare"

Installation of some programs that need NetFx3 will automatically trigger installation of the feature from Windows Update, but what if you are installing on a computer without access to the Internet and Microsoft’s servers? What if you are upgrading 20,000 Windows 7 computers to Windows 10 and don’t want to pay for the bandwidth to download NetFx3 20,000 times during your Office 2016 installation? (In the latter case, you could build a custom Windows 10 image with the feature installed, but maybe you don’t want to do that.) For these reasons, we will use the second approach shown above and depend on Configuration Manager to distribute the needed files for our .NET Framework 3.5 package. For more information about our chosen Dism command, see To restore removed Windows features in the TechNet article Enable or Disable Windows Features Using DISM.

Acquiring the Payload Files

Unfortunately, nearly every Windows version has a different payload for NetFx3. We will have to locate all of the needed files and copy them to a file share for access by Configuration Manager. Let’s get started.

On your application staging file share (wherever you put application source files for Configuration Manager to find), create a folder structure for .NET 3.5. Mine will be \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1. Under this folder, create a folder for each operating system version that will be supported. Note that the 64-bit client OSes can share source files with their server counterparts; I checked, and the NetFx3 files are the same.

Folder Name Description
Win6.1 Windows 7 and Windows Server 2008 R2 (64-bit and 32-bit)
Win6.2×86 Windows 8 (32-bit)
Win6.2×64 Windows 8 and Windows Server 2012 (64-bit)
Win6.3×86 Windows 8.1 (32-bit)
Win6.3×64 Windows 8.1 and Windows Server 2012 R2 (64-bit)
Win10.0.10240×86 Windows 10 RTM (32-bit)
Win10.0.10240×64 Windows 10 RTM (64-bit)
Win10.0.10586×86 Windows 10 November Update (32-bit)
Win10.0.10586×64 Windows 10 November Update (64-bit)

That’s right, folks: We will be building nine—yes, nine—deployment types for this one application package.

Get your DVDs or ISOs ready; it’s time to copy the NetFx3 payload files to the folders you just created! Skip Windows 7 and Windows Server 2008 R2 for now. Assuming that your Windows 8 32-bit installation media is available in drive D: (whether physical media or a mounted ISO), here is my preferred command to copy the files:

Robocopy "D:\sources\sxs" "\\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win6.2x86" /E /DCOPY:DAT /XJ

I prefer using Robocopy because it allows me to preserve the time stamps on any folders I am copying with the /DCOPY switch. (Note that the Windows 7 version of Robocopy does not have the appropriate options to accomplish this, so you will need to use Windows 8 or higher for this functionality.) File timestamps are preserved by default. The /XJ switch is not really necessary here, but I make it a habit to always use it to exclude junction points unless I know I need to copy a certain junction point. (If a junction point targets a containing folder, Robocopy will keep following the junction in an infinite loop, leaving quite a mess that is difficult to clean up. I’m making a note now to blog about this in the future!)

Use similar commands to copy the NetFx3 content from the Windows 8 64-bit, Windows 8.1 32-bit, and Windows 8.1 64-bit media to those operating systems’ respective folders in the folder structure we built above.

Windows 10 is different. It supplies NetFx3 as a single file on a separate Features on Demand DVD or ISO file. Use this command to copy the 32-bit Windows 10 Release payload for NetFx3:

Robocopy D:\ "\\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.10240x86" microsoft-windows-netfx3-ondemand-package.cab

Use similar commands to copy the NetFx3 content from the Windows 10 Release 64-bit, Windows 10 November Update (build 1511) 32-bit, and Windows 10 November Update (build 1511) 64-bit media to those operating systems’ respective folders.

Finally, let’s take care of Windows 7 and Windows Server 2008 R2. These versions of Windows include Microsoft .NET Framework 3.5.1 as a built-in operating system component. Note that .NET 3.5.1 is .NET 3.5 Service Pack 1 with a few additional bug fixes. The payload cannot be removed, so the feature is always present on disk, even if it has been turned off. Therefore, no installation files are required.

Configuration Manager must have source files for every deployment type, though. My solution was to create a text file with Notepad containing the following text and save it into the Win6.1 folder as readme.txt:

The Microsoft .NET Framework 3.5.1 (SP1 plus some additional fixes) is included in Windows 7 and Windows Server 2008 R2, so installation files are neither required nor available.

That explains the presence of the otherwise empty folder to anyone reviewing this folder structure.

Building the Configuration Manager Application

Windows 7 and Windows Server 2008 R2 (64-bit and 32-bit)

In the Configuration Manager Console, create a new Application. Here are the values I provided in mine:

Property Value
Application Properties
Name Microsoft .NET Framework 3.5 with Service Pack 1
Publisher Microsoft
Version 3.5 SP1
Deployment Type Properties
Name Feature Installation – Windows 7 and Windows Server 2008 R2 (64-bit and 32-bit)
Technology Script Installer
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win6.1\
Installation program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Enable-Feature /FeatureName:NetFx3 /NoRestart /Quiet
Uninstall program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Disable-Feature /FeatureName:NetFx3 /NoRestart /Quiet
Detection method Rule 1:
Hive/Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5
Value: Install
Data type: Integer
Equals 1
Rule 2:
Hive/Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5
Value: SP
Data Type: Integer
Equals 1
Installation behavior Installation behavior: Install for system
Logon requirement: Whether or not a user is logged on
Installation program visibility: Hidden
Configuration Manager behavior: Determine behavior based on return codes
Requirements Operating system
One of [all available Windows 7 versions selected], All Windows Server 2008 R2 (64-bit)

Take a look at the installation program:

"%SystemRoot%\System32\Dism.exe" /Online /LogLevel:4 /Enable-Feature /FeatureName:NetFx3 /NoRestart /Quiet

This is a fairly typical Dism command that turns on the built-in .NET 3.5 feature. There are several points to note, though. First, we are not using any files from our file share. We had to provide a content location with a minimum of one file in it (which was the readme.txt described above), but we don’t actually have to use it. Second, we are logging everything so that if something does go awry, we have a chance to begin investigation immediately with a log rather than having to try to reproduce the problem as a first troubleshooting step. Third, we prevent the program from restarting the computer or attempting to interact with the user, which are always the right (and necessary) decisions in Configuration Manager applications—especially those designed to serve as prerequisites for other applications.

The detection rules are taken directly from Microsoft Knowledge Base article, How to determine which versions and service pack levels of the Microsoft .NET Framework are installed.

For the requirements, I selected “All Windows Server 2008 R2 (64-bit)”, which covers that version with and without SP1, and I selected the topmost “Windows 7” node, which automatically selected all subnodes, indicating all service pack levels and bitnesses of Windows 7.

Windows 8 and Windows Server 2012

We have to actually provide the content for Windows 8 and Windows Server 2012. We already copied it to our target folder above. Here are the properties for two deployment types—one for 32-bit and one for 64-bit.

Property Value
Deployment Type Properties – Windows 8 (32-bit)
Name Feature Installation – Windows 8 (32-bit)
Technology Script Installer
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win6.2×86\
Installation program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:”.” /NoRestart /Quiet
Uninstall program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Disable-Feature /FeatureName:NetFx3 /NoRestart /Quiet
Detection method Same two rules as Windows 7 and Windows Server 2008 R2 deployment type
Installation behavior Same settings as Windows 7 and Windows Server 2008 R2 deployment type
Requirements Operating system
One of All Windows 8 (32-bit)
Deployment Type Properties – Windows 8 and Windows Server 2012 (64-bit)
Name Feature Installation – Windows 8 and Windows Server 2012 (64-bit)
Technology Script Installer
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win6.2×64\
Installation program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:”.” /NoRestart /Quiet
Uninstall program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Disable-Feature /FeatureName:NetFx3 /NoRestart /Quiet
Detection method Same two rules as Windows 7 and Windows Server 2008 R2 deployment type
Installation behavior Same settings as Windows 7 and Windows Server 2008 R2 deployment type
Requirements Operating system
One of All Windows 8 (64-bit), All Windows Server 2012 (64-bit)

The Dism command used as the installation program is little bit more involved than a normal feature change command because the NetFx3’s payload is not present by default. It differs from the Windows 7 and Windows Server 2008 R2 version because we are forcing the OS to use the source files (payload) that we are providing:

"%SystemRoot%\System32\Dism.exe" /Online /LogLevel:4 /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:"." /NoRestart /Quiet

Configuration Manager copies all subfolders and files of the Content location to a folder on the local hard drive for installation. We left the Installation start in property empty in our deployment types, so the Installation program is run with that local folder as the working directory. To point the Dism command to the current directory, we pass “.” to the Source switch. The LimitAccess switch prevents the OS from attempting to download the source files from Windows Update.

Windows 8.1 and Windows Server 2012 R2

The two 32-bit and 64-bit deployment types for Windows 8.1 and Windows Server 2012 R2 are nearly identical to those for Windows 8 and Windows Server 2012. As you construct these deployment types, make appropriate changes to the following properties:

  • Name
  • Content location
  • Requirements > Operating System

Windows 10

The properties for all four Windows 10 deployment types are very similar to those for Windows 8, 8.1, Server 2012, and Server 2012 R2. As with the Windows 8.1 and Windows Server 2012 R2 deployment types, you must make appropriate changes to the Name, Content location, and Requirements properties. We’ll use the custom Global Condition from my previous post in the Requirements. You must also alter the installation and uninstallation commands to reflect the different payload packaging method used by Windows 10. For any properties omitted below, use the same values as with Windows 8, etc.

Property Value
Deployment Type Properties – Windows 10 Release (32-bit)
Name Feature Installation – Windows 10 Release (32-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.10240×86\
Installation program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Add-Package /PackagePath:”microsoft-windows-netfx3-ondemand-package.cab” /NoRestart /Quiet
Uninstall program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Remove-Capability /CapabilityName:NetFx3~~~~ /NoRestart /Quiet
Requirements Operating system
One of All Windows 10 Professional/Enterprise and higher (32-bit)
OS BuildNumber Equals 10240
Deployment Type Properties – Windows 10 Release (64-bit)
Name Feature Installation – Windows 10 Release (64-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.10240×64\
Installation program Same as Windows 10 Release (32-bit)
Uninstall program Same as Windows 10 Release (32-bit)
Requirements Operating system
One of All Windows 10 Professional/Enterprise and higher (64-bit)
OS BuildNumber Equals 10240
Deployment Type Properties – Windows 10 November Update (32-bit)
Name Feature Installation – Windows 10 Version 1511 (32-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.10586×86\
Installation program “%SystemRoot%\System32\Dism.exe” /Online /LogLevel:4 /Add-Package /PackagePath:”Microsoft-Windows-NetFx3-OnDemand-Package.cab” /NoRestart /Quiet
Uninstall program Same as Windows 10 Release (32-bit)
Requirements Operating system
One of All Windows 10 Professional/Enterprise and higher (32-bit)
OS BuildNumber Equals 10586
Deployment Type Properties – Windows 10 November Update (64-bit)
Name Feature Installation – Windows 10 Version 1511 (64-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.10586×64\
Installation program Same as Windows 10 November Update (32-bit)
Uninstall program Same as Windows 10 Release (32-bit)
Requirements Operating system
One of All Windows 10 Professional/Enterprise and higher (64-bit)
OS BuildNumber Equals 10586

You may have noticed that I used the Capability options in Dism for the uninstallation commands but not for the installation commands. This nomenclature is new in Windows 10 as part of Features on Demand v2. Unfortunately, there is a bug in the /Add-Capability switch, so I used the /Add-Package switch as with earlier version for installation and used the new switch for the uninstallation. See the From the Media and From the Media: A Convenient Workaround sections of Michael Niehaus‘s blog post, Adding features (including .NET 3.5) to Windows 10 for details.

You may have also noticed that the release and November Update installation commands are identical except for the CAB filename character case. It’s true that case doesn’t usually matter in filenames on Windows, but I like to match the character case of the actual file; Microsoft used all small letters in the initial release and title casing in the November Update for the NetFx3 feature’s CAB file, and the property values listed above match those choices.

Coming Up

Next time, we’ll do this all over again for Microsoft .NET Framework 4.6.1.

Building a Global Condition in System Center Configuration Manager to Test the Windows Build Number

Configuration Manager doesn’t provide a way to differentiate between releases of Windows 10 when specifying requirements for an application package, but the Microsoft .NET Framework 3.5 feature source file differs between the two builds available at the time of this writing. (This may be true of all of Windows 10’s Features on Demand, but I haven’t checked any others.) We will also need a way to tell different releases of Windows 10 apart when installing .NET Framework 4.6.1. Therefore, we must make a custom Global Condition to provide the needed functionality for our application packages.

We need to find some attribute of the operating system that is unique between Windows 10 releases to test in our Global Condition . It turns out that Windows Management Instrumentation (WMI) has a property that we can use: the BuildNumber property of the Win32_OperatingSystem class. This returns—you guessed it—the Windows build number. Even though the build number is, well, a number, WMI defines this property as a string, so keep this in mind if you want to do value comparisons. For example, 10 > 9 (numeric comparison) but “10” < “9” (string comparison).

Global Conditions in Configuration Manager are located in the Software Library workspace under Application Management. I named my Global Condition “OS BuildNumber”, and here are its properties:

Property Value
Name OS BuildNumber
Description Returns the Windows build number from WMI.
Device type Windows
Condition type Setting
Setting type WQL Query
Data type String
Namespace root\cimv2
Class Win32_OperatingSystem
Property BuildNumber
WQL query WHERE clause None (leave blank)

Coming Up

Next time, we’ll use this new Global Condition to specify an installation requirement for a Configuration Manager Application deployment type.

Deploying Microsoft Office 2016: Overview and Prerequisites

I work for a large university in the midwestern United States, where part of my job is building operating system images and application packages for deployment with Microsoft System Center Configuration Manager. It is a lot of work to plan and build a high-quality, reliable deployment, and so I thought I would start my blog by documenting the process of building a set of Configuration Manager application packages for the latest version of one of the most commonly deployed applications on the planet: Microsoft Office. Numerous blogs have helped me to do my job, and it is my hope that this blog will be a worthy gift back to the online software deployment community.

Although Microsoft Office 2016 has been available for several months, there has not been an outcry for upgrades in my organization. We avoid making changes while classes are in session, so major upgrades tend to be scheduled in the downtime between the summer and fall semesters. I suspect, therefore, that the university will move to the new version in summer 2016, which gives me the time to document the required planning and testing here. We have licensed Microsoft Office Professional Plus 2016; we are not using the Office 365 offering.

Application Packaging Guidelines

Goal: Build a reliable Microsoft Office Professional Plus 2016 application package in System Center Configuration Manager for deployment across multiple operating system versions.

I will explain my philosophy of application packaging and deployment fully in a later post, but for now, I will just list these brief rules for applications deployed through Configuration Manager’s Software Center:

  • Installation must be silent.
  • The application package must account for all possible dependencies.
  • The installation must be reversible.
  • First-run prompts must be minimized or preferably eliminated.

Hardware Requirements and Prerequisite Software

Let’s start by taking a look at the System requirements for Office 2016. This will tell us the hardware requirements, which we will need later when building our application package, and any prerequisite software. We must either test for the presence of prerequisite software or build separate application packages for that software. My university has licensed Office Professional Plus, so I will focus on that edition’s requirements. Here they are:

From <https://products.office.com/en-us/office-system-requirements>
COMPONENT REQUIREMENT
Computer and processor 1 gigahertz (GHz) or faster x86-bit or x64-bit processor with SSE2 instruction set
Memory 2 GB RAM
Hard disk 3.0 GB available disk space
Display 1280 x 800 screen resolution
Graphics Graphics hardware acceleration requires a DirectX 10 graphics card.
Operating system
Windows 10, Windows 8.1, Windows 8, Windows 7 Service Pack 1, Windows 10 Server, Windows Server 2012 R2, Windows Server 2012, or Windows Server 2008 R2
For the best experience, use the latest version of any operating system.
Browser The current or immediately previous version of Internet Explorer; the current version of Microsoft Edge, Safari, Chrome, or Firefox.
.NET version
.NET 3.5 required. Some features may require .NET 4.0, 4.5, or 4.6 CLR to also be installed.
Other Internet functionality requires an Internet connection. Fees may apply.
A touch-enabled device is required to use any multi-touch functionality. But, all features and functionality are always available by using a keyboard, mouse, or other standard or accessible input device. Note that touch features are optimized for use with Windows 8, Windows 8.1 or Windows 10.
Product functionality and graphics may vary based on your system configuration. Some features may require additional or advanced hardware or server connectivity.

I highlighted the portions that interest me right now; we’ll come back to the hardware requirements later.

At my university, there is little top-down direction regarding which operating system version should be used, and so I must plan to support all of the listed operating systems in order for my application package to be useful to the entire organization. Unfortunately, that means I have to ensure compatibility with ten client operating systems and three server operating systems:

  • Windows 7 SP1 (huge installed base in my organization) (64-bit and 32-bit)
  • Windows 8 (hopefully no one is running this, but we need to support it anyway) (64-bit and 32-bit)
  • Windows 8.1 (small installed base in my organization) (64-bit and 32-bit)
  • Windows 10 RTM (hopefully no one is running this, but we need to support it anyway) (64-bit and 32-bit)
  • Windows 10 November Update v1511 (small installed base, but our platform of choice for all new installations and reinstallations beginning in summer 2016) (64-bit and 32-bit)
  • Windows Server 2008 R2
  • Windows Server 2012
  • Windows Server 2012 R2

I only worry about software that has actually been released, so the next version of Windows Server is irrelevant at the time of this writing. Also, yes, I know that installing Office on Windows Server is a terrible idea, but Microsoft supports it, so my application package will support it.

You may be wondering why I am so concerned about the operating systems when the Office team has taken care of operating system support. The answer lies in the prerequisites. The various versions of the .NET Framework are installed differently on different operating systems. Each of the required .NET Framework versions must have its own application package in Configuration Manager to act as a prerequisite to the main Office 2016 package. I will cover building the .NET application packages in future posts.

Browser support is less of an issue. Windows 10, 8.1, and Server 2012 R2 have Internet Explorer 11 built in; Windows 8 and Server 2012 have Internet Explorer 10 built in. Both of these IE versions satisfy the requirements. For Windows 7 and Server 2008 R2, we’ll either have to build an IE11 application package or set a condition that checks for IE10 or IE11. My initial thought is to just set a condition because if any Windows installation is on an old version of IE at this point (January 2016), then the user or administrator has specifically blocked it from being installed in Windows Update as well as in the settings of IE itself, and so we should respect that decision and just fail the Office installation. (If I change my mind about this, you’ll find out in a future post.)

Coming Up

The .NET Framework packages are large and complex. They are also applicable to other applications besides Office, so I will cover them first. Next time, we’ll build a single .NET Framework 3.5 SP1 package that works for all 13 platforms listed above. After that, we’ll build a .NET 4.6.1 package. Finally, because Office’s .NET 4.x version requirement is flexible—any version that starts with ‘4’ is OK—we’ll build a package that does the minimum amount of work for a given platform in order to satisfy that requirement, and we will make use of the .NET 4.6.1 package source for platforms that don’t have .NET 4.x included as an OS component.