Search code examples
powershell

What are all the valid extensions for Get-Command -CommandType Application in Powershell 7?


I'm writing a function that launches applications via Get-Command $CommandName -CommandType Application.

Reading the documentation here says that the accepted extensions for -CommandType Application are .txt, .exe, and .dll files.

But this isn't true. I've launched .cmd, .bat, .ps1, and other file extensions using -CommandType Application

I need to know the full range of valid executable extensions for Get-Command -CommandType Application.


Solution

  • The documentation is lacking on that extension list, issue #11528 was submitted to the MS Docs repo to clarify this.

    -CommandType Application will read as follow once the PR is pushed to learn.microsoft.com:

    Application: Searches folders in the $env:PATH environment variable for non-PowerShell executable files. On Windows, executable files have a file extension that is listed in the $env:PATHEXT environment variable.


    If you want to know what the cmdlet uses behind the scenes you can inspect the source code. Get-Command behind the scenes essentially uses $ExecutionContext.InvokeCommand.GetCommands, if you inspect the source for CommandInvocationIntrinsics from there you can see that this class uses CommandSearcher and in there you will see they have this comment:

    We are never going to look for non-executable commands in CommandSearcher.
    Even though file types like .DOC, .LOG,.TXT, etc. can be opened / invoked, users think of these as files, not applications.
    So I don't think we should show applications with the additional extensions at all.
    Applications should only include files whose extensions are in the PATHEXT list and these would only be returned with the All parameter.

    That comment gives a hint that they're using a hardcoded list of extensions, the next step is to scroll up a bit where you will find an #if !UNIX directive (Line 1346) and lastly you can see that they use CommandDiscovery.PathExtensions and there it is, thru a bit of reflection you get that list. In the end, the list is gotten by parsing Environment.GetEnvironmentVariable('PATHEXT').

    $commandDiscovery = [psobject].Assembly.GetType(
        'System.Management.Automation.CommandDiscovery',
        $false,
        $false)
    
    $prop = $commandDiscovery.GetProperty(
        'PathExtensions',
        [System.Reflection.BindingFlags] 'NonPublic, Static')
    
    $prop.GetValue($type, $null)
    

    Which ends with this list:

    .com
    .exe
    .bat
    .cmd
    .vbs
    .vbe
    .js
    .jse
    .wsf
    .wsh
    .msc
    .cpl