Monthly Archives: March 2015

Generating unique email address

So my colleague Rene van Amersfoort walks by, “Hey mr PowerShell!” Stop… Mr. PowerShell is Jeffrey Snover, I’m just a humble PowerShell enthusiast, but keep going, I’m listening…

“So I want to generate some unique email address for this office 365 migration I’m doing. The naming convention is as follows: “First letter GivenName””SurName without spaces”
I’ve got a bit of a challenge, what if the email address is already used? Then I need to increment the email address with 1 and so forth. Care to take a look at what I’ve got so far?”

“Do I??? Is a duck’s butt waterproof???” (Hey, doesn’t take much to get me to look at a PowerShell script, plus the Mr PowerShell was a nice comment, how can I say no eh? 🙂 ) Off we go!!!

Ok, here in the Netherlands SurNames are notorious for having prefixes like ‘van’ and ’van der’. There is no Active Directory attribute for this so it ends up somewhere in the sn or in the DisplayName property.

Let’s see what you got so far… Egad! What did puppies ever do to you? “Huh? (Poor Rene is confused)” Five innocent puppies, I hope you’re happy… (Nope, Rene is still clueless). CBT nuggets followers get it, “Everytime someone uses Write-Host a puppy dies”, the horror. Oh but it gets better, according to Don Jones “there’s a special place in Hell reserved for those that use Write-Host…” I’ll spare poor Rene eternal torture…

Say, why don’t we just gather the information in a [PSCustomObject] ok? That way we can evaluate later on. “Eh [PSCustomObjects]?” Ok, seems I got my work cut out for me. So I started telling Rene about the advantages of using objects. In hindsight, his bewildered look should have told me to take it easy, sorry about that Rene, it’s the PowerShell force…

You know what? Don’t sweat it. This was a learning moment for me personally. Hey I’m ready to make a believer of anyone if they give me a chance, but you have to pace yourself, bring yourself to their level or you’ll lose them.

Ok, let’s collect all known user name and mail property first for reference.

$colUserMail = get-aduser -Filter * -Properties mail | select name,mail

Do you have a CSV file with the users you want to process? Nice!!!
Let’s import them

$users = import-csv -path C:\Migration_Script\CSV\_BATCH\_newaccounts\New-IDs.csv -Delimiter ','

Ok so you have the foreach that’s good. For each user in the CSV File we need the following properties : Name,GivenName, sn, DisplayName

$Name = Get-ADuser -Identity $account -Properties name,givenname,sn,displayname

Let go ahead and create an empty to collect our objects:

$arrResults = @()

Remember the syntax?

$s = $Name.givenname
$t = $s.Substring(0,1) #This will give you the first letter
$surename = ($name.sn -split ' ') -join '' #This will get rid of any spaces in SurNames with prefixes.

Incidentally I recently learned about $OFS (Object field Separator), we’ll just stick with this.

Your new email address is:
$mail = $t+$surename+”@newdomain.com”. At this point I could have stated that using ‘+’ isn’t really the way to manipulate strings, but I’ve also been there. The objective now is to help Rene with the script the way he feels comfortable.

We also have to set the targetAddress and ProxyAddress

$targetAddress = "smtp:"+$account+"@newdomain.com"
$ProxyAddress = "SMTP:"+$t+$surename+"@newdomain.com"

So now it’s time to verify if your new email address already exists

#Verify if user email exists
if (!$colUserMail.mail.Contains($mail)) {
   $newEmail = $mail
}
Else{
   $i=1
   Do {
      $newEmail = $t+$surename+"$i@newdomain.com"
      $i++
   } While (!$colUserMail.mail.Contains($mail))
}

let’s just gather that:

$hshUserMail = [PSCustomObject]@{
   SamAccountName = $user.Account
   Email = $newEmail
   TargetAddress = $targetAddress
   ProxyAddress = "smtp:$newEmail"
}

add to the $arrResults we created and we’re good!

$arrResults += $hshUserMail

Ok let’s run this and see what we got!

$arrResults | ogv

“Say what’s ogv?” oh that the alias for out-gridview, so yeah out-gridview is really cool you can… (Urv, contain yourself!!!)

We gave a test user a known email address a ran it and sure enough “userx1@newdomain.com” was returned.

Ok, so you got from here? “Yep, sure do! Thanks mate!!!” No, thank you for letting me show you how awesome PowerShell is!!! :-p

So Rene is happy and I learned a valuable lesson in not overrunning my colleagues with too much information. Let them get there at there own pace. By all means extend that helping hand, but make sure it does more good than harm…

Ttyl,

Urv

Get-NTFSAccess from the NTFSSecurity module

I’m lovin’ the NTFSSecurity module more and more!

In my first attempt I looked up the NTFS Access on folders that were explicit using Get-ChildItem2 -Recurse. In hindsight this is definitely a WET solution!

Turns out NTFSSecurity module has a cmdlet for getting NTFS Access aptly named:
Get-NTFSAccess!

So there’s no need to reinvent the wheel, think DRY!!!

The code then becomes quiet simple:

Get-ChildItem2 $Path -Recurse -Directory | Get-NTFSAccess -ExcludeInherited

That’s all there is to it! No muss no fuss!!!

Here’s how to get an overview of all the cmdlets in the module with syntax:

Get-Command -Module NTFSSecurity -CommandType Cmdlet -Syntax | Out-GridView

There’s even a Get-NTFSOrphanedAccess cmdlet! Talk about being spoiled!!!

Good watching out for the community raandree! Your code rocks!!!

Ttyl,

Urv

Clearing AD User properties

Suppose for some reason you need to clear the properties of a bunch of users, how would you go about doing that? I’ll give you a hint, you’ll need the Set-ADUser cmdlet.

I recently discovered that Set-ADUser has a -Clear parameter, go figure! Turns out to clear an attribute you need to use the LDAPDisplayName… Ok, so what does that mean?

So you know that Set-ADUser has the -City parameter right? Well the LDAPDisplayName for -City is ‘l’. What this means is to clear -City, you’d have to refer to City by it’s LDAPDisplayName ‘l’…

To clear -City the command would be Set-ADUser -Identity ‘UserName’ – Clear ‘l’ and not ‘City’ as you would expect… Hmmm…

So what you’re saying it that I need to translate the Set-ADUser parameters to the LDAPDisplayName in order to clear the value? Pretty much! Do I have an alternative? Well I’m glad you asked!!!

Ok, for those of you that don’t know this I LOVE to splat!!! Really? Yes I do!!!

I’ve talked about Translating CSV Headers to usable parameters in order to splat. A workaround for the LDAPDisplayName would be to use -ParameterName $NULL.

So to clear City attribute use Set-ADUser -Identity ‘UserName’ -City $null

Here’s the code. The main part is where the user’s property is set to $null. Ok I also talked about the DRY principal and my csv Header issue… I’m sure you’ll get the point I’m trying to get across… 😉

#region: csvUsers
$csvUsers =
@"
UserID nieuw,LoginNaam Nieuw,Personeelsnummer,VoorNaam,AchterNaam,Afdeling,Bedrijf, PostCode,StraatNaam,Stad,LocationCode
150131,150131,150131,John,Wayne,IT,Acme,1222 XX,Elmstreet 26,Sciencefiction,1X
150141,150141,150141,Jane,Doe,HR,Acme,1222 XX,Elmstreet 26,Sciencefiction,2X
150211,150211,150211,Jack,Swift,IT,Acme,1222 XX,Elmstreet 26,Sciencefiction,3X
150211,150211,150211,James,Bond,CEO,Acme,0007 XX,Elmstreet 26,Sciencefiction,
"@ |
ConvertFrom-Csv -Delimiter ','
#endregion

#region: HashTable to translate csv Header
$hshHeader =@{
   'UserID nieuw' = 'SamAccountName'
   Personeelsnummer = 'EmployeeID'
   VoorNaam = 'GivenName'
   AchterNaam = 'SurName'
   Afdeling = 'Department'
   Bedrijf = 'Company'
   PostCode = 'PostalCode'
   StraatNaam = 'StreetAddress'
   Stad = 'City'
}
#endregion

#region: Main
foreach ($user in $csvUsers) {
   $UserProperties = @{}

   foreach ($property in $hshHeader.Keys) {
      #Set user property to $null
      $UserProperties += @{$($hshHeader[$property])=$null}
   }

   #Add the hash Key Identity to the table. Identity key value equals SamAccountName
   $UserProperties.Add('Identity', $user.'UserID nieuw')

   #Remove the hash  Key SamAccountName. This cannot be cleared as it is mandatory
   $UserProperties.Remove(‘SamAccountName’)

   #Clear User
   try {
      Write-Verbose "Clearing user property values of user $($UserProperties.Identity)"
      Set-ADuser @UserProperties -PassThru
   }
   catch {
      Write-Error "Something went wrong clearing user $($UserProperties.Identity) properties"
   }
}
#endregion

My first attempt was to use -SamAccountName to identify the user, you need to use -Identity. No Identity in the csv? No problem! just add it as you go along… Ain’t splat grand… Hehe…

Of course you’re not allowed to clear the SamAccountName, it’s mandatory so I removed it from the hashtable $UserProperties.

This approach has the added value that if the same csv is used to populate the user’s attributes, only those attributes will be cleared. May not seem like a big deal now, but imagine some other process manipulating attributes as well… Ofcourse if they are the same well… You get the picture…

So there you have it, clearing user attributes with Set-ADUser without using -Clear and LDAPDisplayName.

Hope it’s worth something to you…

Ttyl,

Urv