Quickly Create a PowerShell Snippet in the ISE Using an Add On

As you know, starting with PowerShell V3, we have had the ability to create our own snippets within the PowerShell ISE. I actually covered doing this a while back using the New-ISESnippet cmdlet that is available to use so I won’t re-hash all of that for you. Instead, I will cover using the PSISE object to build an add-on that you can then use to quickly put together a snippet with little effort at all!

Looking at the $psISE object (note that this is only available when you are actually opened up in the ISE), you will need to look at the available methods under the CurrentPowerShellTab property and there you will see the AddOnsMenu property which contains all of the AddOns which are available to use for that particular tab.

$psISE.CurrentPowerShellTab.AddOnsMenu

image

Here we can see that there are no menus available at this point in time, but soon that will change.

Under this property is the SubMenus property, and more importantly its Add method which takes a number of parameters based on the parameter set that you use which contribute to the building of the AddOn menu.

image

For this article, I am going with the first set which means that we need to have a DisplayName, a ScriptBlock containing the code that will run and lastly a keyboard shortcut that we can use to quickly call the code in the menu.

Now that we have covered the basics here of building a menu addon, we can now build our menu to create a snippet. I’ll actually have 2 snippet builder menus, one to take the entire script that is in the window and create a snippet and another that will take a selected portion of a script and create a snippet from it. To make it a little more user friendly, I will use Microsoft.VisualBasic.Interaction to create some input boxes so the required information (Name and Description) can be added to the snippet.

Using the code below, we can create our addons that will then show up in the ISE as well as having their own keyboard shortcut to use.

Create a Snippet from Selected Code in Script File

[void]$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add("Save-SelectedSnippet",{
    $Text = $psISE.CurrentFile.Editor.SelectedText
    If (($Text -notmatch '^\s+$' -AND $Text.length -gt 0)) {
        Try {
            [void][Microsoft.VisualBasic.Interaction]
        } Catch {
            Add-Type –assemblyName Microsoft.VisualBasic
        }
        $Name = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Snippet Name", "Snippet Name")
        $Description = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Snippet Description", "Snippet Description")
        If ($Name -and $Description) {
            New-IseSnippet -Description $Description -Title $Name -Text $Text –Force
            Write-Host "New Snippet created!" -ForegroundColor Yellow -BackgroundColor Black
        }
    }
},"Alt+F8")

Create a Snippet from Whole Script File

[void]$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add("Save-Snippet",{
    $Text = $psISE.CurrentFile.Editor.Text
    If (($Text -notmatch '^\s+$' -AND $Text.length -gt 0)) {
        Try {
            [void][Microsoft.VisualBasic.Interaction]
        } Catch {
            Add-Type –assemblyName Microsoft.VisualBasic
        }
        $Name = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Snippet Name", "Snippet Name")
        $Description = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Snippet Description", "Snippet Description")
        If ($Name -and $Description -AND ($Text -notmatch '^\s+$' -AND $Text.length -gt 0)) {
            New-IseSnippet -Description $Description -Title $Name -Text $Text –Force
            Write-Host "New Snippet created!" -ForegroundColor Yellow -BackgroundColor Black
        }
    }
},"Alt+F5")

 

As you can tell from the last parameters, the keyboard shortcuts are Alt-F8 for the selected code snippet and Alt-F5 for the snippet from the entire script file. This might seem familiar as this follows the same logic when it comes to running the code in the ISE (F5 runs all code and F8 runs selected code).

We can go back and verify that this worked a couple of ways first by looking at the properties of the menu…

image

… or by looking at the ISE menu itself…

image

And now we can see both of these in action.

Full Snippet

TestFullSnippet

Selected Snippet

TestSelectedSnippet

Enjoy!

Posted in powershell | Tagged , , , | 4 Comments

Quick Hits: Tracking The Status of GitHub Using PowerShell

This evening I noticed that GitHub, a site for collaborating and sharing code that I use for all of my projects, was down for an unknown reason. The site showed the dreaded ‘Unicorn of 503’ and I was left without access much like everyone else attempting to not only access the site, but also those attempting to send updates for their repos.

githubdown

Now, I could sit at my computer and hit the refresh button dozens of times until I see something other than the fabled unicorn…or I can take advantage of a web api to make a call to return some JSON that PowerShell just happens to enjoy to provide a quick way to monitor the situation.

The available URLs that we can use are below:

URL Purpose
https://status.github.com/api/status.json View Current Status
https://status.github.com/api/messages.json View Recent Status Messages
https://status.github.com/api/last-message.json View Current Status Message
https://status.github.com/api/daily-summary.json View Daily Summary

Using each of these are as simple as using Invoke-RestMethod and bringing back the data. Let’s take a look at the current status and see how things are going.

Invoke-RestMethod https://status.github.com/api/status.json

image

Note the time listed is in Zulu, meaning that if we wanted to know our own time, we need to do a little work with that by just calling Get-Date with that string as the parameter.

Invoke-RestMethod https://status.github.com/api/status.json | Select-Object Status, @{L='Updated';E={Get-Date $_.last_updated}}

image

That looks a lot better!

Moving on we can look at the other approaches and see what they have to offer.

Invoke-RestMethod https://status.github.com/api/last-message.json
Invoke-RestMethod https://status.github.com/api/messages.json

image

The Daily Status api actually gives you a roundup of every status (shown as a count for Major, Minor and Good) that goes all the way back to February 7 2010, which is pretty cool.

Invoke-RestMethod https://status.github.com/api/daily-summary.json

image

…Eventually we get to the bottom with the current date.

image

So there you go! Go out and track the status of GitHub with PowerShell and come up with your own approaches to report when the status changes!

Posted in powershell | Tagged , , , , , | Leave a comment

Getting the Icon from a File Using PowerShell

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.

image

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)

image

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.

ToBitmap()

Fortunately, converting this to Bitmap is as simple as calling the method: ToBitmap() and it does all of the work for you.

$Icon.ToBitmap()

image

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.

image

I’m taking the simple path tonight to save the file.

$Icon.ToBitmap().Save('C:\users\boepr\Desktop\SomeFile.bmp')

And we can see the new file with the actual icon when we open it up.

imageimage

ToBytes()

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.

$MemoryStream.Flush()
$MemoryStream.Dispose()

ToBase64()

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.

 

[convert]::ToBase64String($Bytes)

image

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'

image

$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

image

Give it a download below and let me know what you think!

Download Get-Icon

https://gallery.technet.microsoft.com/scriptcenter/Get-Icon-to-pull-icon-from-6eea1aef/file/147507/1/Get-Icon.ps1

Posted in powershell | Tagged , , | 4 Comments

Updated Function to Remove Long Files and Directories

I had a post last month ( or year for that matter) on Hey, Scripting Guy! where I talked about using PInvoke and PowerShell to create a function that allowed you to remove files which were nested too deep in a folder path causing a long path issue meaning that the file could not be removed.

The problem with this function is that it could only remove a file by using the DeleteFile function. While this is great, it could really use some extra features such as being able to remove directories which includes deleting the child files/folders…similar to what you would have with Remove-Item.

In order to do this, I need to look at working with RemoveDirectory to actually delete the folder. The next issue is that I first need to remove all of the child objects under the directory which includes other files and folders and continue to recursively go through each sub-folder until I reach the end and at that point I can remove the folder.

The result is my function called Remove-Item2 which performs like Remove-Item with the exception of the only parameter that you have is –Path.

For those interested, here is the code that I put together for the recursive folder and file deletion.

If ($Handle -ne -1) {
    While ($Found) {
        If ($findData.cFileName -notmatch '^(\.){1,2}$') {
            $IsDirectory =  [bool]($findData.dwFileAttributes -BAND 16) 
            Write-Debug "$(Get-PSCallStack | Out-String)" 
            If ((Get-PSCallStack).Count -eq 2) {
                $_FullName = "$($Path)"
            } Else {                   
                $_FullName = "$($Path)\$($findData.cFileName)"
            }
            If ($IsDirectory) {                        
                #Dive deeper
                $PSBoundParameters.Fullname = "$_FullName\*"                  
                Remove-Item2 @PSBoundParameters
                If ($PSCmdlet.ShouldProcess($_FullName.TrimStart('\\?\'), 'Remove Directory')) {
                    #Remove file
                    $Return = [poshfile]::RemoveDirectory($_FullName)
                    If (-NOT $Return) {
                        Write-Warning "Unable to remove $_FullName"
                    }
                }
            } Else {
                If ($PSCmdlet.ShouldProcess($_FullName.TrimStart('\\?\'), 'Remove File')) {
                    #Remove file
                    $Return = [poshfile]::DeleteFile($_FullName)
                    If (-NOT $Return) {
                        Write-Warning "Unable to remove $_FullName"
                    }
                }
            }
        }
        $Found = [poshfile]::FindNextFile($Handle,[ref]$findData)
    }
    [void][PoshFile]::FindClose($Handle)
}

I used Get-PSCallStack to help me determine where I am at in the folder path as each call to the function would increase the callstack which helped me to actually delete the top level folder that I was looking to remove. I tried a few other approaches like a counter or setting another variable, but they had less than desirable results.

The result is a function that you can use to clear out files and folders which are normally unreachable using Remove-Item as shown below:

image

The function is available below from the Script Center Repository to use. Give it a run and let me know how you like it!

Download Remove-Item2

https://gallery.technet.microsoft.com/scriptcenter/Remove-LongPathFile-7a4db495

Posted in powershell | Tagged , , | 2 Comments

2016 PowerShell Resolutions

I had a pretty good response with my post from last year on your PowerShell resolutions both in the comments and elsewhere on the internet for 2015 that I decided to do another one!

First I am going to look back on my previous resolutions and see how I did:

  • Learn more about Desired State Configuration (DSC)
    • Didn’t really do a whole lot with DSC, but did make a resource and stood up a couple of systems, but didn’t blog about it (figured people with more knowledge had this one nailed down).
  • Speak at a local conference (SQL Saturday, InfoTech, Nebraska.Code(), etc…)
    • I did speak at Nebraska.Code() which was a great time and hopefully will get to do it again this year. Attempted to speak at SQL Saturday in Omaha but didn’t make the final cut.
  • Continue to speak at User groups (at least 2 this year)
    • I spoke at the Mississippi PowerShell User Group as well as the Omaha PowerShell User Group this year.
  • Develop a new project for 2015 (I actually have mine for 2014 published, but haven’t gone ‘public’ with it just yet)
    • I had a few different projects going this year with PoshRSJob being continuously worked on as well as a project on working with Privileges using PoshPrivilege.

Looking back, I think I did a decent job at meeting my resolutions. I think the DSC resolution was the weakest one of the bunch that I got done, but the nice thing about that is that there are plenty of things to learn and mess with!

With that behind me, the next logical step it to come up with another 4 resolutions that I would like to accomplish at some point during the next year…all PowerShell related of course!

  • Speak at a local conference (SQL Saturday, InfoTech, Nebraska.Code(), etc…). Yes I am using this again but really it is never guaranteed to speak at these things so making one would be great!
  • Work with PowerShell Classes, etc…. These are new in PowerShell V5 and I honestly haven’t even messed with these much, so it is on my TODO list.
  • Start working on re-writing a module as a binary module in C# to better learn the language.
  • Do something with web APIs and OAuth stuff. I keep meaning to invest some time with this but always get side tracked.

There we go! My resolutions are set and now it is time to start working to accomplish these! As always, I would love to hear what you are planning on doing in 2016 with PowerShell and will definitely look forward to reading these in the comments!

Posted in News, powershell | Tagged , , , | 1 Comment