Category Archives: Uncategorized

Coding for speed

The results are in! Great summary about the Hadoop PowerShell Challenge by Stephen Owen! It was fun to see the different approaches. When it comes to speed you can’t beat native C# code! Great tips! Worth the read!

Advertisements

Pester to validate ADUser properties

‘Sup PSHomies,

See if you can relate. You’re in the middle of a migration, the users need to be created asap. You get a xlsx file with all the necessary properties. A quick Copy/Paste to csv file, Import-Csv  user.csv -Delimiter "`t" | New-ADUser and presto! Whew! Glad we got that out of the way 😉

Feels pretty awesome right? 15 minutes after, your project manager comes asking: “Say, which file did you use?” The one you sent me last week, why? “Uh, there’s a new version on sharepoint, did you use that one?” Well I did ask which file I should use (in my defense I did, that’s why I always email, written proof!). “Well there’s an updated version, could you make sure the users get updated? Thanks!!!” Sigh, here we go again…

At this point I can do two things:

  1. Just delete and recreate. Thing is you’ll loose SIDs and access to homedirectory etc etc. Not exactly ideal.
  2. Update the user properties. Definitely a better option. Still tricky especially using the Set-ADUser cmdlet, but that’s another story.

But before you go off to update the user settings, how about validating what has been changed? Maybe the damage isn’t that bad. I mean if it’s under five changes, I just might  do it manually… Oh who am I kidding? Wait, gimme a minute to catch my breathe from laughing! 😛

Enter Pester for ADUser validation!

With a Pester script to validate your ADUser settings, you’ll never have to second guess if the settings are as they should.

Here’s the result:ADPesterResults

Here’s a quick rundown of the script:

First I’ll just get all the user settings using $verify = Get-ADUser -Identity $user.SamAccountName -Properties *.

$ADPropertiesToVerify =  ($csvADUsers | Get-Member | Where-Object {$_.membertype -eq 'noteproperty'}).name will get me all the properties in the csv file. No need to map properties manually. Now I can loop through any amount of properties!

Next up, making sure empty properties get $null

if (([string]::isNullOrEmpty($user.$attribute))) {
   $user.$attribute = $null
}

$null isn’t equal to empty (Ofcourse you already knew that!)

Now compare what’s in the csv to what Get-ADUser found:

if($attribute -eq 'Path'){
   it "User is located in $($user.$attribute)" {
      $verify.DistinguishedName.Contains($user.$attribute)
   }
}
else{
   it "User property $($attribute) value is $($verify.$attribute)" {
      $user.$attribute | Should be $verify.$attribute
   }
}

Quick note: I used Path to create the user in a specific OU. There’s no Path property in Get-ADUser. So I did the next best thing, just verify that path is part of the user’s distinguishedname 😉

I also added a little bonus to verify the user’s homedirectory exists and that the user is also the owner.

Being able to validate will definitely give you peace of mind…

Hope it’s worth something to you

Ttyl,

Urv

Enumerations in PowerShell

‘Sup PSHomies,

I’m trying to get a grip on PowerShell Classes and all the new stuff we have available in version 5.

So June Blender posted this link in one of her tweets by @psCookieMonster. Guess Enum is a good place to start!

Using .NET enumerations to improve a user’s experience is definitely worth investing in, less error prone. I got a great tip how to create Custom Intellisense experience by @pcgeek86

I’ve used validation sets in the past. My “Aha” moment was the fact that you can just as easily typecast using the enumeration. You should check out powershell.com tip on the subject.

So I can create my own Enum and use it as a validation set? Let’s give it a try!

Hey! who doesn’t love a good pizza eh? 😉

Ok, there’s an upside and downside to this approach. The upside is that it keeps your code clean. The downside is that it has to be available prior to using. Another point to consider is that this is Syntax is only available in version 5.

Note: Enumerations are case-sensitive.

As luck would have it, I was perusing Microsoft’s pester scripts GitHub repository when I came across Pester for Classes! Here’s one from the pester scripts on Enumeration found in scripting.enums.tests.ps1

enum E3{
   e0
   e1 = 5
   e2 = ([int]::MaxValue) - 1
   e4
   e3 = 1    # This shouldn't be an error even though previous member was max int
}

So what’s going here? Well for starters I never paid much attention to the value being assigned. The first entry is assigned the value 0 if it hasn’t been given one. The second will be an increment of +1 of the first, that is, if it hasn’t been assigned another value.

So what are the current values?

[Enum]::GetValues('E3') | ForEach-Object {'{0} {1}' -f $_, ([E3]$_).value__ }

E3Values
e2 has the MaxValue of [Int] minus one. e4 wasn’t assigned a value yet. Its value is an increment of e2 (the MaxValue of [Int]). If you try to add a new entry after e4, say e5, you’ll receive an error.

enum E3{
   e0
   e1 = 5
   e2 = ([int]::MaxValue) - 1
   e4
   e5
   e3 = 1    # This shouldn't be an error even though previous member was max int
}

e5error

Have a look at the PizzaSize enumeration, what are the values actually?

[Enum]::GetValues('PizzaSize') | ForEach-Object {'{0}: {1}' -f $_, ([PizzaSize]$_).value__ }

PizzaSizeValues
Medium and Regular are incrementals of Small, Who knew! 😛

Want to make sure the enumeration has been defined?

[enum]::IsDefined([PizzaSize],'large') #Will be False case-sensitive
[enum]::IsDefined([PizzaSize],'Large') #True
[PizzaSize]10 #Returns Small
[PizzaSize]3  #Returns Large

#These will all return Large
[PizzaSize]::Large
[PizzaSize]'Large'
[PizzaSize]3

How about if I wanted the value of the day of the week, say Saturday?

([System.DayOfWeek]'Saturday').value__

[Enum]::GetValues('System.DayofWeek') | ForEach-Object {'{0}: {1}' -f $_, ([System.DayofWeek]$_).value__ }

Well, off to a good start when it comes to Enumerations!

Hope it’s worth something to you…

Ttyl,

Urv

Custom Intellisense for AD cmdlets with SearchBase parameter

Sup’ PSHomies!

You gotta love the PowerShell community! Found this little gem in my twitter feed (again) :-). Trevor Sullivan demonstrates how we can create custom intellisense for cmdlets if they haven’t been provided as yet. Great video! Trevor really does a great job explaining this.

The first thing that came to mind was Active Directory! I can’t tell you how often I needed the DistinguishedName of an OU. Now imagine having a dynamic list generated for you! No more errors,  just select and you’re good to go! Excited??? I sure am!

Sometimes you need to limit your searchbase depending on you AD size. Let’s say I want to retrieve all users starting from a specific point

Get-ADUser -Filter * -SearchBase 'OU=Users,OU=IT,DC=pshirwin,DC=local'

A simple typo will generate an error. Distinguished names are notorious for being lengthy…

Now the obvious AD cmdlets would be Get-ADUser,Get-ADGroup & Get-ADComputer. So that got me thinking , just how many AD cmdlets have SearchBase as a parameter?

Get-Command -Module ActiveDirectory |
ForEach-Object{
   $psItem.Name |
   Where-Object {
        (Get-Command $psItem).ParameterSets.Parameters.Name -eq 'SearchBase'
   }
}

Turns out there are quite a few using SearchBase

  • Get-ADComputer
  • Get-ADFineGrainedPasswordPolicy
  • Get-ADGroup
  • Get-ADObject
  • Get-ADOptionalFeature
  • Get-ADOrganizationalUnit
  • Get-ADServiceAccount
  • Get-ADUser
  • Search-ADAccount

So I can have Intellisense on all these cmdlets? Awesome!!!

Intellisense completed the DistinguisedName on -SearchBase for me. No need to type it in, no errors, just select and go!

TabExpansionSearchBase

Here’s the result:

TabExpansionSearchBase-result

I’m sure you guys will find your own use for this… Thanks again Trevor for bring this to our attention! Good looking out for the community! Be sure to watch Trevor’s video for in depth explanation.

Hope it’s worth something to you…

Ttyl,

Urv

Configuring DNS zones and resource records

“Hey Irwin! Do you have a script to configure DNS autodiscover?” Eh, no not really… I’m assuming you’re doing something with PowerShell DNS cmdlets? 😉 And so begins another PowerShell journey…

My colleague Ofir is our Exchange guy.

“Ok so what exactly do you want to accomplish Ofir? I’m trying to automate registering some Resource records in DNS, but it isn’t working. I’d like to add some IPAddresses to a specific zone… “Ok let’s see what you’ve got!

Add-DnsServerResourceRecordA -Name "autodiscover" -ZoneName "domain.local" -AllowUpdateAny -IPv4Address "IP address 1","IP address 2","IP address 3" -TimeToLive 01:00:00

“So when I use the cmdlet directly it works. When I use varaiables it doesn’t… Ideally the code should be re-usable…”  Ofir’s words not mine… I’ll admit, I teared up a bit… Kids, they grow up so fast… Hehe…

I think we can do this…

So Ofir was using read-host to get ZoneName and IPvAddress. Ah! What a lovely opportunity to demonstrate params!

“Ok Ofir, instead of using read-host, we’re better off using parameters. Using [CmdletBinding()] gives you the possibility to use Write-Verbose, no extra charge!”

[CmdletBinding()]
Param(
   [string]$fqdn ='domain.local',
   [string[]]$ServerIPAddress
)

Now because the Resource record could be multi-valued we’ll go on and define a string array variable [string[]]$ServerIPAddress

“To make you’re code more readable we’ll just go ahead and create a hashtable we can use to splat your parameters.”

$dnsSplat = @{
   Name = 'AutoDiscover'
   Zonename = $fqdn
   AllowUpdateAny =  $true
   IPv4Address = $ServerIPAddress
   TimeToLive = '01:00:00'
}

“Now all we need to do it run the appropriate cmdlet and we’re good!”

Add-DNSServerResourceRecordA @dnsSplat

Ok, so this got Ofir started… Mind you there’s no error handling or anything of that sort…
We did some tinkering on the fly and this was the end result:

<#

Author: I.C.A. Strachan
Version:
Version History:

Purpose: Create AutoDiscover Zone and add ResourceRecord

#>
[CmdletBinding()]
Param(
   [string]$fqdn ='domain.local',
   [string[]]$ServerIPAddress= @('192.168.1.4', '192.168.1.5')
)

BEGIN{
    $dnsRRA = @{
       Name = 'AutoDiscover'
       Zonename = "autodiscover.$($fqdn)"
       AllowUpdateAny =  $true
       TimeToLive = '01:00:00'
    }

    $dnsPZ = @{
        Name = "autodiscover.$($fqdn)"
        ReplicationScope = 'Forest'
        DynamicUpdate = 'Secure'
    }

    Import-Module DNSServer -Verbose:$false
}

PROCESS{
    #Only Add Zone is count is zero (doesn't exists)
    If (@(Get-DnsServerZone $dnsPZ.name -ErrorAction SilentlyContinue ).Count -eq 0 ){
        Write-Verbose "Creating DNS Zone: $($dnsPZ.name)"
        Add-DnsServerPrimaryZone @dnsPZ
    }

    #Get string equivalent of all A records
    $RR = Get-DnsServerResourceRecord -ZoneName autodiscover.domain.local -RRType A |
    Out-String

    $ServerIPAddress | ForEach-Object {
        If (!$RR.Contains($_)){
            Write-Verbose "Adding resource record $_ to $($dnsPZ.name)"
            Add-DNSServerResourceRecordA @dnsRRA -IPv4Address $_
        }
    }
}

END{}

Ofir was quite happy! Nice! Another satisfied customer. So the other day asked him to send me the code for future reference…

This is what he sent me:

What??? This wasn’t the code I expected! Turns out Ofir had a lot more he needed to configure. Just pointing him in the right direction was sufficient to generate this! Awesome! Give a man a fish… 😉

Go Ofir! It’s fun to see colleagues get excited about PowerShell. Sometimes all that’s needed is just a nudge in the right direction…

Ttyl,

Urv

Creating PowerShell GUIs

I’m old school. I’m a big fan of the “Real men don’t click” club!

My PowerShell bestie, Michaja van der Zouwen, is all about the GUI! We would go back and forth about to GUI or not to GUI… Good times…

We got a great introduction in creating PowerShell GUI app at the recent DuPSUG meeting by none other than June Blender! Just google June Blender… We’re being spoiled here!

Back in the days June was also part of the “Real (wo)men don’t click” club. So what changed? I can totally relate to June’s story about providing a script that could resolve a contractors problem. Now you would think the manager would be grateful eh? Nope! They weren’t interested in learning or using PowerShell even if it solved their problem. The idea was too daunting for them. Enter GUI.

GUI took away that initial fear of learning something new. “Just run this and click this button!” Doesn’t get easier than that eh? So should we all be creating GUIs? Well you should at least know how to 😉 Hence the workshop!

So I’m not against GUI, but it is a different mindset when creating a GUI app. You really need to think in events. You still need to validate parameters, but you need to anticipate what a user’s next move could be. The user’s move needs to be processed by ‘event-handlers’. With a script I have some parameters, I validate them and I’m good! With a GUI you need to think ahead of what could happen if…

We used Sapien PowerShell Studio to create a small GUI app. June gave us some excellent Gotcha and Aha tips! Sapien PowerShell Studio makes creating the GUI easy! Once the GUI interface was created we added the script logic. The event-handlers are basically script blocks!

Here’s where you need to think ahead:

What do I want happen if the textbox value is empty? Then you shouldn’t be able to click the button. Ok… But what if someone enters spaces only? We should validate that and make sure the value isn’t empty or spaces. But what if there’s a lingering space somewhere? Make sure Trim your textbox value.

Sapien PowerShell Studio makes it easy to export the complete script. Just go to Deploy -> “Export To Clipboard”. Paste in ISE and run it! Works! Have look at the script, there’s a lot going on under the hood… Imagine creating that by hand…

All the script logic can be found under ‘User Generated Script’ comment block. The rest PowerShell Studio took care of…

As an introduction to creating PowerShell GUI scripts, mission accomplished!

Here’s the link to June’s github repository for more information.

Thanks June it was a pleasure meeting you in person! I’m more open to the idea of creating a GUI around scripts, only after putting up a fight though… Old habits die hard… Hehe…

Ttyl,

Urv

 

Revisiting Exporting Data

Sup PSHomies!

I’ve been playing with different formats lately. I’d like to share a few thoughts on the subject if I may… For demo purposes I’ll be using the following cmdlets: Export-Csv, Export-Clixml and ConvertTo-Json!

Export-Csv

I’ve talked about my love for exporting to csv in the past. Here’s thing, exporting to CSV treats everything as a string. For reporting purposes this might not be an issue. When it comes to nested objects… Yeah… Then you’re better off exporting to XML. Incidentally Jeff Hicks has a great blog on this topic, you should definitely check it out! CSV is still my goto format because of reporting in Excel, although, I’ve been using Doug Finke’s ImportExcel module more and more! Doug’s module cuts out the middle man and can export to Excel without having to export as a CSV first. It does a whole lot more! Worth looking into!

Export-Clixml

Exporting a nested object is pretty straightforward using Export-Clixml. The structure isn’t pretty though. That was the main reason I didn’t use the cmdlet. Export-Clixml is great when used in combination with Import-Clixml, it restores your nested object without a hitch! You can export your results, send the file and import elsewhere for further processing if needed. When I think of xml, I immediately conjure up ideas of html reporting. The xml tags are too cryptic for any css style, I wouldn’t even know where to begin. I recently discovered PScribo (Thanks to the PowerShell Summit in Stockholm), a module by Ian Brighton! This made html reporting a breeze! All I did was import my XML file back into PowerShell to retrieve my nested object and I did the rest in PowerShell! That was awesome!

ConvertTo-Json

The ConvertTo-Json cmdlet has been introduced in PowerShell version 3.0. Back then I was a stickler for XML so I briefly looked at it and forgot all about it… That is until Azure Resource Manager came along. If you’re doing anything with Azure Resource Manager then Json should be on your radar. If you’re not convinced just look at the ARM Templates out there. Json is a lot easier on the eyes for sure. Still not conviced? Just google Json vs XML.

Ok here’s some code you can play with to get a general idea of what the possibilities are when exporting to different formats. Have a look at the Json and Xml, which would you prefer? That was rhetorical… 😉

Bottom line

Export-Csv is best when you need to report  anything in Excel workbooks and you’re not worried about type. Everyone gets Excel.

Export-Clixml isn’t pretty but excellent when it comes to keeping the data metadata in tact. You can always import preserving the metadata and process further in PowerShell.

Use Json if you want to have a structured data set à la XML. Json is a lot friendlier than XML. I was also surprised that the cmdlet interpreted values to it’s best avail. False became Boolean as you would expect. Json is growing on me…

Hope it’s worth something to you…

Ttyl,

Urv