Moving Software Installation Packages between Group Policies
Let's skip the introduction. You probably googled this article anyway, so you'll know what I'm talking about. This is the scenario: You use group policies to publish or assign software packages (usually Windows Installer MSI) to your Windows workstations. At some point it would be convenient to move a package from one group policy to another, without triggering a complete reinstallation.
Delete and recreate packages?
In the traditional approach you remove the package from the source policy and recreate it in the destination policy but this definitely causes a reinstallation of that package. From the workstation point of view, a brand new software package was added to a group policy, so it installs it. The fact that the actual MSI file didn't change makes no difference. Generally speaking, deleting an object and creating a replica just isn't the same as moving that object. Even if the group policy's new package entry in is set up 100% identical to the old one, Windows is not clever enough to detect that and instead chooses to re-install the package from scratch.
Move packages, really!
I wouldn't have written this article hadn't I figured out an alternative. And this is how it works: To begin with, a GPO-deployed software package consists of three parts:
- the actual installation package (an MSI file, the installation files and, optionally, MST transforms),
- the AAS script in SYSVOL and
- the LDAP entry in Active Directory (AD).
If you want to move a package between two group policies, you need to move the latter two. This task can't be accomplished using only stock management tools that come with Windows. You will need
- an Active Directory editor (Softerra LDAP Administrator is a fine product),
- a file manager (Windows Explorer will do) and,
- optionally, the new Group Policy Management Console (only runs on XP and above).
This is what you'll need to do:
- Find out the GUID of the source and the destination GPO. You can find it in the GPO's property dialog. If you're using the newer Group Policy Management Console, you'll find the GUID in the details tab of the policy.
- Fire up your AD editor. In case you're using Softerra LDAP Administrator, you'll need to create a profile for your domain controller. Specify
DC=<yourdomain>, DC=<your-top-level-domain>
forBaseDN
. UseGSS Negotiate
as the credential mechanism and useYOURDOMAIN\yourid
as the principal. Do not checkUse Secure Connection (SSL)
. - Go to
CN=System, CN=Policies, CN=<your source GPO's GUID>, CN=Machine, CN=Class Store, CN=Packages
. You will see a number of entries, i.e. folder-like objects, at least as many as the source GPO has software packages, usually more. - You will be dragging the packages from the source to the destination GPO, so it makes sense that you open the destination GPO's entry as well: repeat step 3 for the target GPO.
- Select all entries that have the same displayName attribute as the software package that you're about to move. There might be more than one – see below for an explanation.
- Drag the selected items into the
CN=Packages
entry of the destination GPO. - Select each of the packages moved and edit the
msiScriptPath
attribute. It will look like\\<your dfs-root>\SysVol\your-domain\Policies\{your source GPO's GUID}\Machine\Applications\{your package's GUID}.aas
. Change it to\\<your dfs-root>\SysVol\your-domain\Policies\{your destination GPO's GUID}\Machine\Applications\{your package's GUID}.aas
by pasting the destination GPO's GUID over the source GPO's GUID. You should keep the destination GPO's GUID in the clipboard during the whole process. - If the package contains an attribute called
canUpgradeScript
, you may need to adjust it. This can happen if the software package is an upgrade to another one, in which case the canUpgradeScript is a reference to the upgraded package. This reference includes the GUID of the GPO that contains the upgraded package. If you moved the upgraded package as well, you need to adjust thecanUpgradeScript
attribute such that it references the destination GPO. If you moved an upgraded package while leaving the upgrade package at its original location, you need to change the upgrade'scanUpgradeScript
to refer to the destination GPO's GUID. Otherwise there is no need to touchcanUpgradeScript
. Think ofcanUpgradeScript
as a pointer to the old, upgraded package. If you moved the old package, this pointer will need to be adjusted, independed of whether you moved the new, upgrading package or not. - In step 7, you modified the
msiScriptPath
attribute of the package entry. It contains a path to the AAS script located in the SYSVOL share. You need to make sure that the new path is valid and points to the correct AAS file. Using a file manager, e.g. Windows Explorer, move the corresponding AAS files from the old location to the new one. The SysVol share can be opened by pointing the file manager, to\\your-domain-controller\SysVol
. - Open the source and target GPOs in Group Policy Management Console or Active Directory Users and Computers and open the Software Installation folder of both GPOs. Check whether all packages appear intact and whether all upgrade relationships are correct.
- Reboot one workstation and watch closely while it starts up, especially during the software deployment phase. Check its event log. There shouldn't be any package reinstallations nor errors regarding software installation. You might also want to wipe the workstation and redeploy Windows in order to verify that it can reach all packages when installing them from scratch. Check the event log after that, too. Reinstalling Windows might sound like a drastic measure but it's really recommended. Personally, I use RIS to deploy Windows, so for me it just takes a couple of key strokes and a cup of tea to drink while waiting.
- Optional: If the source GPO is empty, you might as well delete it. If you do that, the workstations will re-apply the software installation settings once they are rebooted. However, this should only take a couple of seconds because the software packages will not be re-installed from scratch. They will just be brought into managed state.
More Entries Than Packages?
Why are there more entries in \\<dfs>\SysVol\<domain>\Policies\{<GPO>}\Machine\Applications
than there are packages listed in the GPO in Active Directory Users and Computers? I think this is because when a package is removed, Windows doesn't really delete the corresponding entry from the directory database. Instead, the package is marked as "deleted" but it remains in the directory such that workstations can still retrieve the package's configuration in case they need to uninstall it. MST transforms, for example, can have drastic effects on a package's configuration. Consequently, they should be around when the package is uninstalled.
Installation Order
One more word about the sequence in which Active Directory software packages are installed. The installation order among packages that belong to different GPOs is the same as the order in which GPOs are applied: packages of higher level GPO's are installed after the ones in lower level GPOs. Within a container or organizational unit, a GPO further down in the list of GPOs is installed before ones that are listed further up. If you need package A to be installed before package B you simply need to make sure that A is either in a GPO that belongs to a lower level AD entry (domain or organizational unit) than B or that A's GPO is below B's GPO in the list of GPOs that are linked to one particular container.
The above only applies to packages that are located in different GPOs. The installation order within a group policy is also well defined and consistent. Yet it seems that there is no documented way to fine-tune it. In my experience, packages within the same policy are installed in ascending historical order: packages created or modified more recently will be installed later in the installation sequence. It works as follows: Every package entry in \\<dfs>\SysVol\<domain>\Policies\{<GPO>}\Machine\Applications
has a timestamp attribute. The higher the timestamp value, the later the package will be installed. If you want to override this installation order, you need to use an Active Directory editor like Softerra LDAP Administrator and adjust the timestamp values accordingly.
The Assigned Software Sequence Manager (ASSM) v0.3 by Sywan allows you to change the installation order without fiddling with timestamp values. It is no longer maintained but it works just fine. As the program is released under GPL, I assume that I can offer a download on my site.
Note, though, that even the tiniest modification to a package will cause its timestamp to be adjusted to the current date and time, pushing it to the end of the installation sequence. Because even redeploying a package is considered a modification in that sense, everytime you redeploy a package you'll have to manually restore the original package order – a tedious chore that is as easily neglected. Luckily, there often is no need to enforce a complete order. In most cases, there are only a few constraints that need to be guaranteed. Like package A needs to be installed before package B but it doesn't matter in which order packages C,D, and E are installed. This allows for a reduction of the total number of policies needed: group packages into sets and put each set into a separate policy. Choose the sets such that
- it makes no difference in which order the packages within one particular set are installed and
- put packages for which a constraint like the above exists, into separate policies.
In the above example, you would need to put package A in a policy of it's own and all other packages in a second policy.