Pretty up those GUI scripts (1 of 2)

Posted: August 9, 2017 in Powershell, Scripting, Uncategorized

One of the major things that occurs with GUI scripts is the generic form icons that come with the host, and of course there are buttons that almost always have a plain text label, and other controls that are just plain text labels (like a treeview).
However, one of the things that can be done is to use the .Image property of your controls, so that you can get an external icon.  I’ve seen some done like this, and along with the .ps1, they include a graphics file (icon, bitmap, etc.).. you’ll typically see some snippet like this:

 $button = New-Object -Type System.Windows.Forms.Button
 $button.Top = 10
 $button.Left = 10
 $button.Width = 35
 $button.Height = 35
 $button.Image = '.\MyButtonIcon.ico'
 

But, this also requires that the icon file be distributed with the script, and always put in the correct location etc.. This makes portability a little tougher..

To that end, I did some poking around and found I stumbled across this article [https://adminscache.wordpress.com/2013/06/09/base64-encoding-of-images] to embed some icons in a system tray notification.  With this, I was able to create a pair of functions that allow me to get the icons into Base64 string, and then read them back into memory and use them as the Image part of any control.  The two functions are Convert-FileToBase64 which can be used for pretty much any purpose, and Get-IconFromBase64 which reads in the Base64 string and converts it to an in memory icon.

Part 1 covers the Convert-FileToBase64 function.  This is surprisingly simple, and since the output is plain text, it can be used for any number of purposes.

As with any properly defined function, the first thing to do is specify the parameters, most of this is very straightforward

param(
   [parameter(mandatory = $true, ValueFromPipelineByPropertyName = $true)]
   [ValidateScript({Test-Path -path $_})]
   [string]$FilePath
)

We start with the typical param( ) block.. Normally, I would start with the [cmdletbinding()]  to provide the common parameters.  But this script is very simple, and does not really require the -verbose, -debug or other such parameters.  The items mentioned here in the param( ) block are very straightforward.  If there are questions, please post them in the comments section, and I’ll attempt to answer them there.

The next line is the primary work of the function.. it reads in the file as a series of bytes (no interpretation of the data) and uses the built in .Net convert function to change these into Base64 encoding.

$EncodedFile = [convert]::ToBase64String( (get-content -Path $FilePath -Encoding Byte) )

The “problem” with this is that the output is a long string, that is unbroken, and depending on the circumstances can be very unwieldy.  To that end, I added a line to break this up into the typical 64bit lines like you would see in a certificate file.

$EncodedFile = $EncodedFile -replace '.{64}', "$&`r`n"

The -replace function uses the ‘.’ to match any character, and the {64} tells it to grab 64 characters.  The replace uses $& which says “give me the entire match” (all 64 characters) and then it adds the carriage return, line feed (`r`n).

The last line of the function just returns the $EncodedFile

return $EncodedFile

I grabbed an icon from shell32.dll using Nirsoft’s IconsExt.exe
shell32_10

Now, using the script, I am able to grab the full Base64 string.. (not completely posted here for length)

Convert-FileToBase64 -FilePath c:\temp\icons\shell32_10.ico

AAABAAkAMDAQAAEABABoBgAAlgAAACAgEAABAAQA6AIAAP4GAAAQEBAAAQAEACgB
AADmCQAAMDAAAAEACACoDgAADgsAACAgAAABAAgAqAgAALYZAAAQEAAAAQAIAGgF
AABeIgAAMDAAAAEAIACoJQAAxicAACAgAAABACAAqBAAAG5NAAAQEAAAAQAgAGgE
AAAWXgAAKAAAADAAAABgAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
...

Now, in order to use this icon in your GUI script, simply capture the full output (copy and paste, redirect into clip.exe etc.) into your script as a here string.

For example:

$DiskDriveIcon = @'
AAABAAkAMDAQAAEABABoBgAAlgAAACAgEAABAAQA6AIAAP4GAAAQEBAAAQAEACgB
AADmCQAAMDAAAAEACACoDgAADgsAACAgAAABAAgAqAgAALYZAAAQEAAAAQAIAGgF
AABeIgAAMDAAAAEAIACoJQAAxicAACAgAAABACAAqBAAAG5NAAAQEAAAAQAgAGgE
AAAWXgAAKAAAADAAAABgAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
...
'@

The next article will show it in use..

[edit: I forgot the actual script!]


function Convert-FileToBase64
{
<#
.SYNOPSIS
Reads in a binary file and converts it to a Base64 string

.DESCRIPTION
Converts the binary file to a Base64 string, and breaks it up into 64 character lines

.PARAMETER FilePath
The path to the file to be converted

.EXAMPLE
PS C:\> Convert-FileToBase64 -FilePath C:\Temp\MySampleIcon.ico

AAABAAEAICAAAAEACACoCAAAFgAAACgAAAAgAAAAQAAAAAEACAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADx8f8AoqL/AHx8/wCZmf8A7e3/ALGx/wANDf8AAAD/AAkJ
/wCnp/8AkpL/AAsL/wA0NP8ADw//ADAw/wDh4f8A39//AMzM/wDIyP8A3d3/AEBA
/wA2Nv8A////AP7+/wCpqf8AKCj/ABgY/wCTk/8A+fn/AElJ/wA3N/8Atrb/ABoa
/wAMDP8Al5f/APr6/wDS0v8AKSn/ABIS/wClpf8A4+P/AC8v/wABAf8Ar6//APz8
/wDs7P8AT0//ABsb/wC4uP8AXFz/AAIC/wADA/8AHBz/ALOz/wD9/f8Ad3f/AAcH
/wBUVP8AkZH/ACcn/wB+fv8AUVH/APLy/wCdnf8AEBD/ABUV/wCrq/8AOTn/ANra
/wD39/8Aj4//AC4u/wDT0/8AsrL/ACws/wDY2P8ABAT/ANXV/wDPz/8AFBT/APj4
/wB2dv8AZmb/AGpq/wATE/8AdXX/AAYG/wArK/8ASEj/AJiY/wD7+/8A8PD/AHFx
/wBWVv8Ag4P/AIaG/wB6ev8AIiL/ANDQ/wDq6v8AcHD/ADw8/wCNjf8A9PT/AOjo
/wDZ2f8APj7/AKio/wAAAAAAw8P/AKys/wBeXskABwf1AAQE9wBPT8cAv7//AIuL
rwAKCvAABgbzAHZ2rADv7/8AhIT/AGlp/wA5Od4ABAT5AAMD+gAxMd0A6en/AOTk
/wAtLf8AJCT/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbICBBwcHBwcHBwcHBwcHBwcH
BwcHBwcHBwcHBweCRGxseHl6enp6enp6enp7fAcHBwd9fnp6enp6enp6ejx/bGxs
bGxsbGxsbGxsbHR1BwcHB3Z3bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsdHUHBwcH
dndsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx0dQcHBwd2d2xsbGxsbGxsbGxsbGxs
bGxsbGxsbGxsbHR1BwcHB3Z3bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsdHUHBwcH
dndsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx0dQcHBwd2d2xsbGxsbGxsbGxsbGxs
bGxsbGxsbGxsbHR1BwcHB3Z3bGxsbGxsbGxsbGxsbG1ubm5ubm5ubm5ub3AHBwcH
cXJubm5ubm5ubm5uc2xJCwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc4axsH
MiEhISEhISEhISEhISEhISEhISEhISEhISEhMwcKCgdHaWlpaWlpaWlpaWlpaWlp
aWlpaWlpaWlpaWlqBwoKBx4WFmNkZWZnFhYWFhYWFhYWFhYWFlBoABcWFh0HCgoH
HhYWXioHTF8cFhYWFhYWFhYWFhYAYGEdYhYWHQcKCgceFhZYBwcHDVlaFhYWFhYW
FhYWW1xWBypdFhYdBwoKBxUWFlMHBwcHVAUWFhYWFhYWFlBVVgcHB1cWFh0HCgoH
FRYWTiUHBwcHTxI2FhYWFhZQUQgHBwcqUhYWHQcKCgceFhYXSSYHBwcHSksWFhYW
IxtMBwcHBylNFhYdBwoKBx4WFhY2QiEHBwcHQ0QWFkVGOAcHBwdHSBcWFh0HCgoH
HhYWFhY2PDgHBwcyPT4WP0AHBwcHQREXFhYWHQcKCgceFhYWFhY2NzgHBwcqOToh
BwcHBzsSFhYWFhYdBwoKBx4WFhYWFhYEMTIHBwczBgcHBwc0NRcWFhYWFh0HCgoH
HhYWFhYWFhYtLgcHBwcHBwcHLzAWFhYWFhYWHQcKCgceFhYWFhYWFhYoKSoHBwcH
BwYrLBYWFhYWFhYdBwoKBx4WFhYWFhYWFhYkJQcHBwcmJxYWFhYWFhYWFh0HCgoH
HhYWFhYWFhYWFhcfIAcHISIjFhYWFhYWFhYWHQcKCgcVFhYWFhYWFhYWFhcYGRob
HBYWFhYWFhYWFhYdBwoKBw4PDw8PDw8PDw8PDxAREhMPDw8PDw8PDw8PDxQHCgoH
CwwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQcKBQYHBwcHBwcHBwcHBwcHBwcH
BwcHBwcHBwcHBwcHCAkAAQICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBIAA
AAGAAAAB//AP///wD///8A////AP///wD///8A////AP/4AAAAEAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

.NOTES
This was built to automatically convert an ICON file to a Base64 string for use in a powershell script, but
it can be used for any type of binary file. The only limitation is the amount of memory available.

.LINK
PowerShell Base64 Encoding of Images
.INPUTS system.io.fileinfo system.string .OUTPUTS system.string #> param( [parameter(mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ValidateScript({Test-Path -path $_})] [string]$FilePath ) $EncodedFile = [convert]::ToBase64String( (get-content -Path $FilePath -Encoding Byte) ) $EncodedFile = $EncodedFile -replace '.{64}', "$&`r`n" return $EncodedFile }

David F.

 

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.