Sometimes you want to use an icon of a particular file for another purpose such as working with a custom UI in either WinForms or Windows Presentation Foundation (WPF) where you can supply the Base64 data to automatically load the image into the form. Or maybe you just want to gather all of the icons and throw them into their own folder for whatever reason.
The function that I created, called Get-Icon should not be confused with the awesome work that fellow MVP Chrissy Lemaire did with Export-Icon as hers can dig into a DLL to pull out many icons while mine is focused on the grabbing the existing icon for a particular file type.
For my examples, I am going to use the icon for my own Get-Icon.ps1 file which has the familiar PowerShell image that we all know and love.
To get started, I need to load up an assembly to take advantage of a method that will help to extract the icon image from the file.
Add-Type -AssemblyName System.Drawing
The method in question is ExtractAssociatedIcon which comes with the System.Drawing.Icon class and accepts a parameter of a string path name. We can then use that method to pull the icon as shown below:
$Path = 'C:\Users\boepr\Desktop\Get-Icon.ps1' $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)
I now have my System.Drawing.Icon object which I can just leave be or take it a step further by converting it to a bitmap using the ToBitmap() method.
Fortunately, converting this to Bitmap is as simple as calling the method: ToBitmap() and it does all of the work for you.
From there we can actually save the file as a bitmap using the Save() method in the bitmap object. Save() takes a number of parameters with the simplest being just the file path.
I’m taking the simple path tonight to save the file.
And we can see the new file with the actual icon when we open it up.
Converting to bytes isn’t as simple as just calling a method called ToBytes(). This becomes a job for System.IO.MemoryStream which I can use to store the byte array and then present it as output.
$MemoryStream = New-Object System.IO.MemoryStream $Icon.save($MemoryStream) $MemoryStream.ToArray()
What happens after I call ToArray() is that you are then bombarded with a lot of byte information in the console. From there you could just pipe that information into Set-Content and use the –Encoding Byte to write those bites to a file that would then look just like what we did with saving a bitmap.
$MemoryStream.ToArray() | Set-Content -Path "C:\Users\boepr\Desktop\SomeFile.bmp" -Encoding Byte
I also call Flush() and Dispose() at the end to clean up after myself.
The last part I wanted to show is converting this to a Base64 encoded string that you could use to supply an icon to a WinForm or WPF control as an image. Again, there isn’t a ToBase64() method, but that is ok. What is cool is that we already did most of the work previously with the MemoryStream object that we created.
$MemoryStream = New-Object System.IO.MemoryStream $Icon.save($MemoryStream) $Bytes = $MemoryStream.ToArray() $MemoryStream.Flush() $MemoryStream.Dispose()
The only thing left to do is convert those bytes into the encoded string by using ToBase64String() which resides in the [Convert] type that is available to use.
Pretty simply, right? All you have to do is copy and paste this and you are ready to go!
As I mentioned earlier, I do have a function called Get-Icon that will do all of this for you…well with the exception of actually saving the file, but you can use the knowledge here to do that with no effort at all.
A few examples of it in action are below.
Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe'
$FileName = 'C:\Temp\PowerShellIcon.png' $Format = [System.Drawing.Imaging.ImageFormat]::Png (Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBitmap).Save($FileName,$Format)
Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' –ToBase64
Give it a download below and let me know what you think!