9

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!

5
  • 2
    Unclear: The .bat file will execute within a CMD shell that will terminate when it finishes. What does Windows Terminal have to do with it?
    – harrymc
    Commented Mar 23, 2021 at 21:19
  • 1
    @harrymc I'm guessing what the OP means is that .bat files, when executed, open the CMD shell in the Windows Console terminal. The question is really how to make it default to Windows Terminal instead of Windows Console. Same for PowerShell/ps1 files, of course. Commented Mar 23, 2021 at 22:18
  • @Frantumn I don't have the time to fully answer, but maybe I can point you in the right direction. You'll need to edit the existing "Run with" entries for .ps1 and .bat commands. The syntax for opening a new Windows Terminal session and launching a PowerShell script would be wt new-tab powershell.exe -f c:\path\to\script.ps1. That will end up as something like wt new-tab powershell.exe -f %1 in the registry entry. There's some more info here on the "Run with PowerShell" Registry entries. Commented Mar 23, 2021 at 22:33
  • Windows terminal is a terminal/console just like conhost.exe in older Windows and can't run anything. cmd and PowerShell are shells that will attach to terminals like the above or the one in VS code. Only shells can run programs/commands
    – phuclv
    Commented Mar 24, 2021 at 3:39
  • “Can this be done” - No
    – Ramhound
    Commented Mar 24, 2021 at 3:44

8 Answers 8

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.

6
  • Most importantly there is no way to do what the author wants currently. It’s not supported by Windows (today) A developer indicated that it would be unlikely to happen before 21H1 that was in June 2020 which is due to be released in the next 60 days. Follow the Windows Terminal developer team on their blog this will likely be a huge feature
    – Ramhound
    Commented Mar 24, 2021 at 2:41
  • Roger that.... WT is a Windows app, and though you can find the WT.exe, that does not change that.
    – postanote
    Commented Mar 24, 2021 at 2:43
  • It being a UWP isn’t the actual reason, the real reason, there isn’t a way to replace command prompt with a different prompt (even PowerShell) although Microsoft did...
    – Ramhound
    Commented Mar 24, 2021 at 2:46
  • Not disagreeing with that, just pointing out a specific thing. Without the reg hack, one can add WT to the SendTo Menu, just as you can with any .exe or the like, then in Windows Explorer, right-click a file type, select SendTo, and select Windows Terminal or whatever. Yet, if you did this, you still need to tell WT, which command processor you want to use. This will start WT, the processor defined, and run the file defined. I'll update the post to show what I mean.
    – postanote
    Commented Mar 24, 2021 at 3:50
  • "Sometimes it worked, sometimes it did not." -- Does adding -f to the end of the Shortcut command make it work more consistently? Commented Mar 25, 2021 at 3:32
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.

1
  • For powershell it would look something like this: wt powershell -NoExit -Command '.\scriptToRun.ps1'
    – Maxter
    Commented Jan 11 at 19:38
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.

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 \"%1\"
    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',"--title `"$title`"","$psExe -NoLogo -NoExit -f `"$fileName`"")
    }
}
4
  • I can see the point of this approach as well. I just hate .bat/.cmd, since that was my life for decades before better things came along. .bat/.cmd/.vbs just need to die, yet, we need a more built-in succinct/complete replacement first. I know; I know; that would mean getting rid of cmd.exe, wscript.exe,cscript.exe, and MS has no intention to make that happen. Just like they should just get rid of notepad.exe and replace that with VSCode, vs the planned updates to notepad.exe. But, that; sjust me. ;-}
    – postanote
    Commented Mar 25, 2021 at 4:40
  • Oh, definitely not just you. I was thinking the same thing when writing up the first answer. Even those registry entries seem to follow the (fairly arcane) CMD quoting rules, rather than something more consistent and "intelligently designed" like PowerShell. But now we're in an even worse time-period, where even Windows PowerShell is deprecated, not getting anything other than security fixes. So we have two "dead" shells pre-installed with Windows, while the "current" PowerShell core isn't even there out-of-the-box. Commented Mar 25, 2021 at 6:22
  • The "good news" is that there shouldn't be any reason that the "launcher" script couldn't be PowerShell. The only reason I went down the .bat path was that I was hoping it would get launched "in the background" by default. But since it still briefly flashes a terminal window, it has to be minimized anyway. It's (literally) been decades since I've written a batch file. Otherwise I probably would have used the more modern .cmd extension ;-). Commented Mar 25, 2021 at 6:25
  • Yeppers, though MS as said, though no more work in going into WinPS, like cmd.exe, it will be in any OS release for the foreseeable future. So, like cmd.exe, we will seem to always have it around. As for VSC/pwsh not being in the OS by default; well, that the OSS path that we are going to have to live with. On all my gold OS images (when and where my customers allow me), VSC is the notepad replacement (though I provide a way to switch that back), and PSCore is added as well, and I make all visible in the menus (Start/.WinX/SendTo shortcuts in the taskbar), so, users choose which to use.
    – postanote
    Commented Mar 25, 2021 at 7:44
1

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

0
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" %*

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .