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!
Awesome stuff, thank you!
Pingback: PowerShell Server Inventory, Part 3: Viewing the Inventory using a UI | Learn Powershell | Achieve More
Seriously cool work. Combining this with some automation for Citrix and its amazing how many times I’ve run into your work when trying to pull together concepts! Thanks for sharing!
Quick question – Is the data in $Icon.ToBitMap() the same as an ICO file? Further, is the data that comes out of the -ToBase64 routine the same as you would get from converting an ICO to Base64? Citrix has a requirement for the icon data to be ‘Base64 encoded .ICO format icon data’. From what I can tell the data stream (using PowerShell to look at the data stored in Citrix) doesn’t match between the output of Get-Icon -ToBase64.
I’m sorry to say it happened again. In the meantime I accessed the web page with Firefox: everything is working fine, I could download the script (btw: great again).
The problem is still occuring for me with IE11 on Win 8.1 x64.
Thanks for the great script, I love your blog
Can’t download the script from Scriptcenter. Is it corrupt?
EULA appears, then the web page reloads only (other downloads are working)
Weird. I just tried this and couldn’t reproduce the issue. Can you try downloading again and see what happens?
Pingback: Icons aus Dateien bzw. Icons zu Dateitypen per Powershell extrahieren | Das nie endende Chaos!