Modifying PaperCut NG Client to install in the system context via Microsoft Intune

Overview

This post builds on my previous post about PaperCut NG Client. You may want to go read that post first to get some context.

PaperCut NG Client’s Windows Installer (MSI) file has had a bug for months and months, over several version releases, where it is not recognized by Intune as a system-installable app. From the product manual:

There is a known issue with the .msi file not allowing an Administrator to specify in Microsoft Intune which context an Administrator can install the application to.

This would be easy for the company to fix, but for whatever reason, it has not done so. To fix it yourself for your organization, continue reading!

The Cause

The Windows Installer file does not set the ALLUSERS property. For most MSI files, the ALLUSERS property should be set to 1 to specify a system-level installation. If the value is an empty string, then Windows Installer treats it as a per-user installation. Because this property is not even defined in the PaperCut NG installer, it is treated as if it were set to an empty string. The installer itself is coded in such a way that the files are written to per-computer locations anyway, so the installation works fine when run manually.

When you run the Microsoft Win32 Content Prep Tool to generate an INTUNEWIN file for upload into Intune, though, that tool notes the lack of the ALLUSERS property (just like Windows Installer itself would) and generates metadata in the INTUNEWIN file limiting the installer to per-user installations. That’s what causes the problem with Intune, and that is what you are manually changing when you follow the published workaround (described in a video on the same web page right below the notice of the bug).

The Solution

Normally, you can pass any property to a Windows Installer file on the command line at the time of installation. Unfortunately, the Win32 Content Prep Tool is not capable of accepting properties as parameters; it only reads what is built into the file. We can’t even make a transform file like last time because, again, a transform file is specified on the command line at the time of installation as a property parameter. To fix this issue, we must directly edit the MSI file.

The following steps assume that you have the environment described in my previous post set up. You don’t have to follow these steps exactly; for example, I am removing the original MSI file from the source and replacing it with a differently-named file, but you could leave both there if you wanted to.

  1. Move the MSI file to a new folder and make a working copy:
    md "%USERPROFILE%\Downloads\PCClient\Original MSI"

    move "%USERPROFILE%\Downloads\PCClient\win\pc-client-admin-deploy.msi" "%USERPROFILE%\Downloads\PCClient\Original MSI\"

    copy "%USERPROFILE%\Downloads\PCClient\Original MSI\pc-client-admin-deploy.msi" "%USERPROFILE%\Downloads\PCClient\Original MSI\pc-client-admin-temp.msi"
  2. If you made the transform file described in my previous post, I suggest that you move it as well:
    move "%USERPROFILE%\Downloads\PCClient\win\PCClientAutorun.mst" "%USERPROFILE%\Downloads\PCClient\Original MSI\"
  3. Run Orca.exe
  4. Open “%USERPROFILE%\Downloads\PCClient\Original MSI\pc-client-admin-temp.msi”.
  5. Since we’re editing the MSI file, we are defining a new package, so we must specify a new package code. Navigate to View menu > Summary Information…, and click New GUID to replace the package code. Then click OK.
  6. Select the Property table.
  7. Tables menu > Add Row…, and create a new row with these values:
    • Property: ALLUSERS
    • Value: 1

Optional: Merge the MST Settings

Now here is the optional part. Since we are creating a new MSI file anyway, there is no reason to keep depending on a transform file for other behavior. If you want the program to run automatically at user sign-in, and if you created the transform file as described in my previous post, you can apply the transform file the MSI file. Then you won’t need the transform file at installation time because its settings will be baked into the MSI itself.

  1. Transform menu > Apply Transform…, and choose the PCClientAutorun.mst file. You should see green bars beside the Component, FeatureComponents, Property, and Registry tables, indicating that changes are present.
  2. File menu > Save Transformed As…, and save the file with a new name, such as “pc-client-admin-myorg.msi” (replacing “myorg” with an abbreviation for your organization). Be sure not to overwrite the original file from the vendor, as that is your unchanged reference version.

Finishing Up

  1. If you skipped the optional steps above: File menu > Save, then close Orca, and rename the file to something without the word “temp” in it, such as “pc-client-admin-myorg.msi” (replacing “myorg” with an abbreviation for your organization).
  2. If your organization has a code-signing certificate, I recommend signing the new MSI file.
  3. Copy the new MSI into the folder with the rest of the installation files:
    copy "%USERPROFILE%\Downloads\PCClient\Original MSI\pc-client-admin-myorg.msi" "%USERPROFILE%\Downloads\PCClient\win\"

That’s it! You fixed the Intune issue by adding ALLUSERS=1, and you optionally integrated the transform file settings from the previous post directly into the new MSI. You should be able to upload the new MSI into Intune following the normal procedure.

Posts in this series:

  1. Transforming PaperCut NG Client installer to run the program automatically
  2. Modifying PaperCut NG Client to install in the system context via Microsoft Intune

Transforming PaperCut NG Client installer to run the program automatically

Overview

This is a quick demonstration of modifying application behavior at installation time when the app uses Windows Installer. It is not a deep dive but will include some links along the way for further study.

Well-behaved programs don’t force undesirable behavior on users. That’s why I’m normally opposed to programs setting themselves to run automatically without the user’s permission. I didn’t mention this in my earlier post, Providing a Great Software Deployment Experience, but let me add to my list of Guidelines for Great User Experience in that post that installers should let the user decide whether the program should automatically run at computer startup or user sign-in. This should be implemented as a Windows Installer property overridable on the command line so that IT staff can make that choice during unattended installation.

Here, I am focusing on an app whose installer does not configure it to run automatically. That’s good at first glance. An important characteristic of this app, though, is that if you have installed it, you probably want it running all the time. The app is the PaperCut NG Client, and it is the user-facing component of the PaperCut NG printing management system. Organizations implement this to providing accounting around printer costs, among other functions. The client notifies users of printing quota and prompts for approval of printouts, so that users are aware of how much they or their departments will be charged for each printout. If a user tries to print to a printer controlled by PaperCut NG, but they don’t have this app running, they will not be prompted for approval, and so the print job will never be sent to the printer. (Behavior may vary depending on configuration; I’m describing how it works with my organization’ configuration.) This will make users sad and very liable to call for support.

Therefore, IT staff want this app running all the time on any computer where it is installed. The problem is that this app’s installer does not provide a way to make it automatically run. At my organization, we work around this by using Group Policy to run the program as user sign-in:

  • Group Policy setting: User Configuration > Policies > Administrative Templates > System > Logon > Run these programs at user logon
  • Item: C:\Program Files\PaperCut NG Client\pc-client.exe –silent

This has the unfortunate effect of separating the “automatically run” behavior mandate by IT from the collection of computers where the software is installed. IT must ensure that, over time, both the policy and the app are always applied to the same set of computers. It would be better to have the behavior built into the installer, and that is the subject of the rest of this post.

Approach

I am not going to try to teach the Windows Installer system and file format here; whole books have been written about it, and it is documented extensively on Microsoft Learn. The minimum you need to understand here is that Windows Installer installs a set of features, and features are composed of components. Typically, every individual file or registry value needed by the app is defined as a separate component in the Windows Installer file, which always has an “msi” (Microsoft installer) extension.

The approach here will be to transform the vendor-supplied Windows Installer file so that it adds the command line above to one of the standard “Run” keys in the registry at installation time. I will do this by applying a transform file (*.mst) to it the installer file supplied by the vendor. This is a way to alter the behavior of the installer file without editing it directly. That makes the altered settings shareable and leaves the integrity of the vendor’s digitally signed installer file intact.

If you are building your own MSI from scratch (such as if you work at PaperCut), you should consider keeping the default of not running things automatically without the user’s consent, and you should provide a property settable at the command line or through the installer’s user interface so the user can override your default setting. Since I am not the vendor in this case, I am just going to make the change; if I don’t want the change, I won’t apply the transform file. A property would not provide additional value for me, since I have to make the effort of building a transform file already.

Gather Software and Tools

  1. Copy the client software from your organization’s PaperCut NG server. For example, if your PaperCut NG server is “papercutsvr”, and you want to work in your Downloads folder:
    Robocopy "\\papercutsvr\PCClient\win" "%USERPROFILE%\Downloads\PCClient\win" /E /J /DCOPY:DAT /XJ
  2. Install Orca, the Windows Installer database editor, using Windows Package Manager, from an elevated Command Prompt:
    winget install Orca

Create the Windows Installer Transform File

Follow these steps to build a windows Installer transform file that configures PaperCut NG Client to run automatically for all users.

NOTE: I plan to build on what I am doing here in a future post to address another issue with the PaperCut NG Client installer. Keep reading below to understand what I am doing and to create the transform file yourself, but be aware that I plan to provide the finished transform file with an additional bug fix next time. If you can wait, you can avoid the work.

  1. Run Orca.exe
  2. Open “%USERPROFILE%\Downloads\PCClient\win\pc-client-admin-deploy.msi”, and select the option “Open as read-only”. This prevents you from accidentally modifying the installer file provided by the vendor.
  3. Open Windows PowerShell (or the newer PowerShell—either one works for this), and use the New-Guid cmdlet to generate a new GUIDs for use as the identifier for our new component and as the identifier for our new registry value.

    The following will create the registry identifier in the same format as others in the MSI file:
    "reg$((New-Guid).ToString().ToUpper())" -replace '-'

    The following will create the component GUID in the same format as other GUIDs in the PaperCut NG Client MSI file:
    "{$((New-Guid).ToString().ToUpper())}"
  4. In Orca, select Transform menu > New Transform.
  5. Select the Registry table.
  6. Tables menu > Add Row…, and create a new row with these values:
    • Registry: [Paste the registry identifier generated above.]
    • Root: 2
    • Key: SOFTWARE\Microsoft\Windows\CurrentVersion\Run
    • Name: PaperCutNG
    • Value: "[APPLICATIONROOTDIRECTORY]pc-client.exe" --silent
    • Component_: RunAtSignIn
  7. Select the Component table.
  8. Tables menu > Add Row…, and create a new row with these values:
    • Component: RunAtSignIn
    • ComponentId: [Paste the component GUID generated above.]
    • Directory_: APPLICATIONROOTDIRECTORY
    • Attributes: 260
    • Condition: [Leave blank.]
    • KeyPath: [Paste the registry identifier generated above.]
  9. Select the FeatureComponents table.
  10. Tables menu > Add Row…, and create a new row with these values:
    • Feature_: PCClient
    • Component_: RunAtSignIn
  11. Transform menu > Generate Transform, and save the transform file in the same folder as the MSI file as “PCClientAutorun.mst”.

Deployment

Now, when deploying PaperCut NG Client, you must apply the transform file to get the autorun behavior. The command line with verbose logging will be:
msiexec /package pc-client-admin-deploy.msi /quiet /norestart TRANSFORMS=PCClientAutorun.mst /l*v "%TEMP%\PaperCutNGClientLog.txt"

Once this is installed across your organization, the PaperCut NG Client will run automatically at user sign-in wherever it is installed, and you can remove any existing measures to make that happen, such as Group Policy settings or logon scripts.

Next time, I’ll combine the modifications above with a bug-fix to allow the PaperCut NG Client to install in the system context when delivered via Microsoft Intune, and I will make my final transform file available for you to use so you don’t have to do most of the work described above.

Posts in this series:

  1. Transforming PaperCut NG Client installer to run the program automatically
  2. Modifying PaperCut NG Client to install in the system context via Microsoft Intune

<update date=”2023-12-08″>Added link to the second post in the series and struck the offer to supply an MST file.</update>

Deploying Microsoft .NET Framework 3.5 SP1 to Windows 10 Anniversary Update and Windows Server 2016 with System Center Configuration Manager

With the August 2016 release of Windows 10 version 1607 (“Anniversary Update”) and the initial release of Windows Server 2016 in October 2016, it is well past time to revisit last year’s entry on deploying the .NET Framework 3.5 SP1. Although Windows Server 2016 was released two months after its corresponding Windows 10 release, both have the same year-month version number of “1607”, and their build numbers are also identical: 14393. This is excellent news because it suggests that we may be able to use the same files for installing .NET 3.5 on both operating systems; indeed, investigation shows that the Microsoft-Windows-NetFx3-OnDemand-Package.cab files found under sources\sxs on the installation media for Windows 10 v1607 64-bit and Windows Server 2016 are identical.

Please refer to my January 2016 entry on building the Configuration Manager application for .NET 3.5 SP1 if you need to start from scratch. Below, I will add to that Configuration Manager application.

Acquiring the Payload Files

Remember, 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. In this case, we’ll just add to what we built before.

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

Folder Name Description
Win10.0.14393×86 Windows 10 Anniversary Update (32-bit)
Win10.0.14393×64 Windows 10 Anniversary Update and Windows Server 2016 (64-bit)

We are only adding two deployment types to our existing ConfigMgr application, but they will bring the total count of deployment types to 11.

Get your DVDs or ISOs ready; it’s time to copy the NetFx3 payload files to the folders you just created! Assuming that your Windows 10 v1607 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:

I prefer using Robocopy because it allows me to preserve the time stamps on any folders I am copying with the /DCOPY switch. Use a similar command to copy the NetFx3 content from the Windows 10 v1607 64-bit media to its folder in the folder structure we built above.

You can also get the files from the Features on Demand ISO available from the Microsoft Volume Licensing Service Center. In that case, use this command to copy the 32-bit Windows 10 Anniversary Update payload for NetFx3:

Building the Configuration Manager Application

Windows 10 and Windows Server 2016 v1607

Previously, we built deployment types for Windows 10 v1507 and v1511, 64-bit and 32-bit. We need to add two more deployment types for Windows 10 v1607 (“Anniversary Update”) and Windows Server 2016. The properties for these new deployment types are very similar to those for the earlier versions of Windows 10. As usual, we must make appropriate changes to the Name, Content location, and Requirements properties. We’ll use the custom Global Condition from a previous post in the Requirements. For any properties omitted below, such as the detection logic, use the same values as with earlier versions of Windows 10.

Property Value
Deployment Type Properties – Windows 10 Anniversary Update (32-bit)
Name Feature Installation – Windows 10 Version 1607 (32-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.14393×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 (32-bit)
OS BuildNumber Equals 14393
Deployment Type Properties – Windows 10 Anniversary Update (64-bit)
Name Feature Installation – Windows 10 and Windows Server 2016 Version 1607 (64-bit)
Content location \\fileserver\software$\Microsoft\.NET Framework 3.5 SP1\Win10.0.14393×64\
Installation program Same as Windows 10 Anniversary Update (32-bit)
Uninstall program Same as Windows 10 Release (32-bit)
Requirements Operating system
One of All Windows 10 (64-bit), All Windows Server 2016 (64-bit)
OS BuildNumber Equals 14393

Coming Up

Next time, we’ll build a new Configuration Manager application for the Microsoft .NET Framework 4.6.2, which was also released with Windows 10 Anniversary Update.

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.