11

I have little power shell and cmd scripts that I run now and then. When I click on a bat script, it opens a classic CMD window. When I run a PS1 script, it opens the classic PowerShell window.

Is it possible to have these open in the new Windows Terminal by default when I run them? No, I don't want to open the terminal, navigate to the script, and run it. I just want to click on the .bat and have it run in the CMD window that is within the Windows Terminal app.

Can this be done?

I tried finding the terminal exe so that I could set ps1 files to open with it but I get an error when I try to do that. See screenshot.

enter image description here

Thanks!

Giacomo1968
  • 58,727
Frantumn
  • 996

8 Answers8

4

I am putting this here since it is too short for a comment, and that you are not asking a PowerShell code question/issue, but asking a 'How do I configure my environment/chosen tool, to do X or Y.

  1. Windows Terminal is not a shell/command processor.
  2. There is no concept of run in WT.
  3. There is only run with a command processor, PowerShell or cmd.exe. cmd.exe executes .bat, .cmd, .vbs. Powershell executes .ps.
  4. WT, on launch, starts your default shell/command processor.
  • PowerShell.exe
  • Pwsh.exe
  • cmd.exe
  • Bash.exe
  • Python.exe

... whatever processors you have configured in your WT settings.

Even if you reghack this, it will still only run the default shell/command processor you have configured in the JSON settings. So, why start a shell host, just to run a shell/command processor.

What NotTheDr01ds is showing, is already the default when right-clicking a .ps1 file and trying to change that to WT.exe will not work as you'd think.

You can first prove this to yourself by using WinKey + R and typing in the below. One will not work the other will.

wt d:\scripts\hello.ps1
# Results - error and locks WT
<#
[error 0x800700c1 when launching `d:\scripts\hello.ps1']
#>
wt powershell -noprofile -noexit d:\scripts\hello.ps1
# Results - runs the script as expected
<#
Hello World

Tuesday, 23 March, 2021 20:15:28 #>

So, any reg hack would require you to specify the command processor and the filename and any arguments needed for a successful run. As noted in my comments. You can avoid reghacks and just create a shortcut and add this shortcut to your SendTo menu. In Windows Explorer, just type...

shell:SendTo

Or in PowerShell just to this:

explorer shell:SendTo

... and paste your shortcut there (I have lots there), then you have to make the settings changes.

# Example:
"C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.6.10571.0_x64__8wekyb3d8bbwe\wt.exe" powershell -noprofile -noexit

I am letting you know in advance, that this ran into some issues.

Sometimes it worked, sometimes it did not.

Now, of course, if you wanted to do this for any of the command processors, then you need to create multiple shortcuts, alter them as needed, and paste them to the SendTo folder, then right-click your file, and select the proper SendTo shortcut.

postanote
  • 5,136
3

I just want to click on the .bat and have it run in the CMD window that is within the Windows Terminal app.

If you're willing to have two files, this is trivial.

Want to run putMeInTerminal.bat inside Windows Terminal?

Create launcher.bat:

wt cmd /k call "C:\Users\John\Scripts\putMeInTerminal.bat"

After you double-click on launcher.bat, putMeInTerminal.bat will now run in Windows Terminal as desired.

2

The default behavior today, as you know is:

  1. Double-click on a .bat file: Runs the script in the CMD shell in the "old" "Windows Console" (conhost.exe) terminal
  2. Double-click on a .ps1 file: Opens the script in Notepad
  3. Right-click on a .ps1 file and "Run with PowerShell": Runs the script in the PowerShell shell in the "old" Windows Console terminal

If I understand correctly, you want to change the behavior of (1) and (3) to run the scripts in their respective shells, but inside Windows Terminal.

@postanote makes good points that:

  • Registry hacks should be a last resort.
  • shell:SendTo may work for a number of cases without resorting to modifying the Registry.

So the SendTo technique that @postanote suggests is worth a try to see if it works for you. At first, I thought it might fail if there was a space in the path to the script. But in my testing, Windows seems to use the 8.3 short-path.

The SendTo method does have two downsides:

  • SendTo's apply to all file types, so you'll see the Send To -> Windows Terminal when clicking on a file that doesn't support it.
  • SendTo entries are nested under a submenu, so they require a bit of extra mouse movement to get to. On the other hand, "Open with"-style commands are right at the top of the right-click menu.

If it turns out you need something more, then read on for the Registry modification instructions. I do feel these are safe modifications, but the normal Registry warnings apply -- Your mileage may vary / Make backups / Here be dragons / etc.

Next caveat, while you probably can modify the default .bat double-click "Open" command, I don't recommend doing so. There may be other applications (or even Windows functionality) that relies on that default behavior. My recommendation is to add a right-click "Run in Windows Terminal" option for CMD .bat files, just as we will for PowerShell .ps1 files.

To do so:

  • Run regedit.exe (or your preferred method of launching the registry editor)
  • Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Classes\batfile\shell
  • Right-click on shell -> New -> Key
  • Name the key "run_in_wt"
  • Right-click on run_in_wt -> New -> String Value
  • Name the property "MUIVerb"
  • Double-click MUIVerb and set the Value data to "Run in Windows Terminal" (or however you want it to appear in the right-click menu)
  • Right-click on run_in_wt again -> New -> Key
  • Name the key "command"
  • Double-click on the (Default) property and set the Value Data to wt new-tab --title "CMD Shell" cmd.exe /k "%1"
    • The /k switch keeps the shell from exiting after the script is complete. This differs from the "normal" double-click-on-a-bat behavior. If you want the old behavior, just change the /k to /c and the shell will exit when the script is complete.
    • Quoting the "%1" here is what allows us to run scripts with spaces in the path. Windows substitutes the full path of the script being right-click for the %1.
  • Test it out

For Powershell/.ps1 files, repeat the process, but:

  • Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Microsoft.PowerShellScript.1\Shell

  • Repeat everything up until you change the (Default) property for the command. The Value Data here will be wt new-tab --title "Windows PowerShell" powershell.exe -NoExit -Command "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass } \; & '%1'"

    • As before, the -NoExit is added to prevent the shell from exiting (and thus closing the tab/window) when the script is complete.
    • If desired, you can add a -NoProfile to keep your PowerShell startup from running when executing scripts this way. I didn't put in there in case your scripts have any dependencies which are loaded in your profile.
  • The Set-ExecutionPolicy is copied from the "Run with PowerShell 7" right-click menu that is optional installed with PowerShell Core on Windows. It allows the script to execute (bypasses restrictions) as long as the policy isn't at its strictest level.

  • Example Screenshot: Sample Registry

Other notes:

  • Best practice is to use fully-qualified paths for powershell.exe and cmd.exe, and you should probably modify the above commands to do so. However, for wt.exe I believe it is safer to just use it without the path, since it is an "App Execution Alias" that is defined for the Microsoft Store app. On the other hand, if you didn't install through the Store, perhaps you should use the full path to where you installed wt.exe as well.

  • If there are other extensions you launch (e.g. .cmd for CMD), then you'll need to set those up as well. For instance, under cmdfile in the same registry leaf.

  • You can, of course, modify the above for PowerShell Core as well by using pwsh.exe instead of powershell.exe.

  • The hardest part of this process, IMHO, is making sure the quoting and escaping is correct. Windows parses these commands using the CMD shell's quoting and escaping rules, but then we are also running PowerShell code inside that command which needs to be escaped properly.

  • As you can see from the discussion in the comments, a lot of people feel that "terminal" vs. "shell" is an important distinction, and it is. But I don't believe that we should expect that everyone asking questions here (or even answering them) will have the "perfect" vocabulary to describe what they are asking. We ask; we answer; we learn. Apologies if any of the comments came across too harshly.

NotTheDr01ds
  • 28,025
2

Yes. Setting Windows Terminal to be the default for all console/terminal applications is now possible in Windows 11 with a recent release of Windows Terminal.

At the time this question was written, the feature was available on Windows 10 using Insider/Dev Channel builds. That is no longer an option, as all Windows 10 Insider/Dev builds with this feature have expired at this point.

For those on Windows 11 with an updated Windows Terminal:

  1. Open Windows Terminal.

  2. Click the downward-facing chevron () on the title bar then click Settings (Ctrl+,).

  3. From the Default terminal application dropdown, choose Windows Terminal and click Save.

Windows Terminal settings

Screenshot from older Windows Terminal Preview Release

NotTheDr01ds
  • 28,025
1

Also providing another option, which is an extension of @postanote's answer. This may make the "Send to" option more reliable, but it definitely has the added benefit of being a single Send to -> Windows Terminal that works for both PowerShell/.ps1 and CMD/.bat.

It still has the same drawbacks as any other Send To option, as mentioned in my other answer. The Registry Run in Windows Terminal is still an option if you need it, of course.

  • Create send_to_wt.bat wherever you normally create your scripts. This batch file will check the extension of the file being right-clicked, and run it in the appropriate interpreter inside Windows Terminal.

    @echo off
    setlocal
    set _filename=%~n1
    set _extension=%~x1
    if "%_extension%"==".bat" goto wt_cmd
    if "%_extension%"==".cmd" goto wt_cmd
    if "%_extension%"==".ps1" goto wt_ps
    

    :error wt new-tab --title "Error" cmd.exe /c echo Script extension must be either .ps1 or .bat ^& pause goto commonexit

    :wt_cmd wt new-tab --title "CMD Shell" cmd.exe /k &quot;%1&quot; goto commonexit

    :wt_ps wt new-tab --title "Windows PowerShell" powershell.exe -NoExit -Command "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass } ; & '%1'" goto commonexit

    :commonexit

  • Right-click on send_to_wt.bat and copy it to the clipboard.

  • Run explorer.exe shell:sendto from PowerShell, CMD, or the Windows Start Menu

  • Paste Shortcut into the SentTo folder

  • Rename the shortcut to "Windows Terminal"

  • Right click on the shortcut, select Properties, and set it to Run Minimized

That's it.

Update: For completeness, here's a PowerShell version of the same SendTo script, with the added feature of running .ps1 scripts in PowerShell Core if it is available, but falling back to Windows PowerShell if Core is not installed.

Unlike the CMD version, you need to set your Link Target manually to pwsh.exe -f send_to_wt.ps1 (or powershell.exe):

[String]$fileName = $args -join " "
[String]$fileExtension = [System.IO.Path]::GetExtension($fileName)
switch ($fileExtension) {
    {$_ -in @(".bat", ".cmd")} {
        [String]$cmdExe = (Get-Command cmd.exe).Path
        Start-Process wt.exe -ArgumentList @('new-tab','--title "CMD Shell"',"$cmdExe /k `"$fileName`"")
    }
    {$_ -in @(".ps1")} {
        [String]$psExe = ""
        [String]$title = ""
        if (Get-Command pwsh.exe -ErrorAction Ignore) {
            $psExe = (Get-Command pwsh.exe).Path
            $title = "PowerShell Core"
        }
        else {
            $psExe = (Get-Command powershell.exe).Path
            $title = "Windows PowerShell"
        }
    Start-Process wt.exe -ArgumentList @('new-tab',&quot;--title `&quot;$title`&quot;&quot;,&quot;$psExe -NoLogo -NoExit -f `&quot;$fileName`&quot;&quot;)
}

}

NotTheDr01ds
  • 28,025
0

wt new-tab PowerShell -c Start-Service ; new-tab cmd /k ipconfig You can try it out, the simplest command is called in my example

0

Yes you can. I tried to customise my PowerShell terminal, Developer PowerShell terminal and CMD terminal with ASCII art. The way you can do this is to hack the terminal a little bit. I will give the way in which you can do this for each terminal inside Windows Terminal. For all these types of applications, the script must be executed as a parameter for their specific applications.



PowerShell terminal


You need to pass the script as a parameter to the powershell.exe the PowerShell script and give to the argument the "PowerShell -NoExit" attributes. You need to do this because PowerShell will pass its execution flow to the script and once the script finished its execution, the PowerShell will stop.


%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe PowerShell -NoExit %SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\PowerShell_Startup_Ascii_Art.ps1

Replace the above shown PowerShell script's path with your PowerShell script's path and introduce this command inside the command line section within the settings page in the PowerShell profile or within the JSON configuration file commandline section at the PowerShell profile.




PowerShell settings page script execution method [1]

https://i.sstatic.net/oifhS.png




PowerShell settings page script execution method [2]

https://i.sstatic.net/J2OsV.png







PowerShell JSON settings file script execution method [1]

https://i.sstatic.net/5LA8X.png




PowerShell JSON settings file script execution method [2]

https://i.sstatic.net/SgHoc.png




PowerShell JSON settings file script execution method [3]

https://i.sstatic.net/H9tuk.png






PowerShell terminal ASCII art script execution result



Each time PowerShell will start in Windows Terminal the script with the ASCII art will start too

https://i.sstatic.net/GCbeF.jpg














Developer PowerShell terminal


In order to run a script at Developer PowerShell terminal's startup you will need to run your script by passing it as an argument to powershell.exe as with PowerShell.

%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe PowerShell -NoExit %SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\Developer_PowerShell_Startup_Ascii_Art.ps1

The only thing that is differing is the fact that the Developer PowerShell is importing some modules that contain compilers, package-managers and different tools for different programming languages. This is done by passing a script as an argument to powershell.exe when Developer PowerShell is launched by default. Because we already launch a script, we need to import the modules to the instance of PowerShell that is running in our script. The example shown bellow is exemplifying how to import the aforementioned modules inside the instance of PowerShell in a script:

$block = @"
    .^!777777777777777777777777777777777777!^.
   .?55555555Y?J5555555555555555555555555555J:
   !5555555Y^   :7Y55555555555555555555555557.
  :J55555555!.    :7Y5555555555555555555555Y: 
  !5555555555Y!.    :7Y555555555555555555557  
 :Y555555555555Y!.    :7Y55555555555555555Y:  
 !555555555555555Y!.    :7Y5555555555555557.  
:Y55555555555555555Y!.    .!5555555555555Y:   
!5555555555555555555J^     :Y5555555555557.   

:Y5555555555555555J!: :!J5555555555555Y:
!55555555555555?~: :!J55555555555555557.
:Y5555555555Y?~: :!J555555555555555555Y:
755555555Y?~: :!JJJJJJJJJJJJY5555555557.
:Y5555555!. :!J55555555555555555555555Y:
.7555555557:.^!J555555555: J55555557.
:Y555555555555555555555555555555555555555J:
.^!777777777777777777777777777777777777!^.

"@

Write-Host $block -ForegroundColor Blue

PowerShell -NoExit "& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Launch-VsDevShell.ps1'"

At the end of the scripts' execution, the modules are imported with the attribute "PowerShell -NoExit" in order to ensure that the PowerShell instance will stay open once the modules finished importing.

PowerShell -NoExit "& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Launch-VsDevShell.ps1'"


The implementation of the script execution at Developer PowerShell startup is done the same way as in PowerShell.




PowerShell terminal ASCII art script execution result




Each time Developer PowerShell will start in Windows Terminal the script with the ASCII art will start too

https://i.sstatic.net/yLUWA.jpg












Command Prompt terminal


Usually command prompt ASCII art scripts and other scripts are done with BATCH files, but because BATCH is old and unstable I recommend using PowerShell scripts that are executed within Command Prompt. In order to do this you need to run PowerShell as a command argument for the cmd.exe. Within the argument passed to cmd.exe you must pass as an argument to powershell.exe the script you want to execute.

%SystemRoot%\System32\cmd.exe cmd /k "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe cmd-startup-logo-ascii-art.ps1"

The PowerShell script passed as an argument to the powershell.exe within the cmd.exe argument is "cmd-startup-logo-ascii-art.ps1". The script passed as an argument to powershell.exe is not run with the PowerShell -NoExit attribute in order not to pass the control flow to PowerShell in order for the control flow to remain in cmd.exe. Replace the aforementioned script with your desired script.

The PowerShell script running in CMD:

$block = @"

JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@: :@@@ @@@YJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@^..........................................^@@@ @@@: :@@@ @@@: .. .. :@@@ @@@: .!YP5PP5P: .P&7 :@@@ @@@: !#B?^...:^ JJJ. :#@~ :@@@ @@@: !@P. &@@: ~&&^ :@@@ @@@: G@! 7@B: :@@@ @@@: P@? JJJ. ?@P. :@@@ @@@: ^#&! &@@: Y@Y :@@@ @@@: :YBGY?77?Y: ... .P@J :@@@ @@@: .^!7??7~. :JJ. :@@@ @@@: :@@@ @@@. .@@@ @@@YJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@ &&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&& ..................................................

"@

Write-Host $block -ForegroundColor White



In order to launch the script at startup pass the above shown command used to launch the powershell script in cmd.exe in the Command Prompt section of the Windows Terminal settings using the same procedures shown in the PowerShell example shown above.





Command Prompt terminal ASCII art script execution result




Each time Command Prompt will start in Windows Terminal the script with the ASCII art will start too







https://i.sstatic.net/pksBS.jpg

0

It is trivial with cmd's ftype command. Administrator is required for this solution. This solution accomplishes that double-clicking on the script launches it in Windows Terminal instead.

From it's help menu:

ftype /?

Displays or modifies file types used in file extension association

Open an instance of cmd to get started. Type in ftype and find your desired file association. You can pipe the output to findstr for ease of use ftype | findstr "powershell.exe"

Let's take cmdfile as an example (do note that this is separate from batfile).

It's default value is: "%1" %* (queried from ftype batfile)

To change it, simply: ftype cmdfile="%localappdata%\Microsoft\WindowsApps\wt.exe" "%1" %*

Lordoa
  • 11
  • 1