#!
Support for WindowsA tool to support *nix-like #!
functionality in Windows. This way, a file’s content determines the interpreter used, rather than its extension. In particular, it properly passes command-line arguments passed to your script & can be used with standard I/O |
pipelines.
It’s just a batch script that determines & invokes the target interpreter.
The other important detail is properly passing arguments from the command-line. That %*
does some heavy lifting, yo. Unfortunately, it’s often overlooked. Worse, the Windows shell environment specifically removes it in some cases. Rude! Basically this puts it back.
It can be used explicitly to process a script
%a% %b% %c% wshbang.bat my_script.py
but more importantly allows direct calls
%a% %b% %c% my_script.py
Doing so still relies on Windows’s standard filetype/extension associations, but it turns out that is more involved than one might expect…
Recent versions of Windows restrict how associations are set; older versions allow for programatic access – allowing 🪟❗ to do so itself.
The easiest way to handle this is probably via the usual right-click → Open with >
menu, then associating wshbang.bat
as the default by checking the “Always use…” box. Alternatively, the Default apps settings page can be used.
See the note below about arguments & first-time runs!
Earlier versions of Windows can use the ftype
& assoc
internal commands to set associations from an elevated command prompt. wshbang can handle this for you automatically with the use of the -a
argument. This will attempt to spawn a seperate, elevated prompt to do so – including a potential UAC confirmation.
Notably, elevation involves a round-trip through Powershell back into cmd.exe. Have a look if you want a janky sudo
mimic.
Well first of all, now you can just use a Windows path right in the file, if you don’t care about interoperability. It just runs that if a file is found there.
Really though chances are your script points to an interpreter via a Unix-style path. If you’re slick and use env
to path-search, 🪟❗ will do the same. You don’t even need to add .exe
or whatever. %PATH%
& %PATHEXT%
sexiness! Otherwise it prompts you to give it a path to your executable-of-choice; From then on it maps that *nix path to your interpreter. Note the use of con
in the prompt code forces this to be interactive – this is deliberate to avoid devouring any standard input.
Run it again.
This is a known limitation imposed by the Windows shell environment. Setting a file association will remove the %*
from the command responsible for passing arguments. 🪟❗ adds it back every time it is run, but the unfortunate truth is the arguments have already been dropped by then. This can be confirmed, for example, by adding
echo %cmdcmdline%
somewhere in the script. The good news is because the script corrects this each time it runs, subsequent runs should work until you do something that drops the %*
again, like using the “Open with…” prompt again. If need be to avoid running even once without arguments, first set the association via the settings, then invoke wshbang.bat
once before running your script for realsies:
> nul
wshbang.bat %a% %b% %c% this_time_for_realsies.py
binfmt_misc
-type kernel solution but that ain’t happening. Beyond that I figured a script is just transparent – don’t trust me, you see what you’re running before you do. At that point Batch is just the only “universal” option; I don’t know what people have going on with Windows Scripting Host, & Powershell script execution isn’t always permitted.chcp
stuff at the beginning & end?