Category Archives: General

General stuff, usually just stuff related to networking and admin.

PowerShell .NET and GUI Interfaces

I’ve been grabbing a bit of software from Technet (you know, that thing that Microsoft are shutting down! <_<) and with their download links, they provide SHA1 hashes of the ISOs. I had a quick look around the web for something that allowed you to get SHA1 hashes of files and while I found a few, I didn't find any that would allow you to provide a hash and compare the resultant hash with the one you're given by the provider so I decided to write one myself and as with any opportunity, I decided to use PowerShell and .NET with Windows Forms to create a GUI interface as opposed to it all being text based. Sacrilege to those PowerShell purists but it's a limited feature tool and I wanted to learn something new so here's the code.

Function Get-FileName($initialDirectory)
{   
 [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |  Out-Null

 $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
 $OpenFileDialog.initialDirectory = $initialDirectory
 $OpenFileDialog.filter = "All files (*.*)| *.*"

 $OpenFileDialog.ShowDialog() | Out-Null
 $OpenFileDialog.filename
} #end function Get-FileName

#We’re going to draw a form.
[System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”) | Out-Null

#Open a GUI for the user to select the file.
$Filename = Get-FileName -initialDirectory "C:\"

# Check that the path is correct
If (!(Test-Path $Filename)) { Exit }

# Create Input Data (Read the file)
$File = [System.IO.File]::Open($Filename, "open", "read")

# Create a New SHA1 Crypto Provider
$Sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider

# Output the hash (converted to Hex)
$Hash = [String]::Concat(($Sha1.ComputeHash($File) | % { $_.ToString("x2") }))

#[System.Windows.Forms.MessageBox]::Show("$Hash", "SHA1 Hash", 0)


# Create a GUI Form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = “SHA1 Hash Calculator/Comparison Tool”
$objForm.MaximumSize = $objForm.MinimumSize = $objForm.Size = New-Object System.Drawing.Size(400,250)
$objForm.MaximizeBox = $objForm.MinimizeBox = $false
$objForm.StartPosition = “CenterScreen”

# Add a label
$oTitle = New-Object System.Windows.Forms.Label
$oTitle.Location = New-Object System.Drawing.Size(5,5)
$oTitle.Size = New-Object System.Drawing.Size(385,40)
$oTitle.Text = "The calculated hash for your selected file is shown below. You can paste a known hash and compare the two by clicking the compare button."
$objForm.Controls.Add($oTitle)

#File Label
$oFileLabel = New-Object System.Windows.Forms.Label
$oFileLabel.Location = New-Object System.Drawing.Size(5,(53))
$oFileLabel.Size = New-Object System.Drawing.Size(105,20)
$oFileLabel.Text = “File:”
$objForm.Controls.Add($oFileLabel)

# Add a Textbox
$oFileTB = New-Object System.Windows.Forms.TextBox
$oFileTB.Location = New-Object System.Drawing.Size(($oFileLabel.Left + $oFileLabel.Width + 5),($oFileLabel.Top -3))
$oFileTB.Size = New-Object System.Drawing.Size(265,20)
$oFileTB.Text = $Filename.ToString()
$oFileTB.ReadOnly = $true
$objForm.Controls.Add($oFileTB)

# Add a Richtextbox
#$oTitle = New-Object System.Windows.Forms.RichTextBox
#$oTitle.Location = New-Object System.Drawing.Size(0,0)
#$oTitle.Size = New-Object System.Drawing.Size(385,45)

#$oTitle.Rtf = "{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang2057{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}{\f1\fnil\fcharset0 Calibri;}}
#{\*\generator Riched20 6.3.9600}\viewkind4\uc1 
#\pard\sa200\sl276\slmult1\f0\fs16\lang9 The calculated hash for your selected file \b ("+$Filename.Replace("\", "\\")+")\b0  is shown below. You can paste a known hash and compare the two by clicking the compare button.\f1\fs22\par
#}"
#$oTitle.ScrollBars = "None"
#$oTitle.ReadOnly = $True

#$objForm.Controls.Add($oTitle)


# Add a label
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(5,(53+50)) # Everything elses location is calculated in reference to this.
$objLabel.Size = New-Object System.Drawing.Size(105,20)
$objLabel.Text = “Calculated SHA1:”
#$objLabel.TextAlign = "MiddleRight"
$objForm.Controls.Add($objLabel)

# Add another label
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Text = "Comparison SHA1:"
#$objLabel2.TextAlign = "MiddleRight"
$objLabel2.Location = New-Object System.Drawing.Point ($objLabel.Left, ($objLabel.Height + $objLabel.Top + 10))
$objLabel2.Size = New-Object System.Drawing.Size(105,20)
$objForm.Controls.Add($objLabel2)

# Add a Textbox
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(($objLabel.Left + $objLabel.Width + 5),($objLabel.Top -3))
$objTextBox.Size = New-Object System.Drawing.Size(265,20)
$objTextBox.Text = $Hash
$objTextBox.ReadOnly = $true
$objForm.Controls.Add($objTextBox)

# Add comparison box
$objSuppliedVal = New-Object System.Windows.Forms.TextBox
$objSuppliedVal.Location = New-Object System.Drawing.Point ($ObjTextBox.Left, ($objTextBox.Height + $objTextBox.Top + 10))
$objSuppliedVal.Size = New-Object System.Drawing.Size(265,20)
$objForm.Controls.Add($objSuppliedVal)

# Add an Exit button
$ExitButton = New-Object System.Windows.Forms.Button
#$ExitButton.Location = New-Object System.Drawing.Size(300,100)
$ExitButton.Location = New-Object System.Drawing.Point (($ObjTextBox.Right – 75), ($objSuppliedVal.Height + $objSuppliedVal.Top + 10))
$ExitButton.Size = New-Object System.Drawing.Size(75,23)
$ExitButton.Text = “Exit”
#$ExitButton.Add_Click({$objForm.Close()})
$objForm.CancelButton = $ExitButton
$objForm.Controls.Add($ExitButton)

# Add compare button
$CompareButton = New-Object System.Windows.Forms.Button
$CompareButton.Location = New-Object System.Drawing.Point (($ExitButton.Left – $ExitButton.Width – 10), ($objSuppliedVal.Height + $objSuppliedVal.Top + 10))
#$CompareButton.Location = New-Object System.Drawing.Size($ExitButton.Left – $ExitButton.Width – 10,100)
$CompareButton.Size = New-Object System.Drawing.Size(75,23)
$CompareButton.Text = “Compare”
$CompareButton.Add_Click({
    
    $SuppliedValue = $objSuppliedVal.Text.ToLower()
    $CalculatedValue = $objTextBox.Text.ToLower()

    $MsgBoxButtons = New-Object System.Windows.Forms.MessageBoxButtons
    $MsgBoxIcon = New-Object System.Windows.Forms.MessageBoxIcon

    If ($SuppliedValue -eq $CalculatedValue) {

        $MsgBoxButtons = "OK"
        $MsgBoxIcon = "Information"

        [System.Windows.Forms.MessageBox]::Show("Matched successfully.", "Success", $MsgBoxButtons, $MsgBoxIcon)

    }
    Else {

        $MsgBoxButtons = "OK"
        $MsgBoxIcon = "Warning"

        [System.Windows.Forms.MessageBox]::Show("Not matched.", "Not matched", $MsgBoxButtons, $MsgBoxIcon)
    
    }



})
$objForm.Controls.Add($CompareButton)


$objForm.Topmost = $true
$objForm.ShowDialog()



# Clear up
$File.Dispose()

All that lot should give you:
A prompt to select the file you want to calculate the hash of
Open Dialog
The hash result
Hash Result
And then, if you supply a hash and click the Compare button, it’ll say either
Match SuccessMatch Failure

Now I’m sure there are PowerShell gurus out there that could have all this done in 4 lines of code but it was a learning experience so the code is always likely to be a little more verbose than is absolutely necessary.

Feel free to use the code but plug me as a source if you’re going to use the code on your own blog if you wouldn’t mind.

-Lewis

HTML5 Canvas Scaling

Recently I’ve had some time to fettle with things other than Infrastructure and Windows servers so I’ve decided to do my company website with HTML 5. It’s nothing special but as part of my tinkering, I created a new logo and I thought it’d be cool to re-create it in HTML5 Canvas so it was unique and somewhat versatile.

The process starts out as quite a difficult task. How on earth do you re-create a logo by drawing some lines? Well, to cut a long story short, I opened it up in my favourite vector drawing app (the one I used to create it) and just copied the x,y coordinates of the anchor points on to an HTML5 canvas that was the same size as the artboard the illustration was on.

First you’ll need a canvas element on your HTML5 page. Something like:

Pay attention to the width and height declarations since this is the canvas size (in pixels) you’re drawing on.

<canvas id="logo" height="102" width="102">Browser says no...&lt;canvas&gt;</canvas>

The end result is pretty cool. All of this:


function drawLogo(target) {
var element = document.getElementById(target);
var canvas = element.getContext("2d");

/*
Originally drawn on 102px x 102px canvas (it wouldn't go smaller without distorting!)
Use this scale (the original canvas size)
to calculate the appropriate scaling values for
the intended target canvas.
*/

var oScaleY = 102;
var oScaleX = 102;

canvas.scale ((element.width / oScaleX), (element.height / oScaleY)); //Scale the canvas to fit the canvas object's width height.

canvas.beginPath();

canvas.moveTo(5, 4); // Starting Point
canvas.lineTo(5, 30);
canvas.lineTo(23, 30);
canvas.lineTo(23, 40);
canvas.lineTo(5, 40);
canvas.lineTo(5, 66);
canvas.lineTo(23, 66);
canvas.lineTo(23, 77);
canvas.lineTo(5, 77);
canvas.lineTo(5, 103);
canvas.lineTo(90, 103);
canvas.lineTo(98, 90);
canvas.lineTo(90, 77);
canvas.lineTo(79, 77);
canvas.lineTo(79, 66);
canvas.lineTo(84, 66);
canvas.lineTo(92, 53);
canvas.lineTo(84, 40);
canvas.lineTo(79, 40);
canvas.lineTo(79, 30);
canvas.lineTo(92, 30);
canvas.lineTo(100, 17);
canvas.lineTo(92, 4);

canvas.closePath();

// Seemingly the gradient size must be based on the original drawn canvas.
var grad = canvas.createLinearGradient(0,oScaleX,0,0);

grad.addColorStop(0, "rgb(46,92,139)");
grad.addColorStop(0.25, "rgb(0,113,188)");

canvas.fillStyle = grad; // Set the gradient as the fill colour.

canvas.fill(); // Fill the closed path (with the gradient)

canvas.fillStyle = "rgb(255,255,255)"; // Set a new fill colour (white)
canvas.fillRect(29, 30, 44, 10); // Create a filled (white) rectangle.

canvas.beginPath();

canvas.moveTo(29, 66);
canvas.lineTo(29, 77);
canvas.lineTo(64, 77);
canvas.lineTo(64, 81);
canvas.lineTo(73, 81);
canvas.lineTo(73, 62);
canvas.lineTo(64, 62);
canvas.lineTo(64, 66);

canvas.closePath();

canvas.fill();
}

drawLogo("logo"); // Actually draw the logo

Gives you something looking like this:

Anyway, I’m not here to teach you how to re-create my company logo in HTML5, needless to say, that’s what it looks like. The JavaScript function above does some clever scaling so if your intended target HTML5 canvas element defines its height and width as something other than what you drew the original anchor points on, it’ll scale to that appropriately. To explain, I originally drew this on a 102px x 102px canvas so all the canvas.lineTo declarations relate to that size canvas. Say I want to scale it up to say 300px x 300px, I can use the canvas.scale method to achieve that so this bit of code calculates the scaling factor and applies that to the canvas which helps to retain quality when it’s scaled unlike bitmaps which, as we know, don’t scale well.

/*
Originally drawn on 102px x 102px canvas (it wouldn't go smaller without distorting!)
Use this scale (the original canvas size)
to calculate the appropriate scaling values for
the intended target canvas.
*/

var oScaleY = 102;
var oScaleX = 102;

canvas.scale ((element.width / oScaleX), (element.height / oScaleY)); //Scale the canvas to fit the canvas object's width height.

Now, as we look at the site on a desktop PC, the logo looks great and is razor sharp. It’ll scale up nicely in multiples of 2 by adjusting the canvas element’s width and height properties and retain its sharpness but values other than that will give you blurred edges. Still, SVG does the same thing as far as I can tell from my own eyesight.

So what’s the problem? Well, given that the new site is supposed to be responsive design and degrade (I think I’ll call it re-grading since there’s no loss of functionality for my site) for mobile and tablet, when you look at that image on a mobile or tablet, it looks blurred because the devicePixelRatio is greater than 1 and the image is scaled up by the device but retains the original dimensions as defined on the canvas element itself.

On a Nexus 5 with a devicePixelRatio of 3 (at least that’s what its browser tells me it is) this blurriness is quite profound and looks something like this which, for a sharp site, looks shocking compared to the HTML5 SVG above.

nexus5_screenshot

nexus7_screenshot

So, the fix to me seems logical: you should scale the canvas element up by the declared devicePixelRatio amount, let the scaling calculation in the drawing function handle the actual size that comes out and scale back using CSS.

So, here’s the extra code before we call our drawLogo function:

// Upscale the canvas element for mobile HiDPI screens.
// It gets scaled down again to the original size by CSS.
// Keeps the HTML5 canvas sharp on all screen types.

var canvas = document.getElementById("logo");
canvas.width = canvas.width * window.devicePixelRatio;
canvas.height = canvas.height * window.devicePixelRatio;

To retain the 102px x 102px image size that we originally intended for our canvas (remember this works for other sizes too!) and for it to look good (not just a bigger image) we need to use CSS to keep the canvas element’s dimensions at what we originally intended for our canvas.

canvas {
height: 102px;
width: 102px;
}

In essence what I’ve done is to increase the dimensions of the canvas element proportionally to the devicePixelRatio so, if the devicePixelRatio is 3, the in-flight JavaScript resizes the entire element to: width = (102 x 3), height = (102 x 3). The increased size of the canvas element is passed to the drawLogo function which creates an image 3 times the size. This is then drawn on to the canvas which is then styled using CSS back down to 102px. The best way to think of this is like using an oversized PNG scaled down within the img dimensions so it looks OK on mobile devices.
The end result is images that are sharp and consistent across desktop, tablet and mobile screens:

nexus7_improved

nexus5_improved

desktop_original

NB: Please remember that I’ve only been able to test this with the limited hardware available to me, all of which are Android devices. Nexus 5, Nexus 7 (2012 and 2013), Samsung Galaxy Nexus and of course my Windows 8.1 desktop. If you get different or inconsistent results with your devices, please let me know!

Windows Server 2012 R2

Windows Server 2012 R2 Upgrades

So I decided to shift all my stuff to a new Windows Server 2012 R2 box instead of the amalgamation of Fedora 18, nginx, haproxy and a Windows Server 2008 R2 server hosting my web and FTP sites. They worked well as a reverse proxy when I had SSL sites using the same certificate hosted on Linux and Windows servers so I have no complaints, it was just getting a bit long in the tooth and I tihnk my Fedora installation is a couple of releases behind now so patches are few and far between. I’ve had my Fedora installation since something like version 12 but it seemed timely to move from Linux since Fedora have lost the ability to upgrade easily like in the previous six releases. Plus, I get to kill off a number of cross-platform VMs and consolidate everything to a single box. High Availability and Disaster Recovery? At home? Pah.

When Windows Server 2012 came out, I installed it and, well, it was just a non-starter for me. I was left so frustrated with the stupid omission of any kind of Start button that I refused to use it for personal use. Stabbing at 4 pixels in the bottom left corner of the screen or moving my left hand to press the button on the keyboard is already a Bad Idea™ but clearly whoever thought of it had never even considered that people use RDP or vSphere console windows which your mouse flows out of! Even if I Full Screen an RDP session, what if I have a second or, heaven forbid, a third monitor? Having what amounts to a button made up of 4 pixels to hit is utter stupidity. The screenshot below is Windows 8.1 running in a VM with VMware Tools installed – look Microsoft, my mouse moves out of the console seamlessly so placing my mouse on an “edge” isn’t easy.

Windows81

Of course the businesses I work for are a different story so it’s not like I haven’t had exposure to (and frustration with) Windows Server 2012 but thankfully R2 brings a Start button back.

I realise Microsoft want us to run their server in non-GUI mode (for security purposes) but it’s unrealistic to expect a generation of Windows administrators to suddenly abandon their knowledge and intrinsic understanding of a Microsoft OS to learn PowerShell administration where it is far easier to make a horrible mess. I’m pretty solid with PowerShell but I have no desire to configure a Windows Server using it. If I had to create 50 servers exactly the same, perhaps. Also, it’s called Windows not Commands, so ner.

2012R2Start_button

So, Windows Server 2012 R2 seems pretty good. I’ve had some interesting challenges with abnormally terminating connections to FTPS and FTPES servers hosted in IIS but it seems to be related to the client I was using and, well, if the owner of said FTP client refuses to provide a solution to a problem that clearly a large number of people are experiencing (And only with his app), I’ll just use something else and recommend something else too if people ask.

I’m about to embark on a similar approach to consolidation with Windows 8.1 (I have a Windows 7 and Windows 8 box which I’ll consolidate to just the one 8.1) and, who knows, it might even end up on my laptop or desktop! *Gasp* Soon I’ll build out a domain and test out some of that new functionality like failover DHCP, data deduplication and a supposedly simplified DirectAccess setup – which were available in 2012 already but since I didn’t enjoy using it, I didn’t play.

– Lewis

Managed Service Accounts in Windows 2012

One for the notebook if you tend to use Managed Service Accounts extensively and eventually end up implementing them in a Windows Server 2012 environment.

For Windows Server 2012, the Windows PowerShell cmdlets default to managing the group Managed Service Accounts instead of the original standalone Managed Service Accounts.

A useful alteration but surely retaining the default use and extending the cmdlet would make it less prone to us admins using MSAs regularly to smashing up keyboards.

-Lewis

Active Directory Recycle Bin

Windows Server 2008 R2 delivered a new feature called the Active Directory Recycle Bin which offers the ability to restore items deleted from the Active Directory database by restoring them from the Recycle Bin with the simplicity of….well, it’s not really that simple.

The premise is simple enough. You’ve deleted an item that you want to restore so instead of breaking out the backups, taking down a Domain Controller, booting in to DSRM and re-acquanting yourself with NTDSUTIL, you enable the Recycle Bin to save you all that hassle.

But wait a minute! Before enabling the Active Directory Recycle Bin (ADRB) there are a couple of caveats which you should be aware of. Now, Microsoft will tell you what you need to enable your use of ADRB such as:

  • Forest Functional Level: Windows Server 2008 R2.
  • All Domain Controllers running Windows Server 2008R2

…but the limits that enabling Active Directory Recycle Bin can have on restore operations is significant enough to ensure that your Backup Operators and Data Security personnel need to be consulted before you make a unilateral decision to enable it.

  1. Enabling ADRB transitions all currently Tombstoned (deleted) objects to the new Recycled object state. This effectively means that current Tombstoned objects (objects deleted in the last 180 days) should never be restored, either through object reanimation or via an authoritative restore.
  2. Similar to the above, once an object reaches the Recycled object state (after 180 days of being a Logically Deleted object) it cannot be restored or recovered from backup. Microsoft recommends that you do not use authoritative restores at all after enabling ADRB and that you only use ADRB to restore objects during their deleted object lifetime (DOL). This article: http://technet.microsoft.com/en-us/library/dd379542(WS.10).aspx details the recommendation which effectively means that restores must be done within the deleted object lifetime or you should consider the object completely unrecoverable. The deleted object lifetime can be adjusted at the expense of an increased AD database size and replication traffic but the default is 180 days.
  3. ADRB cannot restore changed objects – this must be done using an authoritative restore while the object is still live. Hopefully the proper use of change processes in your organisation should  minimise the eventuality of this occurring and permit the ability to simply undo a change but we all know what happens in the real world.
  4. Enabling ADRB results in the size of your Active Directory database increasing (and consequently the replication bandwidth requirements) to accommodate the new object states before objects deleted are completely removed from the database. The increase is dependent on the amount and type of objects created and deleted but since there is a new object state, the time the objects remain in the database is effectively doubled.

Once each of these discussion points has been thoroughly considered should you look at enabling the Active Directory Recycle Bin.

I know this subject is fairly old hat given that Windows Server 2012 is now available but I’m still astonished by the numbers of Active Directories that I come across that aren’t making use of the Active Directory Recycle Bin. Reading the pro-tip (can I call myself a pro?) enabling it in Windows Server 2012 is pretty much a no-brainer with the easy-peasy GUI on offer, just be mindful of the implications.

Pro tip: Although the procedure for using the Recycle Bin is currently based on PowerShell, Windows Server 2012 provides a Graphical User Interface to permit much simpler use of the Recycle Bin feature.

Admission: I actually wrote this article nearly 12 months ago but never finished it or published it – since then Windows Server 2012 has been released so I’ve made mention of that in the article.

And just like that…

I’m no longer looking for new challenges in 2013! I have one ready to go and it sounds fantastic. I’m looking forward to helping my next employer bring their network infrastructure and supporting services bang up to date so they can provide a cutting edge service to wow their existing customers, expand their client base in to new markets and grow their business the way they want it to grow.

If I don’t say so beforehand, I hope you all have a Happy Christmas 2012 and a prosperous New Year in 2013 and beyond. Here’s to new challenges in 2013!

-Lewis

Looking for new challenges in 2013

I’m now on the lookout for new contract opportunities beginning in early 2013 and would welcome new contacts in the industry to get in touch if you’re looking for a highly skilled Windows Server Enterprise Administrator, Service Design Engineer or Project Technical Lead.

If you’re interested in making contact, please use my LinkedIn profile at: http://uk.linkedin.com/in/lewisroberts/

Thanks!
Lewis

Orange infuriate my soul

I recently applied to join Orange as I was spending more than I needed to on my monthly bills with T-Mobile. I gave T-Mobile a chance to match the deal I could get with Orange but they could only give me it on a 12 month contract. I don’t do twelve month contracts any more, one month rolling is all I’m willing to sign up to since I buy my own mobiles unlocked and outright.

Since I’ve only lived at my new address for 18 months, Orange wanted proof of my address using some kind of utility bill so, being the environmentally friendly person I am using paperless billing and online accounts as much as possible, I downloaded my latest bill from my energy provider and emailed it to Orange’s referral team as requested…this is what I got back.

So the referrals department received my proof but weren’t able to accept it….

No explanation as to why or what the cause of their non-acceptance was they just didn’t accept something they asked for and were sent. So am I to guess what they want?!

Last chance Orange or I take my business to O2, again.