February 2012 Archives

Now I am absolutely certain I will hear a voice from far above (or maybe a bit closer to New York) booming out at me “THIS CAN BE DONE WITH REGULAR EXPRESSIONS!”

I’m pretty certain of that.  I don’t claim to have mastered Regular Expressions.   But I had a simple need today.   Converting cases of words in Powershell.

In my case I had a list of data that was in ALL UPPERCASE and since that feels a bit like shouting I wanted to do something with it.

In Powershell we have many built in methods to manipulate string data.   There are three I’m going to play with today, toupper, tolower and substring.

For example if I have this string….

$Sonnet=“There once was a Canadian Nerd, WHO saNG like an OFFKEY Bird…”

I can switch all of the characters to lowercase by using this method

$Sonnet.tolower()

Which will give us the following output

there once was a canadian nerd, who sang like an offkey bird…

If I would like to make it look like I’m shouting so everybody in Texas can hear me I can switch it all to uppercase

$Sonnet.toupper()

Which (Cover your ears as I’ll now be shouting) looks like this.

THERE ONCE WAS A CANADIAN NERD, WHO SANG LIKE AN OFFKEY BIRD…

Sorry that was a bit loud.   But you can see switching cases is quite trivial.   But here’s the fun.  What if you have to ensure a word is just Capitalized?

For that bit of trickery we can leverage Powershell and the magic substring command.

First let’s take a look at this loud and abusive word.

$ScaryThing=“JABBERWOCKY”

If we’d to present our good friend with JUST the name capitalized, we can grab the first character with a substring, pop it into uppercase like so

$ScaryThing.substring(0,1).toupper()

J

The audience “Oooohs” and “Ahhhs” in the background.    Without knowing the length of the word, we can use substring to grab all characters from the second character to the end and switch to lowercase

$ScaryThing.substring(1).tolower()

abberwocky

….More gasping from the audience…

And so with a wave of my hand and the magic words “Snoopy Dance”

$ScaryThing.substring(0,1).toupper()+$Scarystring.substring(1)

Jabberwocky

Now our good friend will appear less frightening to the general public.  Of course I’m having a bit of fun here but I had a situation where I had a list of full names that were in all uppercase.   Yes it was my own fault, a bad accident between an auto user generator for a Demo environment and an overly caffeinated “toupper()” method (or a broken CAPSlock key, the details are fuzzy).  So in my case I had a perfectly good list of names like

Name
ANDRE GRANT
ALTHEA DOWNS
AUDRA HANEY
CHASITY MCMILLAN
CHASITY KENNEDY
CRYSTAL BURGESS
BRUCE SHEPPARD
CHRISTI MCINTYRE
CHERIE TERRY

Perfectly good, except they were all SHOUTING!

What to do? Just grab each name, split ‘em and use my new evil powers before creating their names in my demo system

$fl=$_.Name;$first=fl[0];$last=$fl[1];

$first=$first.substring(0,1)+$first.substring(1).tolower();$last=$last.substring(0,1)+$last.substring(1).tolower();

Ok, maybe it’s partially useful and the gods of Regex will probably smite me down, but I’m an ITPro.

Have mercy on me.

Sean
The Energized Tech

The Power of Shell is in YOU

There has been the odd time I’ve had to overwrite a VHD file in Hyper-V with a restored copy.

The problem I stumbled across was starting the Hyper-V virtual machine up ended up with an “Access Denied” error almost every time.   The reason for this is simple.   Your VHD file does not have the correct permissions.

But how does one fix that?   It does inherit the folder permissions properly but the issue at hand is the VHD file is assigned a full access write to a SID.   That SID is specific to your Virtual machine and you will probably watch your brain explode.  Or you will go about chewing on your own socks for an answer.

The Cheat (and I stress “Cheat”) to this is to just grant the “Everyone” group full access to the file and…

Oh right…. That smells like a “Security Hole”.  Here, let me just do that to the rest of my files, it’s such a wonderful idea.

While the file is relatively isolated, granting the “Everyone” group access to a critical file is about as dumb as juggling a family of rabid skunks.

But the answer is easier than you think.  Use Powershell

Let’s say you’re looking a virtual machine folder with a file you need to replace (for whatever reason) and it contains the file “CDRIVE.VHD”.  If you need to overwrite CDRIVE.VHD with a restored copy AND retain the original permissions just Rename it and store the ACL’s presently applied to it in a Powershell variable using GET-ACL.

RENAME-ITEM CDRIVE.VHD OLDCDRIVE.VHD

$Permissions=GET-ACL OLDCDRIVE.VHD

Then restore the new file in place giving it the name of the original file.   To place the correct permissions on there, just execute

SET-ACL CDRIVE.VHD –aclobject $Permissions

 

Now your restored virtual machine will start without any complaints.

.. and you won’t be considered “Dumber than a bag of Hammers” by applying “Everyone” to a critical system file. Winking smile

The Power of Shell is in YOU

Sean
The Energized Tech

Unlike in the movie “Annie” tomorrow turned out to be more than a day away, in my case a few months.  Yes work has been busy but this has been a fun side project for me.  So now back to the fun! 

Last time we took a quick look into making an RTF or “Rich Text Format” file from Powershell.  We discovered that all we need to get started is a header and some basic information for the start of the file as well as a Terminator at the end of all the text

So now the “challenge part”, making this into a useful script that could actual like a tiny Word Mail Merge.  

So in Windows Powershell we all know that if you place a variable within a quoted string, it will expand internally.

$Name=”Ernie”
$SillyString=”Hello $Ernie”
WRITE-HOST $SillyString

This will produce the following output

Hello Ernie

Knowing this feature is something we can leverage within Windows Powershell and create a simple Mail Merge type script.   In our case, I would actually like to produce an RTF document where I can substitute the needed data and produce the new document.   Just where am I going with this?  WATCH Smile

First let’s get the script started.  A simple script prompting for a filename and we’ll supply some static variables to drop into the script.

param (
[string]$Filename,
)

# Static Variables

$Firstname=”John”
$Lastname=”Smith”
$Accountname="CONTOSO\\jsmith"
$Password="LousyPass123"

Now like before we’re going to define our header content for the RTF file.  I’ve made some additions.  You’ll note that each line ends with

`r`n

There are certain parts of an RTF that MUST end with a “Carriage Return / Line Feed” combination.   If you remember what a typewriter was and … (Oh oh! Just dated myself!)

Suffice it to say without embarrassing myself further that certain lines in the header MUST (and I mean MUST MUST MUST) end with a Carriage Return / LineFeed.   Also each line within your message must terminate with this sequence.

You’ll also note that rather than adding individual lines, I’m building a single string of content for the ADD-CONTENT Cmdlet

# Our RTF Header using a Consolas font

$Header+="{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Consolas;}}`r`n"
$Header+="{\*\generator Riched20 6.2.8102}\viewkind4\uc1 `r`n"
$Header+="\pard\sl276\slmult1\f0\fs22\lang9 \par`r`n"

As before, your paragraph for an RTF must end with “\par” and again each new line must also terminate with `r`n (Carriage Return / Linefeed) in the string.

$Message+="Hello $Firstname $Lastname and Welcome to ABC\par`r`n"
$Message+="Corporation.\par`r`n"
$Message+="\par`r`n"
$Message+="Your User ID is $Accountname\par`r`n"
$Message+="Your Temporary Password is $Password\par`r`n"
$Message+="\par`r`n"
$Message+="Do not share this information and remember,\par`r`n"
$Message+="We are watching....\par`r`n"
$Message+="`r`n"

And of course we add the footer

# And finally our footer to the RTF file

$Footer="}`r`n"

We need now add the variables together into a single string.

# Build the content together

$Content=$Header+$Message+$Footer

Now we’ll take this and place it into a single file, the name was provided by the $Filename parameter

ADD-CONTENT -path $Filename -value $Content –force

When you’re done you’ll end up with this simple script

param (
[string]$Filename,
)

# Static Variables

$Firstname=”John”
$Lastname=”Smith”
$Accountname="CONTOSO\\jsmith"
$Password="LousyPass123"

# Our RTF Header using a Consolas font

$Header+="{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Consolas;}}`r`n"
$Header+="{\*\generator Riched20 6.2.8102}\viewkind4\uc1 `r`n"
$Header+="\pard\sl276\slmult1\f0\fs22\lang9 \par`r`n"

# the Content of the message

$Message+="Hello $Firstname $Lastname and Welcome to ABC\par`r`n"
$Message+="Corporation.\par`r`n"
$Message+="\par`r`n"
$Message+="Your User ID is $Accountname\par`r`n"
$Message+="Your Temporary Password is $Password\par`r`n"
$Message+="\par`r`n"
$Message+="Do not share this information and remember,\par`r`n"
$Message+="We are watching....\par`r`n"
$Message+="`r`n"

$Footer="}`r`n"

# Build the content together

$Content=$Header+$Message+$Footer

ADD-CONTENT -path $Filename -value $Content –force

Run this script with a parameter of test123.rtf for the filename.

./NEWRTFFILE.PS1 –filename test123.rtf

Here is the exact document it will produce.

Hello John Smith and Welcome to ABC
Corporation.

Your User ID is CONTOSO\jsmith
Your Temporary Password is LousyPass123

Do not share this information and remember,
We are watching....

Can you picture using this in your organization now?  As you create new staff within Windows Powershell, a lovely letter to hand off to the manager.  Or perhaps you have a system that needs to generate reports?  Within Windows Powershell you can leverage a well recognized format like RTF to produce very GUI looking documents from with the native Windows Powershell environment.

You’ll also notice one other thing I did.  Take a look at the variable $Accountname

$Accountname=”CONTOSO\\jsmith”

Did you see the double backslash?  That’s intentional.  It is a part of the specifications for an RTF document.   Much like there are certain characters that require an “Escape” to be seen in Windows Powershell, certain characters like the backslash are important to the RTF interpreter and must be preceded by a backslash to be seen in the actual document.

Play with this and see what you can do with it.   I know what I’m doing at work tomorrow!

The Power of Shell is in YOU

Sean
The Energized Tech