Deploying Any Supported Version of Microsoft .NET Framework 4.x as a Prerequisite Application

Several weeks ago, I described how to ensure that some version of the .NET Framework 4.x would be installed on any version of Windows from 7 through 10. This was accomplished by installing the latest version on Windows 7 (.NET 4.6.1) and just ensuring that the built-in .NET version was turned on in all other versions of Windows. I used this method for performance and stability. If a program can use any 4.x version of .NET, then using whatever is already there is faster than installing a newer version; avoiding unnecessary upgrades makes it less likely that the process will break some other program. (Admittedly, the chance of breakage is small with .NET 4.x, but I think this is a good general principle.) I published that blog post on Monday, February 1; unfortunately, I was unaware that Microsoft had announced, months previous, that support for all 4.x versions of .NET prior to version 4.5.2 would end on January 12, 2016.

When I discovered that announcement, I rethought my strategy for providing this prerequisite package. I decided that instead of using the application package I described previously, I would rather use an application package that ensures that some supported version of the .NET Framework 4.x would be installed. That application package is the subject of this post.

Update from 2016-03-20

Subsequent to this post’s initial publication, I completed all of the application packages and task sequences for my Office 2016 series, and I discovered in testing that the .NET 4.6.1 executable installer would not function correctly on 32-bit versions of Windows when run in a task sequence! On all supported versions of 32-bit Windows, running NDP461-KB3102436-x86-x64-AllOS-ENU.exe /q /norestart results in an exit code of 16389 when run in a task sequence, and the framework is not installed. This registers as a failure to the Configuration Manager client and causes the task sequence to fail. This failure occurs regardless of the state of the Run installation and uninstall program as 32-bit process on 64-bit clients checkbox, which shouldn’t have any effect on 32-bit OSes, but which I tried anyway in troubleshooting. The same command line run on 64-bit Windows in a task sequence also failed with the same exit code if that checkbox was unchecked, but checking the box made it work.

At publication on 2016-02-29, this post described a single deployment type for all versions of Windows previous to Windows 10, and this worked when installed from Software Center on all supported operating systems. Due to the problems described above when installation was run as a task sequence step, I subsequently had to add an additional deployment type for 32-bit Windows. I also originally passed the parameter /ChainingPackage ADMINDEPLOYMENT, but I removed it in the course of troubleshooting and never put it back.

Acquiring the Installation Files

If you’ve been following along with my Deploying Office 2016 series, you’ll find that we already have everything we need. We’ll test for the minimum supported .NET version of 4.5.2, which was not included as an OS component in any version of Windows. For computers without this version or higher, we’ll reuse our .NET 4.6.1 application package from a few weeks ago to bring them up to the latest version. Windows 10 v1507 includes .NET 4.6, and Windows 10 v1511 includes .NET 4.6.1. The NetFx4 feature cannot be disabled in those OSes, so we’ll have a special deployment type for Windows 10 that basically just detects those OS versions.

On your application staging file share (wherever you put application source files for Configuration Manager to find), create a folder for .NET 4.x. Mine will be \\fileserver\software$\Microsoft\.NET Framework 4.x. We’ll use this folder for Windows 10, so we don’t actually need any source files. As we did with .NET 3.5 on Windows 7 and .NET 4.6.1 on Windows 10 v1511, we will just provide Configuration Manager with a single file in that folder. I used Notepad to create a text file named readme.txt in the folder containing the following text:

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

Building the Configuration Manager Application

Windows 7, 8, 8.1 (64-bit), Windows Server 2008 R2 SP1, 2012, 2012 R2 (64-bit, full installations)

In the Configuration Manager Console, create a new Application. We are going to reuse the source folder and settings from our .NET 4.6.1 application package for our first deployment type. Here are the values I provided in mine:

Property Value
Application Properties
Name Microsoft .NET Framework 4.5.2 or higher
Publisher Microsoft
Version 4.x
Deployment Type Properties
Name Microsoft .NET Framework 4.6.1 – Windows 7, 8, 8.1, Server 2008 R2 SP1, 2012, 2012 R2 (64-bit, full installations)
Technology Script Installer
Administrator comments Detects whether a supported version of .NET 4.x is installed (4.5.2 and higher). If any targeted OS does not have .NET 4.x or has an unsupported version of .NET 4.x, install .NET 4.6.1. This deployment type cannot be uninstalled because it registers as installed for multiple minor versions of the .NET Framework 4.x; to remove .NET 4.x, uninstall the exact version in Software Center (if present) or in Programs and Features.
Content location \\fileserver\software$\Microsoft\.NET Framework 4.6.1\PreWin10v1511\
Installation program "NDP461-KB3102436-x86-x64-AllOS-ENU.exe" /q /norestart /ChainingPackage ADMINDEPLOYMENT
Uninstall program None (leave blank)
Run installation and uninstall program as 32-bit process on 64-bit clients Checked
Detection method See below.
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 Windows 7 SP1 (64-bit), Windows 2008 R2 SP1 (64-bit), All Windows 8 (64-bit), All Windows Server 2012, All Windows 8.1 (64-bit), Windows Server 2012 R2
CPU speed: Greater than or equal to 1000 MHz
Total physical memory: Greater than or equal to 512 MB
Free Disk Space of system drive: Greater than or equal to 2560 MB
OS Installation Type: Not equal to Server Core
Return Codes 0 Success (no reboot) Installation completed successfully.
1602 Failure (no reboot) The user canceled installation.
1603 Failure (no reboot) A fatal error occurred during installation.
1641 Hard reboot A restart is required to complete the installation. This message indicates success.
3010 Soft reboot A restart is required to complete the installation. This message indicates success.
5100 Failure (no reboot) The user’s computer does not meet system requirements.

The detection logic for this deployment type is complex.

Connector ( Clause )
LocalMachine\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\Release Greater than or equal to 379893.
And ( LocalMachine\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion Equals 6.1.
Or  LocalMachine\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion Equals 6.2.
Or ( LocalMachine\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion Equals 6.3.
And LocalMachine\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuild Equals 9600. ))
 And  LocalMachine\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE Equals Amd64

This deployment type’s properties are basically the same as those in our .NET 4.6.1 Application except for the detection logic. Remember that the .NET 4.6.1 setup program doesn’t work for Server Core installations, so those are excluded here under Requirements. This application package has a user-friendly name because it is displayed during task sequence deployment, but because it does not represent an exact version of an application, and because it cannot be uninstalled, it doesn’t make sense to deploy this application directly to devices or users. Don’t deploy this Application on its own; just set it as a prerequisite for other Applications that need it, or include it as a step in a task sequence.

Now let’s look at the complicated detection method. What’s happening here? First, we don’t actually test for version 4.6.1; instead we test that a minimum of .NET 4.5.2 is installed; that’s build 379893 stored in the Release registry value. (See How to: Determine Which .NET Framework Versions Are Installed on MSDN for build numbers.) Then we verify that the OS version is less than that of Windows 10, since this deployment type doesn’t apply to Windows 10. The CurrentVersion registry value works for Windows 7 (6.1) and 8 (6.2), but it does not work for Windows 8.1 (6.3). In its latest attempt to mitigate version-check bugs in other vendors’ applications, Microsoft no longer updates this registry value. Both versions of Windows 10 released so far, as well as Windows 8.1, have a CurrentVersion registry value of 6.3. To verify that the OS is really Windows 8.1, we must also check that the build number is 9600.

To build this detection logic, add each clause in the order shown. Then adjust the Connectors as needed by clicking on the word to give it focus; it changes to a drop-down menu from which you can choose which verb you want. Group the Windows 8.1 detection by selecting the “6.3” and “9600” lines and then clicking the Group button. Finally, group all of the operating system detection logic by selecting everything except the top and bottom lines and clicking the Group button.

Windows 7, 8, 8.1 (32-bit)

Due to the inability of the .NET 4.6.1 executable installer to function when run by a ConfigMgr task sequence, it is necessary to extract the files for 32-bit versions. This works, but it has the unfortunately effect of creating a huge installation source due to Microsoft’s needless bloating of the installation packages.

On your application staging file share (wherever you put application source files for Configuration Manager to find), create a new folder for the extracted 32-bit .NET 4.6.1 files. Mine will be \\fileserver\software$\Microsoft\.NET Framework 4.6.1\PreWin10v1511x86. Use 7-Zip to extract the contents of NDP461-KB3102436-x86-x64-AllOS-ENU.exe into the folder you just created. Then delete the huge, hundreds-of-megabyte files than end in “x64”. Since this folder is only for 32-bit content, we can save quite a bit of space by getting rid of what we don’t need.

Then create a new deployment type for 32-bit client operating systems.

Property Value
Deployment Type Properties
Name Microsoft .NET Framework 4.6.1 – Windows 7, 8, 8.1 (32-bit)
Technology Script Installer
Administrator comments Detects whether a supported version of .NET 4.x is installed (4.5.2 and higher). If any targeted OS does not have .NET 4.x or has an unsupported version of .NET 4.x, install .NET 4.6.1. This deployment type cannot be uninstalled because it registers as installed for multiple minor versions of the .NET Framework 4.x; to remove .NET 4.x, uninstall the exact version in Software Center (if present) or in Programs and Features.
Content location \\fileserver\software$\Microsoft\.NET Framework 4.6.1\PreWin10v1511x86\
Installation program "Setup.exe" /x86 /x64 /redist /q /norestart
Uninstall program None (leave blank)
Run installation and uninstall program as 32-bit process on 64-bit clients Unchecked
Detection method Same as 64-bit deployment type except for the last line, which is:
LocalMachine\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE Equals x86
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 Windows 7 SP1 (32-bit), All Windows 8 (32-bit), All Windows 8.1 (32-bit)
CPU speed: Greater than or equal to 1000 MHz
Total physical memory: Greater than or equal to 512 MB
Free Disk Space of system drive: Greater than or equal to 2560 MB
OS Installation Type: Not equal to Server Core
Return Codes Same as 64-bit deployment type.

When NDP461-KB3102436-x86-x64-AllOS-ENU.exe is passed the parameters /q /norestart,  it extracts the contents and runs Setup.exe /x86 /x64 /redist /q /norestart. Since we extracted the content already to get around the bug in the self-extracting executable that prevents it from running in a task sequence, we use that command line as the installation command.

The detection method rules are the same as with the 64-bit deployment type except that the last line is adjusted to detect the x86 platform. The operating system requirements are similarly adjusted to only allow installation on 32-bit operating systems.

Windows 10 (64-bit and 32-bit)

All releases of Windows 10 can be handled by a single deployment type. The NetFx4 feature cannot be disabled in Windows 10, so this deployment type has nothing to do except detect the operating system version. We’ll verify the .NET 4.x version as well for good measure, but that test should never fail in a healthy system.

Property Value
Deployment Type Properties
Name NetFx4 Unremovable Feature – Windows 10 (64-bit and 32-bit)
Technology Script Installer
Administrator comments Windows 10 RTM includes .NET 4.6, and Windows 10 November Update includes .NET 4.6.1. The NetFx4 feature cannot be turned off in Windows 10, so this deployment type performs no installation.
Content location \\fileserver\software$\Microsoft\.NET Framework 4.x\
Installation program "%SystemRoot%\System32\cmd.exe" /C type readme.txt
Uninstall program None (leave blank)
Detection method Rule 1:
Hive/Key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
Value: Release
Data type: Integer
Greater than or equal to 393295
Rule 2:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
Value: CurrentMajorVersionNumber
Data type: Integer
Greater than or equal to 10
Installation behavior Same settings as other deployment type. See table above.
Requirements Operating system
One of Windows 10
Return codes Leave defaults

For the installation program, we just display the contents of a text file. This should never actually run, and even if it did, no one would see it because the deployment type is hidden. The detection logic uses a new registry value in Windows 10, CurrentMajorVersionNumber, to ensure that the OS is Windows 10, and it checks that the .NET 4.x version is 4.6 at minimum.

Coming Up

Next time, we’ll take care of one more prerequisite application before we put everything together to build a set of Configuration Manager Applications for 32-bit and 64-bit versions of Office, Project, and Visio.

<update date=”2016-03-20″>Added new deployment type for 32-bit Windows versions and explanatory text describing the reason for the change.</update>

<update date=”2016-04-17″>Revised the “Coming Up” section for accuracy.</update>

4 thoughts on “Deploying Any Supported Version of Microsoft .NET Framework 4.x as a Prerequisite Application”

  1. Failed to get associated command string for .exe”, error code 80070483 AppEnforce 11/29/2016 11:59:45 PM 5356 (0x14EC)
    PrepareCommandline failed with 0x80070483 for cmdline “NDP461-KB3102436-x86-x64-AllOS-ENU.exe” /q /norestart AppEnforce 11/29/2016 11:59:45 PM 5356 (0x14EC)

    When trying to deploy 4.6.1 on an x64 system even with the box checked inside or outside of a task sequence. Any ideas?

    1. Hi Sanjay. I have not experienced the errors you are getting with this application object, and no brilliant insights are springing to mind. ? It has been a while since you posted. Did you ever solve your problem? If so, I would be interested to know what happened.

Leave a Reply