Strange starting directory when launched from explorer.exe's address bar #16950

Closed
opened 2026-01-31 05:28:13 +00:00 by claunia · 3 comments
Owner

Originally created by @SainoNamkho on GitHub (Mar 8, 2022).

Windows Terminal version

1.4.201119003-release1.4

Windows build number

10.0.19042.685

Other Software

No response

Steps to reproduce

Config the starting directory of the default profile

{
            "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
            "commandline": "cmd.exe",
            "startingDirectory": "%__CD__%",

Run wt from the win+r diaglog:
image
Run wt from explorer.exe's address bar when cwd of explorer is something like %userprofile%\Downloads:
image
check the %__cd__% variable:

C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %cd%
C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe

C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %cd%\
C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe\

C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %__cd__%
C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe\

Config the starting directory of the default profile

{
            "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
            "commandline": "cmd.exe",
            "startingDirectory": "%CD%",

Run wt from the win+r diaglog:
image
Run wt from explorer.exe's address bar, still not same as cwd:
image

Config startingDirectory to %CD%\ or remove it from the profile:

the same as "%CD%".

Maybe related #7204 #12602

Expected Behavior

In some previous version which I cannot figure out, the terminal is launched the same path as the explorer.

Actual Behavior

I've not updated to the latest build because of a problem related to #6591, the .msixbundle file itself will cause a file system error,
but I can reproduce the problem on some other computers with new builds.


Additional problem:
The wt launched by explorer differs from that launched by win+r dialog not only in starting directory. There's also a special environment variable when launched from explorer.
Run !peb in WinDbg will get
image
This is the one launched from win+r
image
And the entry =::=::\ is added to explorer's environment after the terminal process is spawned.

Originally created by @SainoNamkho on GitHub (Mar 8, 2022). ### Windows Terminal version 1.4.201119003-release1.4 ### Windows build number 10.0.19042.685 ### Other Software _No response_ ### Steps to reproduce #### Config the starting directory of the default profile ```json { "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", "commandline": "cmd.exe", "startingDirectory": "%__CD__%", ``` Run `wt` from the <kbd>win</kbd>+<kbd>r</kbd> diaglog: ![image](https://user-images.githubusercontent.com/23036788/157195917-98c3fe8e-d96b-45c9-87b0-831c21d995e6.png) Run `wt` from explorer.exe's address bar when cwd of explorer is something like `%userprofile%\Downloads`: ![image](https://user-images.githubusercontent.com/23036788/157196030-707b5f91-ba2e-406d-bbe0-29db1bd2687d.png) check the `%__cd__%` variable: ```cmd C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %cd% C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %cd%\ C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe\ C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe>echo %__cd__% C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.4.3243.0_x64__8wekyb3d8bbwe\ ``` #### Config the starting directory of the default profile ```json { "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", "commandline": "cmd.exe", "startingDirectory": "%CD%", ``` Run `wt` from the <kbd>win</kbd>+<kbd>r</kbd> diaglog: ![image](https://user-images.githubusercontent.com/23036788/157196133-58168f24-c4a7-498e-8672-1fa2c5ba003d.png) Run `wt` from explorer.exe's address bar, still not same as cwd: ![image](https://user-images.githubusercontent.com/23036788/157196133-58168f24-c4a7-498e-8672-1fa2c5ba003d.png) #### Config `startingDirectory` to `%CD%\` or remove it from the profile: the same as `"%CD%"`. Maybe related #7204 #12602 ### Expected Behavior In some previous version which I cannot figure out, the terminal is launched the same path as the explorer. ### Actual Behavior I've not updated to the latest build because of a problem related to #6591, the `.msixbundle` file itself will cause a file system error, but I can reproduce the problem on some other computers with new builds. --- Additional problem: The `wt` launched by explorer differs from that launched by `win+r` dialog not only in starting directory. There's also a special environment variable when launched from explorer. Run `!peb` in WinDbg will get ![image](https://user-images.githubusercontent.com/23036788/157199308-d10e558e-4c56-4a87-9057-9ca064c4b5f6.png) This is the one launched from `win+r` ![image](https://user-images.githubusercontent.com/23036788/157200047-94ed3137-099b-4477-868c-966c319ed535.png) And the entry `=::=::\` is added to explorer's environment after the terminal process is spawned.
Author
Owner

@SainoNamkho commented on GitHub (Mar 8, 2022):

Correction:
"win+r dialog" mentioned above is actually taskmgr's "File - Run new task".
I assumed it to be same as win+r, but the win+r dialog behaves more like explorer.exe.

@SainoNamkho commented on GitHub (Mar 8, 2022): Correction: "`win+r` dialog" mentioned above is actually taskmgr's "File - Run new task". I assumed it to be same as `win+r`, but the `win+r` dialog behaves more like `explorer.exe`.
Author
Owner

@zadjii-msft commented on GitHub (Mar 16, 2022):

https://ss64.com/nt/syntax-variables.html

Variable Dynamic (update every time used) Volatile (Set at Logon) Shell Variable User Environment Variable(SETX) System Environment Variable(SETX /M) Default value assuming the system drive is C:
CD Y   Y     The current directory (string).

....

Undocumented Dynamic variables (read only)

  • %__CD__% The current directory, terminated with a trailing backslash. (Global)

Other S/O post that may be helpful: https://stackoverflow.com/questions/20156490/why-cant-i-access-a-variable-named-cd-on-windows-7/20169219#20169219

Just from skimming those, I'm betting whatever weird logic the OS uses to figure out %__CD__% behaves differently for a packaged application like the Terminal. Maybe that's why you're always getting the package directory when launched from explorer.exe, and not from the Run dialog.


Consider the following test cases, from the explorer address bar:

  • conhost cmd.exe /k echo %cd%
  • cmd.exe /k echo %cd% (with defterm enabled, so this cmd.exe starts in the Terminal)
  • wt -d %cd%

You'll get the following windows:

image

  • The first started cmd.exe, which then evaluated %cd% as the CWD that cmd.exe was started in, which is D:\dev\public\terminal
  • Same thing happened for the second window, but now cmd is running in the Terminal instead of conhost.
  • This is the key example. Here, we didn't start cmd.exe, we started the Terminal directly. Terminal tried to evaluate its CD variable (which it would have inherited from explorer), but there was no CD variable to evaluate. On (some newer versions of the Terminal than 1.4), the Terminal will correctly report to the user that %CD% is a nonsensical path, and won't just silently fall back to %userprofile%.

Probably best to not rely on %CD% at all - I've a mind to change where wt.exe actually sets it's own CWD anyways, to somewhere that's not where the Terminal was actually started from (see #5506)

Reading between the lines though, you probably want to use . as the startingDirectory, not %CD%. I'm pretty sure %CD% is only actually set by cmd.exe itself, so if you try looking at explorer.exe, the variable isn't set there.

@eryksun is usually my go-to person for explaining the weird quirks of how environment variables are expanded. He can go ahead and correct whatever mistakes I've inevitably made explaining here.

@zadjii-msft commented on GitHub (Mar 16, 2022): https://ss64.com/nt/syntax-variables.html > Variable | Dynamic (update every time used) | Volatile (Set at Logon) | Shell Variable | User Environment Variable(SETX) | System Environment Variable(SETX /M) | Default value assuming the system drive is C: > -- | -- | -- | -- | -- | -- | -- > `CD` | Y |   | Y |   |   | The current directory (string). > > .... > > Undocumented Dynamic variables (read only) > * `%__CD__%` The current directory, terminated with a trailing backslash. (Global) > Other S/O post that may be helpful: https://stackoverflow.com/questions/20156490/why-cant-i-access-a-variable-named-cd-on-windows-7/20169219#20169219 Just from skimming those, I'm betting whatever weird logic the OS uses to figure out `%__CD__%` behaves differently for a packaged application like the Terminal. Maybe that's why you're always getting the package directory when launched from explorer.exe, and not from the Run dialog. <hr> Consider the following test cases, from the explorer address bar: * `conhost cmd.exe /k echo %cd%` * `cmd.exe /k echo %cd%` (with defterm enabled, so this cmd.exe starts in the Terminal) * `wt -d %cd%` You'll get the following windows: ![image](https://user-images.githubusercontent.com/18356694/158607069-0a9a6f35-0318-4ef3-a0de-a5382cdc8311.png) * The first started `cmd.exe`, which then evaluated `%cd%` as the CWD that cmd.exe was started in, which is `D:\dev\public\terminal` * Same thing happened for the second window, but now cmd is running in the Terminal instead of conhost. * This is the key example. Here, we didn't start cmd.exe, we started the Terminal directly. Terminal tried to evaluate its `CD` variable (which it would have inherited from explorer), but there was no `CD` variable to evaluate. On (some newer versions of the Terminal than 1.4), the Terminal will correctly report to the user that `%CD%` is a nonsensical path, and won't just silently fall back to %userprofile%. <hr> Probably best to not rely on %__CD__% at all - I've a mind to change where `wt.exe` actually sets it's own CWD anyways, to somewhere that's not where the Terminal was actually started from (see #5506) Reading between the lines though, you probably want to use `.` as the `startingDirectory`, not `%CD%`. I'm pretty sure `%CD%` is only actually set by `cmd.exe` itself, so if you try looking at explorer.exe, the variable isn't set there. @eryksun is usually my go-to person for explaining the weird quirks of how environment variables are expanded. He can go ahead and correct whatever mistakes I've inevitably made explaining here.
Author
Owner

@eryksun commented on GitHub (Mar 16, 2022):

Currently, __CD__, __APPDIR__, FIRMWARE_TYPE, and NUMBER_OF_PROCESSORS are dynamic variables provided by GetEnvironmentVariableW() and ExpandEnvironmentStringsW() and implemented by the NT runtime library function RtlQueryEnvironmentVariable(). If they're set as real variables via SetEnvironmentVariableW(), the value from the environment block is ignored by GetEnvironmentVariableW() and ExpandEnvironmentStringsW(). The latter isn't necessarily the case for language runtimes, particularly those that work from a copy of the process environment block (e.g. C _wenviron, _wgetenv(), etc).

When a process is spawned via CreateProcess[AsUser]W() , if lpCurrentDirectory is set, it must name an existing directory (off-topic note: long paths aren't supported), else the call fails with ERROR_DIRECTORY. Passing "%CD%" for lpCurrentDirectory is resolved as a literal filename relative to the current working directory of the spawning process (e.g. WindowsTerminal.exe). CD is a dynamic variable in the CMD shell, so it's only reasonable to use it in a command line that's evaluated by CMD, such as cmd.exe /k echo %cd%.

@eryksun commented on GitHub (Mar 16, 2022): Currently, `__CD__`, `__APPDIR__`, `FIRMWARE_TYPE`, and `NUMBER_OF_PROCESSORS` are dynamic variables provided by `GetEnvironmentVariableW()` and `ExpandEnvironmentStringsW()` and implemented by the NT runtime library function `RtlQueryEnvironmentVariable()`. If they're set as real variables via `SetEnvironmentVariableW()`, the value from the environment block is ignored by `GetEnvironmentVariableW()` and `ExpandEnvironmentStringsW()`. The latter isn't necessarily the case for language runtimes, particularly those that work from a copy of the process environment block (e.g. C `_wenviron`, `_wgetenv()`, etc). When a process is spawned via `CreateProcess[AsUser]W()` , if `lpCurrentDirectory` is set, it must name an existing directory (off-topic note: long paths aren't supported), else the call fails with `ERROR_DIRECTORY`. Passing "%CD%" for `lpCurrentDirectory` is resolved as a literal filename relative to the current working directory of the spawning process (e.g. WindowsTerminal.exe). `CD` is a dynamic variable in the CMD shell, so it's only reasonable to use it in a command line that's evaluated by CMD, such as `cmd.exe /k echo %cd%`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#16950