Protecting all OUs from accidental deletion

If you've run the Best Practice Analyzer (or BPA) for Active Directory Domain Services (ADDS), you may get the following warning: "All OUs in this domain should be protected from accidental deletion".  Depending on the size of your domain, going through all OUs to check that could sit on your list of things you want to do somewhere between "Mindbogglingly boring and waste of time" and "SHOOT ME NOW!".  Thankfully, this, too, can be done through PowerShell:

Here's where I tell you that this makes changes to your AD environment, and while there should be no ill consequences for this one, do take proper precautions; before running it, you should also just run the first two lines by themselves (minus the last pipe) to see what you'd be changing.

Other than that, this is another really simple, fairly self-explanatory snippet.

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.

Bulk removing printers using WMI

The best way to do this is through Group Policy Preferences, but sometimes, we just need something quick and dirty.  If you have Server 2012 or Windows 8 (or newer), you have access to such wonderful cmdlets as Get-Printer and Remove-Printer to help you out; most of us, however, still have to work with Windows 7 and Server 2008 R2 frequently.  Fortunately, there's a way to do this using WMI, and I've written a quick snippet to show that off.

In my example, I needed to remove all of the printers on a server that came from one particular print server, and Group Policy wasn't really a good option at the moment.  Note the 4 backslashes at the beginning and 2 at the end; this is because of how WQL queries work, meaning you have to do a double backslash for every backslash to escape them.

You can also use SystemName instead of Name in the filter; if you do, leave off the ending backslash (or just leave all backslashes off; it should work just fine that way).

Warning: this code could potentially cause unexpected and bad results if you aren't careful.  I highly recommend testing before you use, and checking to make sure you've actually captured only the printers you want to remove by taking a look at what's in $printers before you run the last part (just do "$printers | select name" to see what printers you've targeted).