Trains, Planes, Automobiles (and Buses) (part 1)

After I decided I wanted to go up to Michigan to see my parents, the question was, “How?”

I didn’t even consider driving. My wife and I have driven our Hyundai to Michigan, Washington D.C., North Carolina, and Tennessee – but it’s gotten a bit worn down and I’m not really confident taking it much farther from home than, say, San Antonio.

What about flying? I checked airline prices, and couldn’t find a flight in the next couple of weeks for less than $1000. Right now, that’s impossibly out of our budget.

The last time my wife and I took the Greyhound bus from Austin to Michigan and back, we swore we’d never do it again. Greyhound severely oversold the trip from Chicago to Memphis, and we couldn’t get two seats together – all the fat people who were waiting in line grabbed window seats, and we were separated.

If you know me, you’re probably saying, “Well, Ed, who are you to talk about people being fat?” That’s a fair point. I was definitely overweight or even obese at that time. But my seatmate, and my wife’s seatmate – they were FAT. We were crowded and miserable all the way to Memphis. We had a fairly good trip the rest of the way home to Austin, but we were determined – NEVER AGAIN!

However, sometimes life has a way of making you change your mind…

The ‘Good News – Bad News Tour’

The Good News: I’m taking an awesome Amtrak train trip to Chicago, and then a cool bus trip to Michigan!

The Bad News: I’m heading home to help my dad and mom with my dad’s surgical recovery.

Dad had some surgery a few days ago, and he was moved to a nursing home while he was recovering. He’s been in a lot of pain and been getting very depressed.

I called him last night (Sunday) to wish him a happy Easter. His pain medication made conversation difficult, but I could tell he was very depressed.

The more we talked, the more worried I got, and the more I decided I wanted to get up north to see him and help Mom, if I could.

It’s less than 48 hours later, and I’m on my way to Michigan. More to come…

Where it all started – the Monad Manifesto

PowerShell originally started as a project called “Monad” within Microsoft.

The original Monad Manifesto[PDF] was written by Jeffrey Snover back in August 2002.

BTW, one of the major influences on Monad was a paper by John Ousterhaut:
Scripting: HigherLevel Programming for the 21st Century[PDF]

It’s interesting to read Snover’s original manifesto and see how much of the original vision made it into PowerShell (and how much didn’t).

Setting up my PowerShell profiles

There comes a time in every programmer’s life when s/he has to strike out on his/her own, writing new code (instead of typing in examples from books / websites). That time has come now for me with regards to PowerShell.

But first, I have to set up my working environment.

Here at work, we have a common (i.e., shared) network directory on our Production resource server. There were no PowerShell utilities in the directory (probably because I think I’m the first person to do anything serious with PowerShell here, with the possible exception of the IT guys – and they don’t use the Production resource server).

However, it occurred to me that that common directory (call it N:\common\utils, because that’s not its name) would be a good place to put modules meant to be shared.

How do I tell PowerShell to look for modules there, without having to specify this every time I start PowerShell?

For now, I just:

  1. created a PS subdirectory in N:\common\utils (PS for PowerShell, of course)
  2. Started PowerShell on my PC and created a profile file in the $profile directory (per Recipe 1.6 from the Windows PowerShell Cookbook):
    New-Item -type file -force $profile
  3. edited the profile file using Notepad.exe:
    notepad $profile
  4. and added a line to add the common directory to the PSModulePath environment variable:
    $env:PSModulePath += “;N:\common\utils\PS”
    (the leading semicolon is the profile path separator)
  5. exited notepad, saving $profile on the way out.

 

Now, whenever I start PowerShell, the $profile runs and adds the PS shared folder to the module search path.

To do the same thing (less step 1) for the Windows PowerShell ISE, I consulted Microsoft Technet article How to Use Profiles in Windows PowerShell ISE, which suggests wrapping the New-Item in step 2 in an if statement to prevent overwriting an existing profile, and using the ISE to edit the resulting profile file:

  1. (PS subdirectory already created in N:\common\utils)
  2. Started the PowerShell ISE and created a profile file in $profile:
    if (!(test-path $profile)) {New-Item -type file -path $profile -force}
  3. edited the profile file (using the ISE editor):
    psEdit $profile
  4. and added the same line to add the common directory to PSModulePath:
    $env:PSModulePath += “;N:\common\utils\PS”
  5. then closed the ISE editor tab, saving the ISE $profile file on the way out

 

Now I just have to figure out modules and module manifests…

Automating web browsing using PowerShell

A lot of our Production Quality Control (QC) operations where I work require checking that data has been uploaded to one of our websites, using either one of our internal tools, or our backdoor access to one of our customer-facing sites. This is all right when we’re checking a couple of customer jobs, but gets tedious VERY quickly for routine QC of dozens or hundreds of customer jobs.

A web app works well as a manual tool (“enter text to be searched for in this box, click Search, click the link for desired item in the list of items matching your search term…”), but our internal tools and customer-facing sites were never designed to be scripted.

For a while, when I was working with more cross-platform scripting languages, I was looking at Selenium. Selenium allows you to control popular web browsers from a number of programming languages, including Python, Ruby, and C# – but not directly from PowerShell. It would be possible to write my own PowerShell wrapper for C# to control Selenium, but I don’t have any experience extending PowerShell with C#, and since we’re not a C# shop, I think that would be very fragile from a long-term maintenance standpoint.

Anyway, unlike the typical Selenium application, our Production QC ops aren’t testing a single web app across multiple browsers. We’re searching for a multitude of data items, but we only have to find each one once, in a single web browser. A more robust solution would be to use something more native to PowerShell to control a single browser – which could even be Internet Explorer (perish the thought!).

I Googled “powershell web browser automation” and came up with a number of possibilities.

Web UI Automation with Windows PowerShell, is an MSDN article from 2008 and talks about using COM to control Internet Explorer, which is something I’ve dabbled in using VB Script. My first experiment with the method wasn’t successful, though, so I looked for troubleshooting info for COM in my handy copy of Windows PowerShell in Action. As it happens, the book illustrates COM with an example of “…a COM-based tool to help manage…browser windows,” so the book probably offers a more fertile field for further research.

A post on StackOverflow then led me to WatiN – Web Application Testing in .Net. WatiN allows control of Internet Explorer AND Firefox, so it might be even better than using COM.

Find subfolders that lack a given file(name)

Our processing automation at work creates a number of files during processing. One way we can tell when the automation hasn’t completed successfully is when the processed files directory has been created, but the files that are created at the end of processing are missing from the directory.

Here’s a PowerShell script fragment to identify subfolders (two levels down) that lack a given file (target.txt in this example) :

PS > Get-ChildItem |
>>   ForEach-Object {
>>     Set-Location $_
>>     Get-ChildItem |
>>       Where-Object {!(Test-Path $_\target.txt)}
>>     Set-Location ..
>> }
>>

And here’s a one-liner version of the above:

PS > ls | %{ cd $_ ; ls | ?{!(test-path $_\target.txt)} ; cd ..}

It’s not perfect – if it encounters a file (rather than a subdirectory) one level down, it attempts to Set-Location to that filename and throws an error (because you can’t Set-Location to a file, only a folder). However, it seems to find all the folders missing the target.txt file before it attempts to Set-Location to that file.

PowerShell – Get-WmiObject vs. Get-CimInstance

A recent post on the Hey, Scripting Guy! blog showed how to use PowerShell to find a network adapter’s MAC address. The post provided two ways to get the information using WMI:

Get-WmiObject win32_networkadapterconfiguration | select description, macaddress

Get-CimInstance win32_networkadapterconfiguration | select description, macaddress

I wondered about the difference between GetWmiObject versus Get-CimInstance. Happily, while exploring older Hey, Scripting Guy! posts, I found one about simplifying PowerShell scripts that addressed the difference(s):

One of the first changes I make to a script, if I can, is I change Get-WmiObject to Get-CimInstance. Since Windows PowerShell 3.0, I can use Get-CimInstance. It is faster and more robust, and it permits lots of cool things for retrieving data (such as using Cim-Sessions).

Since most of our servers here are running PowerShell 2.0 right now, it will be a while before I can routinely use Get-CimInstance instead of Get-WmiObject — but it’s something for me to keep in mind for the future.

Scriptify – A navigation aid for SharePoint 2013 PowerShell Cmdlets

Via yesterday’s Hey, Scripting Guy! blog –

Scriptify – A navigation aid for SharePoint 2013 PowerShell Cmdlets is a web-based reference for PowerShell cmdlets related to SharePoint 2013. The cmdlets are divided into 36 categories – clicking on a category’s button takes you to a page of buttons to access the invidual cmdlets in that category. Clicking on a cmdlet’s button takes you to a page with parameters for the cmdlet and a link to its Technet homepage.