{"id":12037,"date":"2016-05-23T06:00:00","date_gmt":"2016-05-23T13:00:00","guid":{"rendered":"https:\/\/www.sapien.com\/blog\/?p=12037"},"modified":"2016-05-23T07:13:58","modified_gmt":"2016-05-23T14:13:58","slug":"add-custom-tools-to-the-menu","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2016\/05\/23\/add-custom-tools-to-the-menu\/","title":{"rendered":"Add custom tools to the menu"},"content":{"rendered":"<p>There are so many features in PowerShell Studio and PrimalScript that <a href=\"https:\/\/www.sapien.com\/blog\/2015\/09\/28\/hidden-charms-of-powershell-studio\/\">I think I can&#8217;t live without<\/a>, like the Format Script button, <a href=\"https:\/\/www.youtube.com\/watch?v=YaFb2gbPSWQ\">file groups<\/a>, and <a href=\"https:\/\/www.sapien.com\/blog\/2016\/04\/20\/setting-conditional-breakpoints\/\">conditional breakpoints<\/a>.<\/p>\n<p>But, there are few features I&#8217;d love to have that aren&#8217;t there. They&#8217;re easy enough to add, but they&#8217;re really personal to me. Fortunately, I can add them myself.<\/p>\n<h1>What is a custom tool?<\/h1>\n<p>The <i>Custom Tool<\/i> feature in PowerShell Studio and PrimalScript lets you define commands in an INF file and add them to a menu.<\/p>\n<p>For example, I have huge Scripts library on One Drive where I keep all of my scripts. When I get to a certain point in my script development, I want to copy the current script to my Scripts library without closing it or finding its path.<\/p>\n<p>No problem! In PowerShell Studio, I click <b>Tools<\/b> and, in the File group, click <b>Custom Tool<\/b>, <b>Copy to One Drive<\/b>.<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image002.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image002\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image002_thumb.jpg\" alt=\"clip_image002\" width=\"395\" height=\"335\" border=\"0\" \/><\/a><\/p>\n<p>In PrimalScript, I click <b>Home<\/b> and, in the Build and Run group, click <b>Custom Tool<\/b>, <b>Copy to One Drive<\/b>.<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image004.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image004\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image004_thumb.jpg\" alt=\"clip_image004\" width=\"404\" height=\"211\" border=\"0\" \/><\/a><\/p>\n<p>As you can see, I also have options to copy to a different location, run a PowerShell Get-Acl cmdlet, run a script, open a module directory, open a Git shell, and open some very special INF files.<\/p>\n<h1>Which commands can I use in a custom tool?<\/h1>\n<p>You can run almost any command, including cmd.exe commands, Windows PowerShell commands and scripts, and commands to executable files, like robocopy.exe, netstat.exe, and git.exe.<\/p>\n<ul>\n<li><b>Cmd.exe<\/b>: To run a command that&#8217;s internal to cmd.exe, precede the command with &#8216;cmd&#8217; or &#8216;cmd.exe&#8217;.<\/li>\n<li><b>Executables<\/b>: To run a command in an executable file, such as robocopy.exe, git.exe, or ipconfig.exe just type the command with any valid switches.<\/li>\n<li><b>PowerShell<\/b>: To run PowerShell cmdlets, functions, or scripts, precede the command with &#8216;powershell&#8217; or &#8216;powershell.exe&#8217;. When running scripts, be sure to include the full path to the script file. Also, verify that your local execution policy permits you to run scripts.<\/li>\n<\/ul>\n<p>In the commands, in addition to using valid parameters, arguments, and switches, you can include variables for values that PowerShell Studio resolves before it sends the command to the editor.<\/p>\n<table class=\"nicetable\">\n<tbody>\n<tr>\n<td>$ProjectFolder$<\/td>\n<td>Path to the current project directory. Valid only when a project is open.<\/td>\n<\/tr>\n<tr>\n<td>$PowerShell$<\/td>\n<td>PowerShell version number selected on the ribbon.<\/td>\n<\/tr>\n<tr>\n<td>$Platform$<\/td>\n<td>Current platform (x86 or x64).<\/td>\n<\/tr>\n<tr>\n<td>$WinDir$<\/td>\n<td>Path to the Windows directory (e.g. C:\\Windows).<\/td>\n<\/tr>\n<tr>\n<td>$WinSystem$<\/td>\n<td>Path to the Windows system directory (e.g. C:\\Windows\\System32).<\/td>\n<\/tr>\n<tr>\n<td>$Selection$<\/td>\n<td>Currently selected content, if any. Might contain carriage return\/ linefeed characters.<\/td>\n<\/tr>\n<tr>\n<td>$File$<\/td>\n<td>Full path to the current file, if any.<\/td>\n<\/tr>\n<tr>\n<td>$FileName$<\/td>\n<td>Name of the current file (no path).<\/td>\n<\/tr>\n<tr>\n<td>$FileDir$<\/td>\n<td>Path to the directory of the current file (no file name).<\/td>\n<\/tr>\n<tr>\n<td>$Dir$<\/td>\n<td>Full path to PowerShell Studio installation directory.<\/td>\n<\/tr>\n<tr>\n<td>$Line$<\/td>\n<td>Current line number in the active file.<\/td>\n<\/tr>\n<tr>\n<td>$Col$<\/td>\n<td>Current column in the active file.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You can also prompt for one parameter value and create a custom menu specific to a directory. I&#8217;ll show you how below, but keep these features in mind as you dream up your custom tools.<\/p>\n<h1>How to create a custom tool<\/h1>\n<p>To create a custom tool, start with a text file named CustomMenu.inf. Place the file in the ProgramData directory for PowerShell Studio or PrimalScript.<\/p>\n<p>For example:<\/p>\n<p>..\\ProgramData\\SAPIEN\\PowerShell Studio 2016<br \/>\n..\\ProgramData\\SAPIEN\\PrimalScript 2016<\/p>\n<p>To make this simpler, I have a script, <a href=\"https:\/\/gist.github.com\/juneb\/43cf2e566e4c8003d6e19e48821b48eb\">New-CustomMenu.ps1<\/a> that creates and opens the CustomMenu.inf menu for PowerShell Studio or PrimalScript.<\/p>\n<p>IMPORTANT:<br \/>\nTo make changes to the CustomMenu.inf file effective, restart PowerShell Studio or PrimalScript.<\/p>\n<h1>Custom Tool Syntax<\/h1>\n<p>The syntax of the file content is:<\/p>\n<pre class=\"PowerShell\">[Menu]\r\n1=Command Name 1;command line 1\r\n2=Command Name 2;command line 2\r\n[Application]\r\n1=Command Name 1;command line 1\r\n2=Command Name 2;command line 2<\/pre>\n<p>You can add additional numbered command lines. The numbers indicate a command line. They do not determine the order of commands in the file. If the file contains multiple command lines with the same number, only the first one with each number is effective.<\/p>\n<p><b>Examples:<\/b><\/p>\n<p>For each command, enter the command name, a semi-colon (;), and the command.<\/p>\n<p>For example, this line creates a &#8216;Run Get-Acl&#8217; command that run the Get-Acl cmdlet on the current file ($File$), then formats all properties of the output in a list.<\/p>\n<pre class=\"PowerShell\">1=Run Get-Acl;powershell Get-Acl -Path $File$ | Format-List -Property *<\/pre>\n<p>Generates this menu item:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image006.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image006\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image006_thumb.jpg\" alt=\"clip_image006\" width=\"216\" height=\"65\" border=\"0\" \/><\/a><\/p>\n<p>When you open a file and run it:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image008.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image008\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image008_thumb.jpg\" alt=\"clip_image008\" width=\"555\" height=\"174\" border=\"0\" \/><\/a><\/p>\n<p>This line copies the current file to a Scripts directory on OneDrive.<\/p>\n<pre class=\"PowerShell\">2=Copy to OneDrive;xcopy $File$ %UserProfile%\\OneDrive\\Scripts\\*<\/pre>\n<p>It generates this menu item:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image009.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image009\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image009_thumb.png\" alt=\"clip_image009\" width=\"194\" height=\"78\" border=\"0\" \/><\/a><\/p>\n<p>When you run it, it returns this result:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image011.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image011\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image011_thumb.jpg\" alt=\"clip_image011\" width=\"396\" height=\"143\" border=\"0\" \/><\/a><\/p>\n<h1>Sections in a CustomMenu.inf file<\/h1>\n<p>There are two sections in the file:<\/p>\n<ul>\n<li>In the <b>[Menu]<\/b> section, add commands that run and exit, like a PowerShell cmdlet. The custom menu waits for the command to complete.<\/li>\n<li>In the <b>[Application]<\/b> section, add commands that don&#8217;t exit, like a command that displays a file or UI that you might want to keep open. The custom menu runs these commands and exits without waiting for them to complete.<\/li>\n<\/ul>\n<p>For example, I have a command in the [Application] section that opens the current CustomMenu.inf file in Notepad.<\/p>\n<pre class=\"PowerShell\">[Application]\r\n1=Open CustomMenu.inf;Notepad 'C:\\ProgramData\\SAPIEN\\PowerShell Studio 2016\\CustomMenu.inf'<\/pre>\n<h1>Additional Syntax in a CustomMenu.inf File<\/h1>\n<p>You can use these features in any CustomMenu.inf file.<\/p>\n<ul>\n<li><b>Horizontal line. <\/b>To add a horizontal line separator to the file, enter a single dash or hyphen on a line. For example:\n<pre class=\"PowerShell\">3=-<\/pre>\n<\/li>\n<li><b>Comment.<\/b> To add a comment or comment-out a line, use a semicolon (;). All text to the right of &#8216;;&#8217; on that line is ignored. For example:\n<pre class=\"PowerShell\">; Ignore this<\/pre>\n<\/li>\n<li>Prompt for input. To prompt for input, use <b>{prompt}<\/b>.For example, this &#8216;Copy to location&#8217; command runs the Copy-Item cmdlet on the current file. It prompts the user for the destination path. The default message says &#8220;Enter value&#8221;.\n<pre class=\"PowerShell\">3=Copy to location;powershell Copy-Item $File$ -Destination {prompt}<\/pre>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image013.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image013\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image013_thumb.jpg\" alt=\"clip_image013\" width=\"184\" height=\"105\" border=\"0\" \/><\/a><\/li>\n<li>To include a message with the prompt, use <b>{prompt| <\/b><i>message <\/i><b>}<\/b>For example:\n<pre class=\"PowerShell\">3=Copy to location;powershell Copy-Item $File$ -Destination {prompt|-Destination}<\/pre>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image015.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image015\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image015_thumb.jpg\" alt=\"clip_image015\" width=\"177\" height=\"106\" border=\"0\" \/><\/a><\/li>\n<li>To set a default value, use {prompt|<i>message<\/i>|<i>defaultValue<\/i>}For example:\n<pre class=\"PowerShell\">3=Copy to location;powershell Copy-Item $File$ -Destination {prompt|-Destination|$home\\Dropbox\\Scripts}<\/pre>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image017.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image017\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image017_thumb.jpg\" alt=\"clip_image017\" width=\"172\" height=\"91\" border=\"0\" \/><\/a><\/li>\n<\/ul>\n<h1>Folder-Specific Custom Tools<\/h1>\n<p>To create custom tools that appear only when the current file is stored in a particular directory, place a CustomMenu.inf file in the specified directory.<\/p>\n<p>For example, I have GitHub custom commands that appear in my CustomMenu.inf only when I&#8217;m in one of my C:\\GitHub subdirectories.<\/p>\n<p>Here&#8217;s my default custom menu.<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image019.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image019\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image019_thumb.jpg\" alt=\"clip_image019\" width=\"184\" height=\"225\" border=\"0\" \/><\/a><\/p>\n<p>Here&#8217;s the CustomMenu.inf file in my GitHub clone directory. To prevent this file from being included in my repo, I create a <a href=\"https:\/\/wp.me\/p3tXTf-37v\" target=\"_new\">gitignore text file<\/a> and list CustomMenu.inf in that file, along with .TempPoint files.<\/p>\n<pre class=\"PowerShell\">[Menu]\r\n1=GIT - Add To Staging;\"C:\\Program Files\\Git\\bin\\Git.exe\" add \"$file$\"\r\n2=GIT - Commit To Local Repo;\"C:\\Program Files\\Git\\bin\\Git.exe\" commit $fileName$ -m \"{Prompt|Enter comment|Commit from PowerShell Studio $Date$ $Time$}\"\r\n3=GIT - Commit All To Local Repo;\"C:\\Program Files\\Git\\bin\\Git.exe\" commit -a -m \"{Prompt|Enter comment|Commit from PowerShell Studio $Date$ $Time$}\"\r\n4=-\r\n5=GIT - Status;\"C:\\Program Files\\Git\\bin\\Git.exe\" status\r\n6=-\r\n7=GIT - Push Files To Remote Repo;\"C:\\Program Files\\Git\\bin\\Git.exe\" push Remote\r\n8=GIT - Fetch From Remote Repo;\"C:\\Program Files\\Git\\bin\\Git.exe\" fetch Remote\r\n9=GIT - Pull From Remote Repo;\"C:\\Program Files\\Git\\bin\\Git.exe\" pull Remote master\r\n<\/pre>\n<p>When I open a file in one of my GitHub clones on disk, my custom menu changes to:<\/p>\n<p><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image021.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image021\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2016\/05\/clip_image021_thumb.jpg\" alt=\"clip_image021\" width=\"197\" height=\"352\" border=\"0\" \/><\/a><\/p>\n<p>These are just the basics of custom menus. The benefits are limited only by our creativity.<\/p>\n<p>For more information about custom tools and menus, see:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.sapien.com\/blog\/2015\/10\/01\/powershell-studio-2015-new-custom-menu-features-git-template\/\" target=\"_new\">New Custom-Menu features: Git template<\/a><\/li>\n<li><a href=\"https:\/\/www.sapien.com\/blog\/2013\/01\/08\/powershell-studio-2012-with-git-subversion-and-mercurial-oh-my\/\" target=\"_new\">Git, Subversion, and Mercurial &#8212; Oh, my!<\/a><\/li>\n<\/ul>\n<p><em>June Blender is a technology evangelist at SAPIEN Technologies, Inc. and a Windows PowerShell MVP. You can reach her at <\/em><a href=\"mailto:juneb@sapien.com\"><em>juneb@sapien.com <\/em><\/a><em>or follow her on Twitter at <\/em><a href=\"https:\/\/www.twitter.com\/juneb_get_help\"><em>@juneb_get_help<\/em><\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are so many features in PowerShell Studio and PrimalScript that I think I can&#8217;t live without, like the Format Script button, file groups, and conditional breakpoints. But, there are few features I&#8217;d love to have that aren&#8217;t there. They&#8217;re easy enough to add, but they&#8217;re really personal to me. Fortunately, I can add them [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[932,283,703,410],"tags":[1110,1031,1109,1111,934],"class_list":["post-12037","post","type-post","status-publish","format-standard","hentry","category-beginners","category-howto","category-powershell-studio","category-primalscript-software-news","tag-add-to-menu","tag-custom-menu","tag-custom-tools","tag-gitignore","tag-juneb"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12037","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=12037"}],"version-history":[{"count":15,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12037\/revisions"}],"predecessor-version":[{"id":12148,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12037\/revisions\/12148"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=12037"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=12037"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=12037"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}