HOWTO: Monitor a webpage and alert on change

This is admittedly kind of a silly HOWTO but does contain a number of very useful concepts.

I am eagerly awaiting the Lenovo Thinkpad P50 laptop.  The official webpage for this laptop went live today but for pricing it simply says “Coming Soon”.
Rather than refresh the page constantly, I figured I’d let PowerShell do the work for me.  Specifically:

1) Connect to the shop.lenovo.com website every hour and check if the “Coming Soon” pricing has changed
2) If the text is still present, do nothing
3) If the the “Coming Soon” text has been removed (presumably replaced by actual pricing) do the following:
4) Create a pop up tooltip in the Windows System tray alerting me that the pricing is now available
5) In case I miss the popup, email me as well.

To accomplish this, take the code below, save it to a file and create a scheduled task to run it every hour.  That’s it.  You will now be notified as soon as the laptop is available for purchase!

Note: You may be wondering why I didn’t use the built-in Invoke-WebRequest cmdlet.  Normally I would but for Lenovo’s website specifically, I would consistently get “403 – Forbidden” errors.
I tried adding custom user agents and even went as far as using Fiddler to figure out what a good header looks like and then copied that.
The issue appears to be that the Lenovo website is compressed with Gzip and encoded in such a way that (I couldn’t figure out anyway) how to make it work with the built in tool.

imageimage

Function Show-BalloonTip($Text)
{
# Set notification title and message.
$Title = "Lenovo P50 Countdown"
$Message = $Text

# How long to display the notification in milliseconds.
# Must be between 10 and 30 seconds.
$Timeout = 30000

# Balloon icon type: None, Info, Warning or Error.
$BalloonIcon = "Info"

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$NotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$HostProcessPath = Get-Process -id $pid | Select-Object -ExpandProperty Path
$NotifyIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($HostProcessPath)
$NotifyIcon.BalloonTipTitle = $Title
$NotifyIcon.BalloonTipText = $Message
$NotifyIcon.BalloonTipIcon = $BalloonIcon
$NotifyIcon.Visible = $True
$NotifyIcon.ShowBalloonTip($Timeout)

Start-sleep -Seconds 10
$NotifyIcon.Dispose()
}

Function Get-Webpage($URL)
{
$request = New-Object System.Net.WebClient

# Custom headers required to access shop.lenovo.com as the page is compressed with gzip and otherwise returns 403 Forbidden errors
$request.headers.add("User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko")
$request.headers.add("Accept-Language: en-US")
$request.headers.add("X-Requested-With: XMLHttpRequest")
$request.headers.add("Accept: text/html, application/xhtml+xml, */*")
$request.UseDefaultCredentials = $true
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$request.Proxy.Credentials = $request.Credentials

$RawHTML = $request.DownloadString($URL)

# The text comes in one long string. Seperate out each line on each carriage return
$RawHTML -split "`r`n"
}

$HTML = Get-Webpage "http://shop.lenovo.com/ca/en/laptops/thinkpad/p-series/p50/"

# Currently Coming Soon appears 3 times in the code. Once pricing appears this should no longer be present so display the message
if (($HTML | select-string "coming soon" | measure-object).count -ne 3)
{
Show-BalloonTip "The Thinkpad P50 is ready for purchase!"

$smtpServer = "mail.domain.com"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "me@mydomain.com"
$msg.To.Add("target@domain.com")
$msg.IsBodyHTML = $false
$msg.Subject = "Lenovo P50 Pricing is a go!"
$msg.Body = "The Lenovo P50 website is no longer saying coming soon and presumably has pricing now!"
$smtp.Send($msg)
}

HOWTO: Identify and Run every valid Get-* cmdlet on your system

I recently found myself on a long bus ride with my laptop and no Internet connection.  I decided to create a PowerShell puzzle for myself to keep me busy until I reached my destination.  It ended up being kind of interesting so I wanted to share my puzzle and the solution with here.

Challenge

PowerShell has the concept of “Get-*” cmdlets where these will only retrieve information but will never change anything.  This makes Get commands safe to run, even if you don’t know what they do.   PowerShell ships with hundreds of Get cmdlets.  It would be great to know what kind of information each one provided.  To do that I’d need to run every Get command.  That’s simple enough but is complicated by the fact  that most Get- cmdlets come with multiple ‘parameter sets’ and many are configured with mandatory parameters.  This means that if we blindly run each command we’ll end up with a bunch of errors and prompts for user input.

So what we need to do is figure out which of the Get- commands can be run without passing any parameters.  We then also want to exclude commands that run properly but don’t return any data by default.

Solution

Check out the script below.  It will scan the system for every Get- command and then will figure out which ones can be executed directly without parameters and will actually return data.  It then runs all of those and returns the first 5 objects so you can get a feel for what kind of data is returned.  It will then display a report showing how many cmdlets met each criteria.  On my system for example we can see that 143 commands can be executed and return something useful just by typing the name of the command and hitting enter.

image

Continue reading

HOWTO: Convert SQL data to PowerShell Objects

As you develop your PowerShell skills, you’ll start to see how they can be useful everywhere – even in places where it might not seem obvious.
Let’s say you have a SQL database that you need to extract information from but you’re not terribly strong with SQL.  You are pretty good with PowerShell though.
Wouldn’t it be great if you could easily "convert" your SQL data into a native PowerShell object and then do all of your filtering and customization there?  In a language you know and love?

I found myself in that exact situation and I’m pleased to say I found a simple and elegant solution.

Sidenote: As I was preparing for this blog post, I realized it can be incredibly difficult to build screenshots and database queries that don’t contain potentially sensitive information.

Let’s make up a scenario in which we have a database called ‘rdm’ and inside that there is a table called ‘ConnectionLog’.
We want to find the 5 dates in which the user ‘rvance’ logged in most frequently.  Let’s assume we are doing some kind of security analysis. 

Continue reading

Adele would be amazing at Karaoke

I was browsing the news today and learned that Adele recently performed on Saturday Night Live.  It’s clear by this point that she is a very capable singer. But for a major television performance, I always just cynically assume that the artist is seldom actually singing.  I often expect them to be either dubbed based on a studio recording or with liberal use of Autotune being applied.  Here is an example of what I mean:

 

https://www.youtube.com/watch?v=crv5uchJmGM

Or how about this?  Here is a much more humorous take on how much work is required to make singers sound actually good called “Sound Engineer’s Hard Work”:

 

All of this brings us to the point.  The reason I knew Adele performed on SNL is because her raw mic audio feed was leaked from the performance.  If this were to happen to a good chunk of modern musicians these days, I suspect their PR teams would be working a lot of overtime.  But Adele is not most musicians.  The raw audio feed was in my opinion even better than the full song with all of the other instruments and backup singers.  There are not many artists that can carry a song entirely on their own with nothing but their voice but Adele would be one of them.

Continue reading

HOWTO: Create Fastest Possible Custom Objects [Revisit]

In November of last year I did a post called the "Fastest Possible Way to Make Custom Objects in PowerShell".

https://pleasework.robbievance.net/howto-fastest-possible-way-to-make-custom-objects-in-powershell/

That post came about because I was frustrated with the techniques I was using at the time to make custom objects and decided to sit down and once and for all simply the process.
If you have a look at that code, you’ll see using it was simple enough but initializing it was all sorts of bizarre.

I’m pleased to say that in the year since I’ve wrote that post, I’ve learned a lot about PowerShell. I’ve learned that I made things far, far more complicated than it needed to be.*
(* The technique above technically is still useful for PowerShell 2 environments as the technique below I’m pretty sure isn’t supported there)

Let’s say you want to make a custom object.  Specifically let’s say you want to show the filename of all files in a folder and the first line of each file.  Look how easy this is now:

Get-ChildItem c:\windows\*.log | % { [pscustomobject]@{‘Filename’=$_.fullname; ‘FileContent’= (Get-Content $_.fullname | select -first 1)} }

If that doesn’t make any sense, here is the important part.  To make a custom object, do the following:

[pscustomobject]@{‘column1name’=column1content;’column2name’=column2content;}

You’re using a "type accelerator" called [pscustomobject] and defining it as a hash table (series of key/value pairs).  The right side of the equals in each line can be wrapped in round brackets allowing you to run anything you want and save it into the final object, just as I did above with Get-Content.

Very cool stuff!

HOWTO: Reusable Template with Windows Server Trial

This HOWTO covers how use the free 180 trial version of Windows Server 2012 R2 to build a reusable template for lab and development purposes.
The objective of the steps below are as follows:

  • Ensure that whenever we need to deploy a new Windows Server for testing, it will always have the latest updates and customizations
  • Each deployment will be sysprepped ensuring there are no SID conflicts when using multiple machines
  • Allow for the latest updates and new customizations to be be added in the future without impacting already deployed test machines
  • New Server 2012 R2 VMs including fresh domain controllers and domain joined member servers must be spun up as quickly as possible with as little user intervention as possible
  • The process must allow for an unlimited number of Syspreps to take place
  • This entire guide must be repeated every 6 months as we are using the free trial version of Windows Server 2012 R2
  • Any machines deployed during the 6 month trial period will reset and start from their own 180 day counter independent of the source
  • The implement will leverage the linked clone snapshot feature found in VMware Workstation

 

Overview

The idea behind this build is to provide the fastest possible way to build new Windows 2012 R2 Active Directory lab environments.
I’m aware there are other solutions available but I wanted to see what I could accomplish using nothing more than the 180 day trial ISO, VMware Workstation and PowerShell.
The configuration may seem a little complex but once these steps are in place, it becomes hilariously easy and fast to deploy new test servers at home for testing.
The idea is to build out a new VM using the trial, snapshot it, sysprep it and then use PowerShell scripts to automatically build new Domain controllers and join to the domain using Desired State Configuration.

Continue reading

HOWTO: Desired State Configuration (DSC) Overview

I found myself curious if I could get my entire lab environment to build itself from scratch in a 100% automated fashion including deploying and configuring Active Directory.

All of the cmdlets to perform these tasks already exist in PowerShell and are trivial to perform individually.  But what happens if you want to combine them together?  In order to do that, you have to be able to manage restarts and be able to continue your script where it left off.  That turns out to be a non-trivial problem for traditional PowerShell scripts.  As I was researching how I might accomplish this, I stumbled across something called “Desired State Configuration” or DSC.  I’ve heard it talked about constantly over the last year or two and all of the major PowerShell bloggers have stated that it is the concept to learn after you’ve got the basics of PowerShell down.  I’ve never had a reason to look into it though… until now.

The first thing I did was start watching the Microsoft JumpStart series on DSC.  I just assumed it would be a module’s length but to my shock and surprise, Microsoft created an entire course on just DSC and that course is 2 full days – equal to that of the JumpStart for PowerShell itself!  The next thing that jumped out at me is that at the beginning of the video series, one of the hosts and inventor of PowerShell, Jeffrey Snover said:

“DSC is not just a priority at Microsoft, it is THE priority at Microsoft.”  That may sound like hyperbole coming from most people but remember that Jeffrey Snover is now the Technical Lead Architect for Windows Server.  So even accepting he probably meant his team specifically, that’s still a big deal for those working in IT as most of our time is spent with the products he is responsible for.

With that backstory out of the way, what exactly is Desired State Configuration and why should you care?  Here is what I’ve been able to piece together so far.  DSC is a mechanism for you to define how a server or servers should be configured.  Notice I did not say how specifically to configure them.  This is the first thing that took me a while to wrap my head around.  In DSC, you never define HOW to configure a server, only WHAT you want the final product to look like.  Think of DSC more as a manager than a programmer.

The way this is accomplished is Microsoft (and others) create something called “resources” which are effectively large, complex PowerShell modules that are written by professional programmers that contain all of the logic and error handling and dependency management that is almost always missing from amateur scripts.  You then use a special subset syntax of PowerShell to declare what you want and PowerShell will go out and do it for you.

Continue reading

Why are people on Kijiji like this?

I’ve recently put up several items on Kijiji and in doing so received a number of interested replies.  Unfortunately, many of those replies are practically unintelligible.

Why is this?  At first I thought that many of them are some kind of bot or automated software that intentionally uses exceptionally poor grammar but I couldn’t think a reason anyone would benefit from this since the people on the other end are already willing to provide you details and meet you.  So these replies must be from actual human beings.

Is our Education system really that bad?  Could it be that they are all non-native English speakers?  I’ve been in enough countries and met enough non-native English speakers to know that it’s not that.  ESL writers can come across as having poor English certainly, but it’s… different.  You can spot the mix up of language structures or at the very least identify that some modicum of effort was put into the writing.

As a public service, I’d like to present two such replies I received from two different people and rewrite the sentences in a way that makes some better degree of sense.  Names and phone numbers are changed.

“evething is gor 100 , am poor woma but my son is crasy got one of thid box i cant buy it . but is it 100 i like to buy it gor him ,let mr know pleas thank you .5551234567 bob”

“Everything is for $100.00.  I am a poor woman but my son is crazy.  He wants one of those Xboxes but I cannot afford it.  But is it really $100?  I’d like to buy it for him.  Let me know please.  Thank you.  555-123-4567 – Bob”

“I'm interested of Xbox, can you send me, cll no. Then I ca pay the xbox”

“I am interested in your Xbox.  Can you send me your cell phone number?  Then I can pay you for the Xbox.”

HOWTO: Stop VMs from locking when idle

Tell me if you’ve heard this one before.  You build a bunch of new VMs for your lab environment.  You have them all running but every time you switch back to a VM you find that it’s always locked and you  have to press Control-Alt-Delete and enter your password.  In a production environment, this is a great behavior but in a home lab it is maddening.  I finally sat down to try and fix this and it turns out it seems pretty simple.  Simply add the following two lines to your deployment script:

powercfg -change -monitor-timeout-ac 0
powercfg -change -standby-timeout-ac 0

What these commands do is change the following two properties (Turn off the display and Put the computer to sleep) for the currently active PowerPlan and sets them to Never.

image

HOWTO: Build Tasklist for Studying for Microsoft Exams

This HOWTO is fairly specific to me but since I needed to document it anyway I figured I would share it in case in benefited others.
I have scheduled yet another Microsoft Exam for October.  One of the techniques I use during studying is to take the base “Skills Measured” list from Microsoft and build a checklist around it so I can keep track of what to review next.  To do this I traditionally copy and paste the list from the Microsoft exam site and painstakingly edit it to make it compatible with a commercial task tracking software I purchased called Swift To-Do List.  It’s mind-numbing repetitive work and I always tell myself I’m going to try and automate it but never do.  Well that ends today.

What am I talking about exactly?  Well let’s use an example.  I’m scheduled to write the 70-462 – Administering SQL 2012.  So I visit the site (https://www.microsoft.com/learning/en-ca/exam-70-462.aspx) and get something that looks like this:

image

There are a series of one level collapsible trees that contain all types of items on the exam.  The catch is rather than provide them in a list, the entries are separated by semi-colons.  What would be so much more useful is if I could transform that list into something like this:

image

Continue reading