Search code examples
windowspowershellcmdconsoleio-redirection

Why does a Perl script that is run from PowerShell run in a new console, but a Python script does not?


For both file associations, .py and .pl, I have a pair of ftype and assoc so that I can run Perl and Python scripts without explicitely specifying the path to their respective interpreter executable, like so:

 C:\users\rene> .\abc.pl
 C:\users\rene> .\xyz.py

When I do the "same" in a PowerShell console, executing the Perl Script opens another console in which it executes, yet the Python script executes in the same console.

Because the Perl Script runs in another console, I am faced with two problems: 1) I cannot redirect STDOUT of the script and 2) the console closes when the script is done, thus I cannot see its output.

I have no idea why the Python script behaves differently from the Perl script and I wonder what I need to change in order for the Perl script to run in the same console when executed in PowerShell.


Solution

  • Assuming that the .pl filename extension is associated with a file type that uses a console application to perform the Open verb on that file type (run ($fileTypeName = cmd /c assoc .pl) to learn the file-type name, then cmd /c ftype $fileTypeName to see its definition):

    In order for PowerShell to run files with a given filename extension in the current console window, synchronously (assuming they're associated with a console application), that extension must be listed in the system-defined $env:PATHEXT environment variable, which is surprising.[1]

    You can add .pl to $env:PATHEXT as follows:

    • For the current session only:

      $env:PATHEXT += ';.pl'
      
    • Persistently:

      • Must be run from an elevated session (run as admin), and requires starting a new session to take effect:

        [Environment]::SetEnvironmentVariable('PATHEXT',
          ([Environment]::GetEnvironmentVariable('PATHEXT', 'Machine') + ';.pl'), 
          'Machine'
        )
        
      • Note: It is possible - though rare and not advisable - for a persistent user-level definition of this environment variable to shadow the machine-level (all-users) definition. If that is true for your user account, replace 'Machine' with 'User' above.


    [1] As you state, the purpose of the $env:PATHEXT environment variable is to list filename extensions that are implicitly executable, so that, with .pl present in the variable, excecuting .\abc.pl can be shortened to .\abc. This aspect is conceptually separate from the file-type associations that allow defining what executable to pass non-executables with given filename extensions to on direct invocation, and it is arguably a bug that PowerShell couples these two aspects; it would make more sense for PowerShell to always run console-based executables in the current window, synchronously.