Summary: Learn how to use Windows PowerShell to create a custom file extension to store code snippets.

Weekend Scripter: Creating a .snip file type

Microsoft Scripting Guy, Ed Wilson, here. After I created the Get-CodeSnippet function yesterday, I decided that it might be useful to have my own file extension to keep track of code snippets.

The reason is that to make using code snippets truly useful, the code needs to be designed specifically to be added to my script. It can take the form of reusable functions, or it can even take the form of script block skeletons. Rather than weeding through a bunch of .ps1 or .psm1 files, I thought I would make my own extension.

The New-SnipType.ps1 script adds a couple of registry keys as shown here.

New-SnipType.ps1

New-PSDrive -Name HKCR -PSProvider registry -Root HKEY_CLASSES_ROOT | Out-Null

Push-Location

Set-Location -Path HKCR:

New-Item -Name .snip -ItemType String -Value snip_file | Out-Null

New-ItemProperty -Path HKCR:\.snip -Name PerceivedType -Value Text `

   -PropertyType String | Out-Null

New-Item -Name snip_file -ItemType string | Out-Null

New-Item -Name shell -Path HKCR:\snip_file -ItemType string | Out-Null

New-Item -Name edit -Path HKCR:\snip_file\shell -ItemType string | Out-Null

New-Item -Name command -Path HKCR:\snip_file\shell\edit -ItemType ExpandString `

   -Value "%SystemRoot%\system32\NOTEPAD.EXE %1" | Out-Null

New-Item -Name open -Path HKCR:\snip_file\shell -ItemType string | Out-Null

New-Item -Name command -Path HKCR:\snip_file\shell\open -ItemType ExpandString `

   -Value "%SystemRoot%\system32\NOTEPAD.EXE %1" | Out-Null 

Set-Location -Path HKCU:

$FEPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts"

New-Item -Name .snip -Path $FEPath | Out-Null

New-Item -Name OpenWithList -Path $FEPath\.snip | Out-Null

New-ItemProperty -Name a -Path $FEPath\.snip\OpenWithList `

   -value "Notepad.Exe" -PropertyType String | Out-Null

New-ItemProperty -Name MRUList -Path $FEPath\.snip\OpenWithList `

    -value a -PropertyType String | Out-Null

New-Item -Name OpenWithProgids -Path $FEPath\.snip | Out-Null

New-ItemProperty -Name snip_file -Path $FEPath\.snip\OpenWithProgids `

    -value "(zero-length binary value)" -PropertyType Unknown | Out-Null

New-Item -Name UserChoice -Path $FEPath\.snip | Out-Null

New-ItemProperty -Name Progid -Path $FEPath\.snip\UserChoice `

    -value "Applications\Notepad.Exe" -PropertyType String | Out-Null

Pop-Location 

Remove-PSDrive -Name HKCR

The first thing I do in the New-SnipType.ps1 script is create a new Windows PowerShell drive, by using the New-PSDrive cmdlet. I use the registry provider, and I specify the root as HKEY_CLASSES_ROOT. The reason for this is that, by default, the HKEY_CLASSES_ROOT registry hive is not exposed via a Windows PowerShell drive. Because the New-SnipType.ps1 script is working with the HKEY_CLASSES_ROOT hive, the script must be run with elevated rights. You might wish to add the Test-IsAdministrator function to ensure that the script has the appropriate rights.

Next, I store the current drive location by using the Push-Location cmdlet, and I then change my working location to the HKCR: drive. Now I create several new registry keys and registry key properties. When I am finished on the HKCR: drive, I change to the HKCU (HKEY_CURRENT_USER) drive and create some more values. When I am finished on that drive, I change drives back to the original drive by using the Pop-Location cmdlet. I then use the Remove-PSDrive cmdlet to remove the newly created HKCR: drive.

The type for a new registry key must be an instance of the Microsoft.Win32.RegistryValueKind .NET Framework enumeration class. Using my Get-EnumValues function that I have in my Windows PowerShell ISE startup profile, I obtain the following information about the RegistryValueKind as shown here.

PS C:\Users\ed.NWTRADERS> get-enumValues Microsoft.Win32.RegistryValueKind

 

Name                           Value                                                                                                                       

----                             -----                                                                                                                       

MultiString                     7                                                                                                                           

QWord                          11                                                                                                                          

DWord                          4                                                                                                                           

Binary                           3                                                                                                                           

ExpandString                  2                                                                                                                           

String                           1                                                                                                                           

Unknown                       0

It is perhaps a bit unfortunate that the EnumValues do not match the data types (such as REG_SZ) that are displayed in the Registry Editor, but things such as REG_DWORD and REG_BINARY are close enough to DWord and Binary that one can figure them out. String values like MultiString (REG_MULTI_SZ) and ExpandString (REG_EXPAND_SZ) cause admins confusion.

Because this is a special purpose, one-time use type of script, I did not add any error checking, or command line Help. After the script runs, the .snip file type will be recognized, and will open in Notepad when double-clicked. An If_Else.snip appears as shown in the following image.

WES-2-6-11-01

If I add the .snip file extension to the Open file dialog box filter that I created yesterday, I can easily pull up a list of all of my code snippets.

One other thing—I consider it to be bad form to write code that makes a bunch of changes to the registry without also writing code to clean up after those changes. That is a great advantage about using a Windows PowerShell script to make the changes in the first place. Here is the Remove-SnipType.ps1 script.

Remove-SnipType.ps1

New-PSDrive -Name HKCR -PSProvider registry -Root HKEY_CLASSES_ROOT | Out-Null

Push-Location

Set-Location -Path HKCR:

Remove-Item -Path HKCR:\.snip -Recurse

Remove-Item -Path HKCR:\snip_file -Recurse 

Set-Location -Path HKCU:

Remove-Item -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.snip -Recurse  

Pop-Location 

Remove-PSDrive -Name HKCR

Well, that is all there is to creating a custom file extension in the registry.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy