Passing on the power of Powershell

I was recently asked to help a fellow systems administrator in one of our divisions with a request.  The request was simple enough with Powershell and when I provided the information the recipient shared the attempts they had made.  When I saw the example it was the familiar blue background of a powershell console and the syntax showed they were familiar with the Quest AD cmdlets….. 

I noticed they tried to run the same command several times just changing the SearchRoot.  So, working on the request I offered a one-liner they could use to replace it, simplifying it to list through the OU’s instead of specifying each one in another command line and formatting the output to make it easier to use.

So I offered the following syntax as a possible solution for their request (Report the count of objects in a set of sub-OUs).

get-qadobject -Type OrganizationalUnit -Searchroot '' -SearchScope OneLevel | `
% {$_.CanonicalName + ": " + (get-qadobject -SearchRoot $_.CanonicalName -SizeLimit 0).count }

The one-liner  produced the results they looked for and I was able to explain the line continuation with the backtick (`) and the alias for ForEach (%).  The obvious next question was how do I save this to a script.  So I have an admin hungry for some information on Powershell so I had to create an easy to read script. I had to include something I recently mentioned (thanks to Karl Mitschke) to add a new twist and make the code a little easier to read.

$QADObject = @{
Type = "OrganizationalUnit"
= ''
= "OneLevel"
# Create array of OU's to measure
$checkous = Get-QADObject @QADObject
# Process a count for each returned OU
ForEach ($ou in $checkous){
# Generate output in report format
$ou.CanonicalName + ": " +(get-qadobject -SearchRoot $ou.CanonicalName -SizeLimit 0).count

Of course I also had to ask what they were using for an editor and suggested that, since they were obviously familiar with the Quest AD cmdlets, they try PowerGUI.



Be More Specific

Nothing revolutionary here and I probably should have planned accordingly but… I was provided with a list of computers to delete, as long as they are not online.  It’s a pretty simple script and since its been a sporadic request I have not really formalized it.  I use the start-transcipt and stop-transcript to record the output, and was going through the anomalies (computer objects with sub-objects, etc..).  Hmmmm why didn’t this computer get deleted???

Well based on the name, a get-qadobject returns several objects.  The computer name met the naming convention but was not complete.  An example would be if your computers are named in a fashion similar to computerXXX and a computer is named computer, when you perform:

get-qadcomputer computer

This will return the object you were looking for but will also return all of the computerXXX named objects.  The fix is simple, and this is not a bug in my opinion, just a caveat that is easily accounted for.  When performing the get-qadcomputer use the Name parameter to return the specific object…

get-qadcomputer -Name computer


Powershell Plus and other editors

I have been a big fan of PowershellPlus, the enhanced shell and scripting tool from Idera.  I had started experiencing issues with the application going into a “Not Responding”  state.  So the new version (3.5) was announced and I thought I would give it a try.  Same interface that drew me to the product with the clear command history, variable displays and the command completion were there.  I started using it and again it was regaining my interest.  Testing done, now lets use it…. Uhoh! I can only suspect this is an issue with PowershellPlus and Quest AD Management tools not working well together but… I was doing a pretty simple query of computers using the Quest get-qadcomputer cmdlet.  Simple output of:

Get-QADComputer -SearchRoot ‘ OU’ -SearchScope ‘Subtree’ | select Name, ParentContainer

looks as expected.  I prepended to a variable with:

$test = Get-QADComputer -SearchRoot ‘ OU’ -SearchScope ‘Subtree’ | select Name, ParentContainer

$test.count returns a number in the range I was expecting as it shows 113, so lets look at the output of $test … WTH! it shows 11 items which equated to a specific ParentContainer and the “Not Responding” state surfaced again but not as severe.  Odd, so I test in a standard Powershell CLI and $test.count returns 113 again, and when I check the contents of $test, the screen shows lines of what would be expected of 113 records. 

I will look at this but I have to say my loyalty to this product is done.  On the upside, since I have taken a new position, I have been evangelizing Powershell amongst the Windows SystemAdmins so I have been suggesting PowerGUI and even more the Powershell ISE.  Some of the main features (automatic code-signing, V2 comment based help template, etc…) that I used to favor PowerShellPlus have been showing up in these products.  If you can’t work with the Quest AD cmdlets that’s a deal breaker for me.

I am thinking my blog entries with be adorned with this from here on out….

My PowerShell IDE is PowerGUI

Home Drive Mapping

So, this one is quick and was primarily meant to be a quick example when presenting on the Quest AD cmdlets.  The practical piece is to deal with something we experience when working remotely.  Typical scenario, user logs in locally to their laptop and then connect to the corporate network via VPN.  The home drive is not mapped because when the desktop state is loaded the VPN connection has not yet been made.  So the script showed how to add a little function to their powershell profile so they could simply run the function to make their connection.

function map-homedrive {

# simple function to map the drive based on your user info

$nw = New-Object -ComObject Wscript.Network

$nw.MapNetworkDrive((Get-QADUser $env:USERNAME).HomeDrive, (Get-QADUser$env:USERNAME).HomeDirectory)


The script simply  determines the current user name ($env:USERNAME), then reads the configured values for the corresponding Active directory object for the drive letter (Get-QADUser $env:USERNAME).HomeDrive and then the path (Get-QADUser $env:USERNAME).HomeDirectory , combining those two values to perform the drive mapping.