Copy Group Policy links from one OU to another

Testing Group Policies can be a chore if you have a lot of them, especially if you need to link a long list of GPOs to one OU that are linked to another OU.  You could do this via the Group Policy Management console, but that can be time consuming, and you could wind up linking the wrong GPO or missing one if you're not careful.  So, let's script it, instead!

You will need to have the AD RSAT tools installed, and have the GroupPolicy module.  I've only tested this on Windows 8.1 with PowerShell V4, so your mileage may very (and, as this is one I've marked as "Dangerous", you absolutely should test this before using it in production, and be VERY careful: linking GPOs in the wrong place could have very bad adverse effects).

I highly recommend playing around with the output stored in $gpos; as you can see, what you want is nested fairly deeply ($gpos.gpos.gpo[*].LinksTo.SOMName).

Note that the SourceOU is the name of the OU itself, while DestinationOU is the full LDAP name.

I do very much recommend playing around with this on a test environment before going to town in production.

EDIT (2019-01-22): I didn’t spell this out, but this method will only work if the source OU name is unique on your domain. ColdPower in the comments below mentions an alternative way to get the GP links that will work with the full DN of the source OU, and will work a lot faster (especially if you have a lot of GPOs and GP links)

Someone else commented how this doesn’t copy additional properties like enabled state, permissions, etc. I didn’t approve it as the comment was rather rude and I’m not into that, so I’ll just respond up here instead. That is true, and it’s something to consider if your GP links are more complicated. I’ll again reiterate that I do very much recommend trying this on a test environment before using it in production. That includes finding and dealing with cases where the copy won’t be perfect. I didn’t share this as a heavily tested and battle tried method that should work in all circumstances. I don’t have one of those as my need for this sort of thing is very occasional and if I run into a few minor extra tweaks I need to make after, it’ll still be faster than accounting for it in the script at this point for me. I may come back and revisit this at some point in the future, if I feel up to it, and make it a much more comprehensive solution.