microsoft / terminal

The new Windows Terminal and the original Windows console host, all in the same place!
MIT License
95.24k stars 8.27k forks source link

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

Closed SainoNamkho closed 2 years ago

SainoNamkho commented 2 years ago

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.

SainoNamkho commented 2 years ago

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.

zadjii-msft commented 2 years ago

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:

You'll get the following windows:

image


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.

eryksun commented 2 years ago

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%.