Is it possible to add a keyboard shortcut to Powershell? - powershell

I've switched to Powershell after a couple of decades of bash, and after some configuring of my profile (and adding PSCX, openssl and a few other tools) I'm generally happy.
One thing I miss from bash:
mkdir some-very-long-dir-name
cd (hit ESC then hit _ on the keyboard)
Escape underscore is bash for 'last item on the previous command'. It's super useful - in this chase I didn't have to type out the very long directory name.
Is it possible to add keyboard shortcuts to powershell? How?
I'm using ConEmu as my terminal if that matters.

Short answer:
Set-PSReadlineKeyHandler -Key 'Escape,_' -Function YankLastArg
Longer explanation:
Thanks to #davidbrabant and #TheIncorrigible1 for pointing to PSReadLine: it's not the answer itself, but understanding how PSReadLine works is the key to solving this.
Although vi is the default editor on every Linux distribution, bash's default is emacs editing mode. From the bash docs:
In order to switch interactively between emacs and vi editing modes, use the ‘set -o emacs’ and ‘set -o vi’ commands (see The Set Builtin). The Readline default is emacs mode.
Which means 'escape underscore' comes from emacs.
Oddly, PSReadLine, unlike bash, does't use emacs mode by default. From the PSREADLine docs:
To use Emacs key bindings, you can use:
Set-PSReadlineOption -EditMode Emacs
It's not very explicit, but that means another mode is default. Confirming that, running:
get-PSReadlineOption
Returns:
EditMode : Vi
So there are two solutions:
Solution 1: change mode
Set-PSReadlineOption -EditMode Emacs
You can see the effect with Get-PSReadlineKeyHandler includes the standard escape underscore shortcut:
Escape,_ YankLastArg Copy the text of the last argument to the input
Escape underscore now works.
Solution 2: add the shortcut to your existing mode
Instead of changing mode (it turns out I like vi keybindings!), you can also run:
Set-PSReadlineKeyHandler -Key 'Escape,_' -Function YankLastArg
To add it to your existing mode.

An alternative to your ESC+_ solution, the PowerShell automatic variable $$ contains the same information without the need for PSReadLine (pre-v5.0 or without the module installed).
PS C:\> Get-ChildItem -Path 'C:\'
...
PS C:\> $$
C:\
You can also capture the command used with the $^ variable:
PS C:\> $^
get-childitem

Related

How do you edit the command line in an external editor?

tl;dr
I want to find a Powershell version of the bash edit-and-execute-command widget or the zsh edit-command-line widget.
Background
Short commands get executed directly on the command-line, long complicated commands get executed from scripts. However, before they become "long", it helps to be able to test medium length commands on the command-line. To assist in this effort, editing the command in an external editor becomes very helpful. AFAIK Powershell does not support this natively as e.g. bash and zsh do.
My current attempt
I am new to Powershell, so I'm bound to make many mistakes, but I have come up with a working solution using the features of the [Microsoft.Powershell.PSConsoleReadLine] class. I am able to copy the current command-line to a file, edit the file, and then re-inject the edited version back into the command-line:
Set-PSReadLineKeyHandler -Chord "Alt+e" -ScriptBlock {
$CurrentInput = $null
# Copy current command-line input, save it to a file and clear it
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $CurrentInput, [ref] $null)
Set-Content -Path "C:\Temp\ps_${PID}.txt" -Value "$CurrentInput"
[Microsoft.PowerShell.PSConsoleReadLine]::KillRegion()
# Edit the command with gvim
Start-Job -Name EditCMD -ScriptBlock { gvim "C:\Temp\ps_${Using:PID}.txt" }
Wait-Job -Name EditCMD
# Get command back from file the temporary file and insert it into the command-line
$NewInput = (Get-Content -Path "C:\Temp\ps_${PID}.txt") -join "`n"
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($NewInput)
}
Questions
My current solution feels clunky and a somewhat fragile.
Are there other solutions? Can the current solution be improved?
Environment
OS Windows 10.0.19043.0
Powershell version 5.1.19041.1320
PSReadLine version 2.0.0
The solution I went with
Create a "baked" executable similar to what mklement0 showed. I prefer vim for this instead of `gvim, as it runs directly in the console:
'#vim -f %*' > psvim.cmd
$env:EDITOR = "psvim"
Set-PSReadLineKeyHandler -Chord "Alt+e" -Function ViEditVisually
tl;dr
PSReadLine comes with the feature you're looking for, namely the ViEditVisually function, and on Unix-like platforms it even has a default key binding.
For the feature to work, you need to set $env:VISUAL or $env:EDITOR to the name / path of your editor executable.
As of PSReadLine v2.1, if you also need to include options for your editor - such as -f for gvim - you need to create a helper executable that has the options "baked in".
Since creating a helper executable is cumbersome, a custom emulation of the feature, as you have attempted and as refined in zett42's helpful answer, may be the simpler solution for now. zett42's answer additionally links to a Gist that improves the original functionality by preserving cursor positions.
GitHub issue #3214 suggests adding support for recognizing executables plus their options in these environment variables.
Details below.
The PSReadLine module ships with such a feature, namely the ViEditVisually function.
Its default key bindings, if any, depend on PSReadLine's edit mode, which you can set with Set-PSReadLineOption -EditMode <mode>:
Windows mode (default on Windows): not bound
Emacs mode (default on macOS and Linux): Ctrl-xCtrl-e
Vi mode: v in command mode (press Esc to enter it)
Use Set-PSReadLineKeyHandler to establish a custom key binding, analogous to the approach in the question; e.g., to bind Alt-e:
Set-PSReadLineKeyHandler -Chord Alt+e -Function ViEditVisually
For the function to work, you must define the editor executable to use, via either of the following environment variables, in order of precedence: $env:VISUAL or $env:EDITOR; if no (valid) editor is defined, a warning beep is emitted and no action is taken when the function is invoked.
E.g., to use the nano editor on macOS: $env:VISUAL = 'nano'
The value must refer to an executable file - either by full path or, more typically, by name only, in which case it must be located in a directory listed in $env:PATH
Note: .ps1 scripts do not qualify as executable files, but batch files on Windows and shebang-line-based shell scripts on Unix-like platforms do.
As of PSReadLine 2.1, including options for the executable - such as --newindow --wait for code (Visual Studio Code) is not supported.
Therefore, for now, if your editor of choice requires options, you need to create a helper executable that has these options "baked in"; see examples below.
GitHub issue #3214 proposed adding support for allowing to specify the editor executable plus options as the environment-variable value, which is something that Git (which recognizes the same variables) already supports; for instance, you could then define:
$env:VISUAL = 'code --new-window --wait'
Example configuration with a helper executable for code (Visual Studio Code):
Create a helper executable in the user's home directory in this example:
On Windows:
'#code --new-window --wait %*' > "$HOME\codewait.cmd"
On Unix-like platforms:
"#!/bin/sh`ncode --new-window --wait `"$#`"" > "$HOME/codewait"; chmod a+x "$HOME/codewait"
Add a definition of $env:VISUAL pointing to the helper executable to your $PROFILE file, along with defining a custom key binding, if desired:
$env:VISUAL = "$HOME/codewait"
# Custom key binding
Set-PSReadLineKeyHandler -Chord Alt+e -Function ViEditVisually
This code has some issues:
Temp path is hardcoded, it should use $env:temp or better yet [IO.Path]::GetTempPath() (for cross-platform compatibility).
After editing the line, it doesn't replace the whole line, only the text to the left of the cursor. As noted by mklement0, we can simply replace the existing buffer instead of erasing it, which fixes the problem.
When using the right parameters for the editor, it is not required to create a job to wait for it. For VSCode this is --wait (-w) and for gvim this is --nofork (-f), which prevents these processes to detach from the console process so the PowerShell code waits until the user has closed the editor.
The temporary file is not deleted after closing the editor.
Here is my attempt at fixing the code. I don't use gvim, so I tested it with VSCode code.exe. The code below contains a commented line for gvim too (confirmed working by the OP).
Set-PSReadLineKeyHandler -Chord "Alt+e" -ScriptBlock {
$CurrentInput = $null
# Copy current console line
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $CurrentInput, [ref] $null)
# Save current console line to temp file
$tempFilePath = Join-Path ([IO.Path]::GetTempPath()) "ps_$PID.ps1"
Set-Content $tempFilePath -Value $CurrentInput -Encoding utf8
# Edit the console line using VSCode
code --new-window --wait $tempFilePath
# Uncomment for using gvim editor instead
# gvim -f $tempFilePath
# The console doesn't like the CR character, so rejoin lines using LF only.
$editedInput = ((Get-Content -LiteralPath $tempFilePath) -join "`n").Trim()
# Replace current console line with the content of the temp file
[Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $currentInput.Length, $editedInput)
Remove-Item $tempFilePath
}
Update:
This GitHub Gist includes an updated version of the code. New features including saving/restoring the cursor position, passing the cursor position to VSCode and showing a message while the console is blocked.
Notes:
A default installation of VSCode adds the directory of the VSCode binaries to $env:PATH, which enables us to write just code to launch the editor.
While UTF-8 is the default encoding for cmdlets like Set-Content on PowerShell Core, for Windows PowerShell the parameter -Encoding utf8 is required to correctly save commands that contain Unicode characters. For Get-Content specifying the encoding isn't necessary, because Windows PowerShell adds a BOM which Get-Content detects and PowerShell Core defaults to UTF-8 again.
To have Alt+E always available when you open a console, just add this code to your $profile file. Makes quick testing and editing of small code samples a breeze.
VSCode settings - for most streamlined experience, enable "Auto Save: onWindowChange". Allows you to close the editor and save the file (update the console line) with a single press to Ctrl+W.

How to clear the entire terminal (PowerShell)

I had an issue. Using the clear or cls command in powershell clears only the visible portion of the terminal,I would like to know how to clear the entire terminal?
I use VSCode by the way.
To also clear the scrollback buffer, not just the visible portion of the terminal in Visual Studio Code's integrated terminal, use one of the following methods:
Use the command palette:
Press Ctrl+Shift+P and type tclear to match the Terminal: Clear command and press Enter
Use the integrated terminal's context menu:
Right-click in the terminal and select Clear from the context menu.
On Windows, you may have to enable the integrated terminal's context menu first, given that by default right-clicking pastes text from the clipboard:
Open the settings (Ctrl+,) and change setting terminal.integrated.rightClickBehavior to either default or selectWord (the latter selects the word under the cursor before showing the context menu).
Use a keyboard shortcut from inside the integrated terminal (current as of v1.71 of VSCode):
On macOS, a shortcut exists by default: Cmd+K
On Linux and Windows, you can define an analogous custom key binding, Ctrl+K, as follows, by directly editing file keybindings.json (command Preferences: Open Keyboard Shortcuts (JSON) from the command palette), and placing the following object inside the existing array ([ ... ]):
{
"key": "ctrl+k",
"command": "workbench.action.terminal.clear",
"when": "terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported"
}
Using a command you can invoke from a shell in the integrated terminal:
Note: A truly cross-platform solution would require executing the VSCode-internal workbench.action.terminal.clear command from a shell, but I don't know how to do that / if it is possible at all - do tell us if you know.
Linux (at least as observed on Ubuntu):
Use the standard clear utility (/usr/bin/clear), which also clears the scrollback buffer.
From PowerShell, you may also use Clear-Host or its built-in alias, cls.
By contrast, [Console]::Clear() does NOT clear the scrollback buffer and clear just one screenful.
macOS:
Unfortunately, neither /usr/bin/clear nor PowerShell's Clear-Host (cls) nor .NET's [Console]::Clear() clear the scrollback buffer - they all clear just one screenful.
Print the following ANSI control sequence: '\e[2J\e[3J\e[H' (\e represents the ESC char. (0x1b, 27); e.g., from bash: printf '\e[2J\e[3J\e[H'; from PowerShell: "`e[2J`e[3J`e[H"
You can easily wrap this call in a shell script for use from any shell: create a file named, say, cclear, in a directory listed in your system's PATH variable, then make it executable with chmod a+x; then save the following content to it:
#!/bin/bash
# Clears the terminal screen *and the scrollback buffer*.
# (Needed only on macOS, where /usr/bin/clear doesn't do the latter.)
printf '\e[2J\e[3J\e[H'
Windows:
NO solution that I'm aware of: cmd.exe's internal cls command and PowerShell's internal Clear-Host command clear only one screenful in the integrated terminal (not also the scrollback buffer - even though they also do the latter in a regular console window and in Windows Terminal).
Unfortunately, the escape sequence that works on macOS ("`e[2J`e[3J`e[H" or, for Windows PowerShell, "$([char]27)[2J$([char]27)[3J$([char]27)[H") is not effective: on Windows it just clears one screenful.
(By contrast, all of these methods do also clear the scrollback buffer in regular console windows and Windows Terminal.)
right click on the powershell button,
then select clear,
when you are at the command window, type "clear" command, to clear the terminal window.

Redirecting STDERR and STDOUT in a DOSKEY macro

I am trying to define a DOSKEY macro that redirects both STDOUT and STDERR output to a file. The doskey will be set by running a batch file. I can do this for STDOUT only with the following:
doskey logged_build=build $g build.log
However, I cannot use the typical 2>&1 option (as below) to also redirect the STDERR output to the same file.
doskey logged_build=build $g build.log 2>&1
I have also tried
doskey logged_build=build $g build.log 2$g&1
which gives a syntax error and
doskey logged_build=build $g build.log 2$g build.log
which gives an error that the file cannot be accessed because it is being used by another process.
I am sure this is just a matter using the right macro wildcard (like using $g instead of >), but I have done loads of googling and have not yet been able to find anything. So I pose the question to you my fellow SOFers.
You can't do this directly at the command line, but you can do it using a doskey macrofile. Macrofiles don't even need to use confusing magic like $g; they're not part of the shell, so shell special characters can be used normally, and get included in the definition of the macro instead of being interpreted by the shell before the macro gets defined.
Create a file wherever you like (e.g. %USERPROFILE%\mymacros.txt), and put the following line in it:
logged_build=build >build.log 2>&1
Then load the macros by running:
doskey /MACROFILE=%USERPROFILE%\mymacros.txt
You can put many macros in the file to load them all at once too; this makes it easy to customize your command prompt in general too; you can either modify the existing Command Prompt shortcut or create a new shortcut based on cmd.exe to make the Target:
%windir%\system32\cmd.exe /K doskey /MACROFILE=%USERPROFILE%\mymacros.txt
and clicking the shortcut will create a command prompt with all of the macros pre-loaded. The /K option to cmd.exe runs the subsequent command in the shell before giving the user an interactive prompt. Saves a lot of hassle if your prompts define all your macros automatically without having to set them up each time.
Alternatively, to avoid needing to modify individual shortcuts, you can set a registry key that will load the macros no matter what, even if cmd.exe is invoked directly, without going through a modified shortcut. Just run:
reg add "HKCU\Software\Microsoft\Command Processor" /v AutoRun /t REG_SZ /d "doskey /MACROFILE=%USERPROFILE%\mymacros.txt"
You can change HKCU to HKLM to make it apply globally for all users, not just yourself, though in that case you'd want to put the macro file in a common location, not your user profile. Annoyingly, you can't use a REG_EXPAND_SZ for cases like this (which would allow you to use variables like %USERPROFILE% to set a global HKLM setting to files relative to each user's profile directory, or handle the case of a profile being relocated), but it works well enough.
I too have trolled the web for a solution with no luck. The best I could come up requires adding the 2>&1 to the invocation of your macro:
doskey logged_build=build $* $g build.log
Then invoke it as such:
logged_build 2>&1

Use CTRL + D to exit and CTRL + L to cls in Powershell console

I am trying to make
CTRL + D - exit Powershell console
and
CTRL + L - clear the screen
like in bash.
So far, I have seen that we can define
function ^D {exit}
but that means I have to do CTRL+D and then hit enter for it to work.
Also, it doesn't even let me define
function ^L {exit}
Is there anyway to add these key bindings in the default Powershell console?
Old question, but with PowerShell 5.1 and PowerShell Core 6.x and later:
Set-PSReadlineKeyHandler -Key ctrl+d -Function ViExit
There is a new library PSReadline for Powershell v3.0 that emulates the GNU Bash tab completion and key bindings. Even CTRL + R for reverse incremental search works. Exactly what I wanted.
If you don't mind relying on an external program, you could do the following with AutoHotKey:
#IfWinActive ahk_class ConsoleWindowClass
^L::SendInput , {Esc}cls{Enter}
^D::SendInput , {Esc}exit{Enter}
#IfWinActive
The above will work with the PowerShell or CMD console. Otherwise the only thing I can think of would be to work up some P/Invoke magic with SetWindowsHookEx.
Edit: Fixed AutoHotkey script to pass through the shortcut keys to other programs.
The keybindings are controlled by PSReadLine. PSReadLine's default edit mode is Windows style, where Ctrl-D is unbound.
Set your edit mode to Emacs
Set-PSReadlineOption -EditMode Emacs
or bound the key
Set-PSReadLineKeyHandler -Key 'Ctrl+d' -Function DeleteCharOrExit
There is also a PowerShell snapin called PSEventing which will allow you to do this (see the demo on the front page:
http://pseventing.codeplex.com/releases/view/66587
# clear screen in response to ctrl+L, unix style
register-hotkeyevent "ctrl+L" -action { cls; write-host -nonewline (prompt) }
You can set your PSReadline to emacs mode, it will not only exit with ^D, you will be able to go to beginning of line with ^A, end of the line with ^E
Include this in your profile:
Set-PSReadlineOption -EditMode Emacs
I'm using cmder which uses ConEmu, find profile.ps1 with <appdir>/vendor/ for that case and you can add into that file.
Otherwise you can add to default locations where powershell loads it. One of tutorials HERE.

How do I make Perl scripts recognize command-line parameters in the Win32 cmd console?

When I invoke my Perl scripts in the Windows environment without invoking perl first, the parameters are not passed to my script.
For example,
C:\> C:\my-perl-scripts\foo.pl bar
invokes foo.pl but doesn't recognize bar as a parameter (#ARGV is empty). However,
C:\> perl C:\my-perl-scripts\foo.pl bar
works as expected.
Is this a configuration issue?
Ideally, I'd like to be able to distribute some perl scripts, have the user add C:\my-perl-scripts\ to the path and then just be able to invoke foo.pl from anywhere while running cmd.
If they have to specify perl first, then they'll always have to give a complete path.
Any ideas or recommendations?
Edit: To show that the assoc and ftype are correct on my system, I executed the following commands.
C:\>assoc .pl
.pl=Perl
C:\>ftype Perl
Perl="C:\Perl\bin\perl.exe" "%1" %*
C:\>more t.pl
print "'$_'\n" for #ARGV;
C:\>t a b
C:\>perl t.pl a b
'a'
'b'
C:\>t.pl a b
C:\>
I included both the output of t and t.pl to show it's not a %PATHEXT% problem. Both outputted nothing as originally described whereas invoking perl first gave the expected response.
I'm not sure where to look next, but thanks for the suggestions so far. They have been very helpful.
Edit 2: The problem appears to be on my vista business box. On my xp pro box, it works as expected. Both have ActivePerl 5.8.9. I have another vista home box that I have not yet tried yet. I'll post back if I discover anything.
Edit 3: I found the answer (posted below). I found it by running a registry cleaner, removing perl, running the registry cleaner again. On 2nd cleaning, only one invalid entry remained - the one that was causing the problem (probably left over from a previous installation).
I found out what the problem was. Although the ftype and the assoc values were set as suggested, the actual behavior on my system seems to be determined by the registry key
HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command
It should have a (Default) string value of "C:\Perl\bin\perl.exe" "%1" %*
When I found this entry, it was set to "C:\Perl\bin\perl.exe" "%1". Changing it immediately fixed the problem.
Why it was set that way in the first place? I don't know. Maybe from a previous installation?
Anyway, thanks for the suggestions, and I hope this answer helps someone else, too.
Hmmm... sounds like the file association for *.pl is messed up somehow. I'm not on a Windows box, so I can't test this. You can check the file association stuff with either the ASSOC or FTYPE command on the command-line. IIRC, "ASSOC .pl" should tell you what the file type is and "FTYPE filetype command" tells the shell what to do with a Perl script. Try something like:
C:\> ASSOC .pl=perlscript
C:\> FTYPE perlscript=C:\Perl\bin\perl.exe %1 %*
From the looks of one of the command references that should do the trick. My guess is that the current association is not passing the parameters along to the script. You should be able to check that by using ASSOC .pl to figure out what the name of the file association is and then using FTYPE to print out the command that the shell is going to execute.
Update
I found an interesting thing that I want to note for posterity. I started seeing exactly this problem on a friends machine at work with respect to some Python scripts. ASSOC and FTYPE resulted in the expected output but the parameters were still not being passed along - exactly what was originally reported.
After a little digging, I found that the registry settings were created somewhere along the line as REG_SZ values. I deleted them and re-created them using ASSOC and FTYPE and everything started working... looking at the registry gave me the answer the new values were created as REG_EXPAND_SZ! These worked exactly as expected.
Update: Given that the following is correct, the only thing left to make sure is that command extensions are not turned off. Try:
cmd /e:on
on the command line before you run your tests. See also Windows XP cmd documentation:
Enabling and disabling command extensions
Command extensions are enabled by default in Windows XP. You can disable them for a particular process by using /e:off. You can enable or disable extensions for all cmd command-line options on a computer or user session by setting the following REG_DWORD values:
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\EnableExtensions\REG_DWORD
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\EnableExtensions\REG_DWORD
Set the REG_DWORD value to either 0x1 (that is, enabled) or 0x0 (that is, disabled) in the registry by using Regedit.exe. User-specified settings take precedence over computer settings, and command-line options take precedence over registry settings.
E:\Temp> assoc .pl
.pl=Perl
E:\Temp> ftype Perl
Perl="C:\opt\Perl\bin\perl.exe" "%1" %*
E:\Temp> #echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.PL;.PLX;.WPL;.py;.pyw
E:\Temp> cat t.pl
print "'$_'\n" for #ARGV;
E:\Temp> t a b c d e f g h j
'a'
'b'
'c'
'd'
'e'
'f'
'g'
'h'
'j'
I have used pretty much every ActiveState Perl distribution since 2004. These settings are enough to make it work.
To sum up.
ftype is old and cmd.exe doesn't care whatever it says.
The real deal is the HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command thing.
Just run: reg add HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command /ve /d "C:\strawberry\perl\bin\perl.exe \"%1\" %*" /f
and everything will be ok. (* given that "C:\strawberry\perl\bin\perl.exe" is the exact path to your perl installation.*)
/ve is meant to work on de “(Default)” REG_SZ value
/d is to assign “data” to the “value”
/f to force substitution (or overwriting) of the preexisting value
In fact, if assoc .pl=Whatever and ftype Whatever doesn't exist (never assigning a value to it, or doing ftype Whatever= to unassign), the scripts could still be invoked without prepending perl.exe.
So, if using Windows >= 6.0 (Vista, 2008, 7, etc.) just forget that the commands assoc and ftype exist at all. Don't bother. Go reg.exe!
I tried updating and associating .pl with the many different PERL entries in the registry that others have tried (.pl, Perl, PerlScript, pl_auto_file, Applications\perl.exe) and none of these worked. I'm running AS Perl 5.14.2 on Windows 7. I then noted that there was an entry for \Applications\perl5.14.2.exe in the registry and it was set to:
"C:\Perl\bin\perl5.14.2.exe" "%1"
Added the %* to this and then I was able to see data in #ARGV.
I also noted that on some of these entries I had a command path entry of "C"\Perl64\..." from a previous 64 bit PERL that I'd installed earlier and uninstalled when I found out that 64 bit PERL isn't as nice with IIS 7 as 32 bit PERL is. So there are dangling installation remnants that are probably affecting things too.
So the answer here is probably not a short one and is in simple words... "It depends..." (on your system and installation).
After fixing file association problem could not pass parameters. A user I support mistakenly associated .pl file extension with notepad after trying to run script from (Windows 7 Professional) command line for first time. Tried all the file association tricks and environment variable fixes to no avail. Uninstalled and reinstalled and tried 32 bit and 64 bit installations. Issue was only present on users profile.
Finally went into the registry and simply deleted the key from
HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command
and added back via
reg add HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command /ve /d "C:\strawberry\perl\bin\perl.exe \"%1\" %*" /f
started passing parameters again Thanks "lucretius"
I found this additional location in the registry that had to be updated before it would work for me. Note: The name after HKEY_USERS may be different on your machine.
Add %* to default string:
HKEY_USERS\S-1-5-21-1399284159-2775065347-350672949-4058_Classes\pl_auto_file\shell\open\command
"D:\Perl\bin\perl.exe" "%1" %*
Original author answer works. Here's a complete registry file for manually installing PERL on Windows, just add to PATH environment variable: ";C:\PERL\bin;" and make a perl.reg file with notepad containing this:
Windows Registry Editor Version 5.00
[-HKEY_CLASSES_ROOT\.pl]
[HKEY_CLASSES_ROOT\.pl]
#="Perl"
"PerceivedType"="text"
[HKEY_CLASSES_ROOT\.pl\Perl]
[HKEY_CLASSES_ROOT\.pl\Perl\ShellNew]
[HKEY_CLASSES_ROOT\.pl\PersistentHandler]
#="{5e941d80-bf96-11cd-b579-08002b30bfeb}"
[HKEY_CLASSES_ROOT\Applications\perl.exe]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_CLASSES_ROOT\Perl]
[HKEY_CLASSES_ROOT\Perl\shell]
[HKEY_CLASSES_ROOT\Perl\shell\Open]
[HKEY_CLASSES_ROOT\Perl\shell\Open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_CLASSES_ROOT\pl_auto_file]
#=""
[HKEY_CLASSES_ROOT\pl_auto_file\shell]
[HKEY_CLASSES_ROOT\pl_auto_file\shell\open]
[HKEY_CLASSES_ROOT\pl_auto_file\shell\open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell\open]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell\open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl\OpenWithList]
"a"="perl.exe"
"MRUList"="ab"
"b"="NOTEPAD.EXE"
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl\OpenWithProgids]
"pl_auto_file"=hex(0):
"Perl"=hex(0):
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell\Open]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell\Open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file]
#=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell\open]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell\open\command]
#="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_LOCAL_MACHINE\SOFTWARE\Perl]
#="C:\\PERL\\"
"BinDir"="C:\\Perl\\bin\\perl.exe"
I installed Perl 5.24.3 on Windows2016 and found the JAMS scheduler Agent Shell ignored the .pl extension as if it did not exist. All good from DOS desktop.
The same config on Winows2008 worked fine.
The registry entries created by that ActiveState Perl Install, matched Lucretius Post above, but do not apply globally to all users. Not the default system user for example.
Logging in as the user the Shell will run as, and making the association helped.
Ideally there would be a registry twig to make .pl assoc global ?