Error Handling, Part 1: Overview

It happens to all of us: our perfect script will run in to something it doesn't understand, doesn't know how to deal with, and out comes the red text.  It was probably something simple, like someone mistyped the command, or that file was moved by someone trying to be "helpful".

Whatever the reason, you find yourself looking at a garbled mess of angry red text.  Or, even worse: it was a script you had running automatically, and now you have no idea what went wrong.  Fortunately, PowerShell comes with many ways to deal with errors.

Error Handling isn't a sexy or fun topic, but it is vital to writing good scripts.  In this series, I hope to give you enough to get started.

Read More

State of the Bear

It's been a while since my last post, so I thought I'd say a few things about what I've been up to the last few months.  While I may not have posted here, I have been quite busy, and working on a lot of other things.

A lot of what I've been doing is just using PowerShell for what it does best: administering systems.  Through that, I've learned a lot and have grown my tool belt plenty, but the project I'm working on right now is probably the biggest thing I've done with PowerShell yet: I'm creating a full user management application for provisioning and disabling user accounts in both Active Directory and Office 365 to make a complex process simple for low level techs.  The most exciting part of it for me is that I'm building it as a fully functional GUI application using WPF.  I'm not using any expensive toolkit like PowerShell Studio to build it, either, so I'm building the GUI in Visual Studio (by the way, VS 2015 Community is out, and it's great!), loading it in to my script with a couple of functions I adapted from things I found online, then adding actions to the button clicks to make them execute my PowerShell code.

Through this, I've been learning a lot about WPF, how to lay out a GUI with XAML, and the .NET framework.

I'm hoping to share the things I'm learning from this, along with many other things, very soon.

Pipe output to the clipboard using clip.exe

Quick one today, a very simple trick I learned a few days ago: if you need to copy and paste your output from the console, instead of using the markup tools built in to cmd.exe, you can simply pass your output directly to the clipboard.  No big trick needed for this; just pipe the output to clip.exe and it will be put on the clipboard, ready to be pasted wherever you need.  It's built in to the OS, so you don't need to download and install anything.

Let's say I have a list of user account I've grabbed from Active Directory and saved to the variable $users, and I need to send that list in an email.  I could enter "$users" by itself on the command line, then select and hit enter to copy.  Then I would paste the list...and find I need to strip out all of the white space this creates. It's not hard, but it can be inconvenient sometimes, especially if it's a long list.

Instead, I could just run "$users | clip.exe" and get the same effect, only without jumping through hoops, without the chance of over or under selecting, and without selecting a bunch of extra white space.

It's really that easy.  Just add " | clip.exe" to the end and it will throw the screen output into the clipboard directly instead of on to the screen, and then you can paste it normally.

I really should start using GitHub

Okay, not a PowerShell thing (directly, anyway), just finding that my method of storing my code is becoming unmanageable.  Basically, what I've been doing is throwing everything in my Google Drive, which is overall very convenient, but over time is showing to be unwieldy.  Especially since, though I write a change log with my more important scripts, I have no way to go back to an old version of my code.

I already had a GitHub account, I've just not been using it.  So, depending on how things work, I'll probably start sharing more of my code from there rather than embedding it directly here, and just provide a link to it instead.

In my limited interaction with GitHub in the past, it was fantastic and fairly easy to use.  If you're looking for a way to store your code, and even collaborate, it's a great system for it.  If you're on GitHub already, I'm on there as poshcodebear.  You can find me here: https://github.com/poshcodebear.

There's not much there yet, but I'm going to start migrating my code to there soon so you'll see things start to pop up.

Test execution speed with Measure-Command

When hacking away at a shell or writing a quick on-off script that will only do a handful of things and only once, knowing how fast each part works isn't that big of a deal.  When you're writing something that will get reused over and over, especially if it's something that's working against a large collection (such as, for example, running a WMI query against every computer in your domain), knowing how quickly different commands run could be quite important, especially if you're looking to improve execution speed.

To test execution speed, I use Measure-Command.

Read More

Better place to PowerShell (say goodbye to cmd.exe)

I'll be honest, I hate cmd.exe, which is what PowerShell uses by default.  It's functional, but crude, old fashioned and basic. I had been using ConEmu for some time, and it's an excellent product, but I ran into another that I feel fixes all of the problems with cmd (and even the last nagging issue I had with ConEmu): Cmder.  It uses ConEmu for the console emulator, it's completely portable, and when you just need a windows command prompt (rather than PowerShell), it gives you a Bash-like shell experience (unfortunately, trying to get the bash-like enhancements to work in PowerShell broke tab completion for PowerShell cmdlets for me, so I had to stick with PowerShell style tab completion).

Anyway, it's a great functioning, great looking console emulator, and I highly recommend giving it a try.

Discovering folders with severed inheritance

What do you do when you find your network file share permissions are a little...weird?  That when you go to add permissions to a folder, some of the sub folders still remain out of reach?  Then, when you check them manually, you find that someone, at some point, disabled inheritance on that folder, and for no good reason.  Or, worse, someone set up the shares with a bunch of severed inheritance, mainly because they didn't know how to manage folder permissions well.

Whatever the reason, knowing where inheritance is severed in your file shares is not only useful, but critical to properly manage your shares.  To discover those inheritances, just go through each folder, one by one, and write down each one tha...

Wait!  There's got to be a better way to do this!

Fortunately, Get-Acl is here to help.  The AccessControl.DirectorySecurity objects it returns for folders has a property called "AreAccessRulesProtected", which when set to True, means inheritance is disabled.  So, I wrote a quick script to help locate and document this.  Note that you will need to be using an account with at least read permissions to all of the folders you are targeting; also, I've done this for a single server with multiple shares, each share I've put in a text file.  It will be easy to modify that as you need. 

When will you be 1 billion seconds old?

I was watching this video from Neil deGrasse Tyson where he explains just how rich Bill Gates is (it's a fun video to watch, check it out here: http://9gag.tv/p/a5XWnk/watch-neil-degrasse-tyson-explain-how-rich-bill-gates-is).  In it, he talks about how old you will be when you've reached your billionth second (it's close to 32 years, BTW), and mentioned having taken the time to compute this, and that someone will probably write an app to do this.

So of course, I said "that should be easy enough for PowerShell!".  It was.  Ridiculously easy, in fact.  So, for some fun, you, too, can quickly calculate when you can celebrate your billionth second!  (I used some sample data not actually linked to anyone's birthday that I know)

Note that the time is in 24 hour format (though you can use 12 hour format by adding AM or PM to the end), and that the date is the US standard format, so if your localization is different, you'll probably need to use your localized standard.

Whoever has the above birthday will celebrate their 1 billionth second on Saturday, April 24, 2021 at 7:41:40 PM.

Find-PCBCrypto: Function to aid in finding CryptoLocker encrypted files

CryptoLocker is a nasty beast of a bug causing all manner of havoc.  If it's done nothing else, one positive impact it has had on IT is that we're making sure our backups aren't being ignored.

One of the hardest parts still, though, is finding what got hit, and who got hit, and in a timely enough manner to minimize the damage done.  Part of that problem is that there is no scanner that can definitively detect CryptoLocker encrypted files, specifically because they just look like any encrypted file; there is no virus fingerprint to be had.

So, how to scan for its fingerprints proactively?  It seemed like a nearly impossible task (I'm no malware expert, so figuring out how to detect something like this isn't my forte).  When I started digging in to the problem, though, I did learn a few key pieces to the puzzle.

Read More

Block updates to Internet Explorer

Keeping everything up to date is great...up until it breaks something your business needs.  Internet Explorer upgrades are notorious for breaking production applications, and as such, most businesses need to test each version before allowing it to deploy in production.  When you have a dozen systems, it is easy enough to just walk to them and hide the upgrade, and uncheck the little "Install new versions automatically' checkbox; when you manage hundreds or thousands of machines, however, that task quickly moves from time consuming to impossible.

Read More

Listing Forwarders for all domain DNS Servers

Anyone who's managed Active Directory long enough can tell you that one of the most (if not the most) important thing to a healthy AD is healthy DNS.  While forwarders won't likely be a huge cause for AD problems, it's still nice to make sure your servers are configured in a consistent manner, and since forwarders can be set per DNS server, you'd have to log in to each and every one to verify the settings on it.  Fortunately, PowerShell can help (but only if you're running Windows 8/Server 2012 or newer; don't worry, though, the target servers can be 2008 R2, though it does have to be Microsoft DNS (sorry, BIND users!)).

Note that if you supply the name of your domain, you should get back a list of IPs of all of your AD/DNS servers.  If this is not the case, then you likely have bigger issues with DNS to resolve first.  If you for some reason separate your AD and DNS servers, then you may have to do something else to get the list of servers.  Also note that my idea of having all forwarders be the same is not necessarily a one-size-fits-all; there are times and places when having them be different for some servers makes sense.  Even still, being able to quickly and easily document these settings could be a huge time saver, especially if you have a large environment.

Forwarders aren't the only thing you can get with Get-DNSServer; you can see just about any setting on the server with that.  I recommend firing it off by itself against a single DNS server to see what all it gives you, and you could easily modify this snippet to document just about any setting in there that you want.

EDIT 5-18-2015: I've modified the part of the script that gets the name servers and makes it actually capture the name servers and not just assume that the A records for the domain will be a full list of name servers.

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.

Get VMWare network adapter types

This one requires PowerCLI to work, and you will need to connect to your vSphere server first; I wrote this one to see what servers had which network adapters configured so we'd know which ones could be upgraded to VMXNET 3.  This could easily be modified to capture just about any information you want, just by digging in to the VM objects a bit.

That's it; there's not much to this one other than what you see.  Use in good health.

EDIT: Well, this is embarrassing.  You could easily do the above faster and better  with "Get-NetworkAdapter (Get-VM)".  Well, this will work if you don't have Get-NetworkAdapter in your version of PowerCLI, or you could modify the above to target info that's not as readily available via cmdlet.

EDIT 2: "Get-NetworkAdapter (Get-VM)" won't show which server they're connected to, so I guess there is still use for my script.  I may circle around and update it using Get-NetworkAdapter, but for now, there you go.

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.

File server permissions audit

This is another one of those quick and dirty snippets to solve a problem or answer a question (I'm a real fan of those); it could easily be modified to create a much more professional looking report.

I was asked to go through a file server share and find out who had access to what at a pretty basic level; mostly, we're comparing groups in an old domain to make sure the corresponding groups have been set in the new domain, but this can be tweaked to help answer many questions.

I'm positive there's a better way to target only domain permissions without calling them directly, and when I find it, I'll come back and update this post; but for now, this works.  Note that to strip out inherited permissions, you will need at least version 3 of PowerShell (that property isn't returned by v2's Get-Acl).

Depending on the size of the file shares you target, this will very likely take a long time to complete, and could give your shell a nice, very large memory footprint, so you'll want to watch for that.  Once you have the output, though, you could easily do some quick manipulation in the shell, or export it to CSV and load it up into Excel to analyze it with pivot tables (the best reason for keeping Excel around, in my opinion).

Oh, and you will need access to read permissions on everything for this to actually work.

Update: There were issues with the original iteration of the snippet, mostly in that the output got messed up somehow when dealing with large-ish data sets (like you'd expect from any file server that's been in production for a length of time): it seemed to get "stuck" (for lack of a better word) on security principals and just list permission after permission tied to the same principal (which a quick sanity check against the file or folder's actual permissions showed to be false).  I solved that by outputing each object to a temporary csv file, then importing it back at the end of the process, rather than hold everything in a variable while it worked.

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).

Updated About section

I've updated my about section with a few more details about me and what I'm doing.  Check it out; I'll be filling more in to it as time goes on and I have more to say there.

Simple Network Host Scan in PowerShell

This is very crass and simplified, and frankly, other programs (such as Angry IP and (my personal favorite) NMap) do a much, much better job; however, if you need to do a scan in a script for whatever reason, this may do the trick.  It would be very easy to make any changes to this you'd like, such as leaving out DNS resolution, or swapping it for a WMI query, or adding just about anything else you want.  This is just a quick, dirty example, and as such, it doesn't have a lot of polish.  (Note: as-is, this code requires Windows 8 due to Resolve-DnsName not being included in prior versions)

If you want to run this on Windows 7, here are two methods of resolving DNS names that work:

Using .NET methods (my preference):
Windows PowerShell One Liner: Name to IP Address

Using nslookup (more work to get the output you want, but always a good tool):
PowerShell v2 And DNS Queries

Removing the first or last lines from a text file

If you've ever run into a situation where you know you won't be needing those pesky first or last lines in a text file (this also works for other arrays, BTW), then this is a quick and easy way to get just what you're looking for:

Explanation: you can call a particular object by the index, or in this case, a particular line in the file.  Remember, the index number will be one number lower than the line number, because the index starts at 0, so line 20 will be at index 19, or $test[19].

You can also call a range of indices, such as to get lines 1 through 5, you would use $test[0..4].  You can use a variable number to specify the index as well, such as $test[$index].

Put this all together, and you can strip the last line out of your variable with:

Since the count is going to be the full number of lines, $var.count - 1 would be the last line, so you want it to stop at the next to last line, or $var.count - 2.

Removing the first line is likewise simple, with just a tiny modification:

If you need more than one line off of either side, just tweak the numbers.  Simple!