After updating Windows Terminal, pressing Ctrl+Profile will not inherit the working directory #19705

Closed
opened 2026-01-31 06:51:19 +00:00 by claunia · 11 comments
Owner

Originally created by @TGSAN on GitHub (Apr 13, 2023).

Windows Terminal version

1.16.10262.0

Windows build number

10.0.22621.1537

Other Software

No response

Steps to reproduce

  1. Set the startup directory in Windows Terminal settings to ".".
  2. Go to a folder in File Explorer (for example: D:\SomeDir).
  3. Right-click and select "Open with Terminal" from the context menu.
  4. Hold down the Ctrl key on the title bar of the new Windows Terminal and create any tab (to create as an administrator).`

Expected Behavior

In the new Windows Terminal that runs as an administrator, the working directory is inherited as D:\SomeDir

Actual Behavior

In the new Windows Terminal that runs as an administrator, the working directory is reset to C:\Windows\System32

Originally created by @TGSAN on GitHub (Apr 13, 2023). ### Windows Terminal version 1.16.10262.0 ### Windows build number 10.0.22621.1537 ### Other Software _No response_ ### Steps to reproduce 1. Set the startup directory in Windows Terminal settings to ".". 2. Go to a folder in File Explorer (for example: `D:\SomeDir`). 3. Right-click and select "Open with Terminal" from the context menu. 4. Hold down the Ctrl key on the title bar of the new Windows Terminal and create any tab (to create as an administrator).` ### Expected Behavior In the new Windows Terminal that runs as an administrator, the working directory is inherited as `D:\SomeDir` ### Actual Behavior In the new Windows Terminal that runs as an administrator, the working directory is reset to `C:\Windows\System32`
claunia added the Issue-BugIn-PRNeeds-Tag-FixProduct-TerminalSeverity-Blocking labels 2026-01-31 06:51:19 +00:00
Author
Owner

@TGSAN commented on GitHub (Apr 13, 2023):

In the first stable version that supports creating an administrator profile window by holding down Ctrl (Version 1.15.2525.0), its behavior was as expected. After Windows Store updated Windows Terminal recently, I found that its behavior was broken.
Currently I can only solve this behavior change by using the powershell -Command Start-Process wt -Verb runAs command, but it is very inconvenient.

@TGSAN commented on GitHub (Apr 13, 2023): In the first stable version that supports creating an administrator profile window by holding down Ctrl (Version `1.15.2525.0`), its behavior was as expected. After Windows Store updated Windows Terminal recently, I found that its behavior was broken. Currently I can only solve this behavior change by using the `powershell -Command Start-Process wt -Verb runAs` command, but it is very inconvenient.
Author
Owner

@TGSAN commented on GitHub (Apr 13, 2023):

I just tested every stable version and found that 1.15.3465.0 and 1.15.3466.0 are the last stable versions that can inherit the working directory, while 1.16.10261.0 and 1.16.10262.0 are the first stable versions that will not inherit the working directory.

@TGSAN commented on GitHub (Apr 13, 2023): I just tested every stable version and found that `1.15.3465.0` and `1.15.3466.0` are the last stable versions that can inherit the working directory, while `1.16.10261.0` and `1.16.10262.0` are the first stable versions that will not inherit the working directory.
Author
Owner

@DHowett commented on GitHub (Apr 13, 2023):

@zadjii-msft hm. ShellExecute("appsfolder:...") fallout?

@DHowett commented on GitHub (Apr 13, 2023): @zadjii-msft hm. `ShellExecute("appsfolder:...")` fallout?
Author
Owner

@zadjii-msft commented on GitHub (Apr 18, 2023):

@zadjii-msft hm. ShellExecute("appsfolder:...") fallout?

probably

@zadjii-msft commented on GitHub (Apr 18, 2023): > @zadjii-msft hm. `ShellExecute("appsfolder:...")` fallout? probably
Author
Owner

@kovdu commented on GitHub (Apr 26, 2023):

Also noticed this when looking into #14817 and in my case I was not able to set the working directory for ShellExecute. Somehow it was never talking into account and googling around didn't return anything useful.

1.15.2525.0 is just doing CreateProcessW here https://github.com/microsoft/terminal/blob/release-1.15/src/cascadia/ShellExtension/OpenTerminalHere.cpp#L47 but was not starting elevated then.

So indeed moving to ShellExecute is causing this. But don't know what would the best way to set the working directory then tbh.

@kovdu commented on GitHub (Apr 26, 2023): Also noticed this when looking into #14817 and in my case I was not able to set the working directory for `ShellExecute`. Somehow it was never talking into account and googling around didn't return anything useful. `1.15.2525.0` is just doing `CreateProcessW` here https://github.com/microsoft/terminal/blob/release-1.15/src/cascadia/ShellExtension/OpenTerminalHere.cpp#L47 but was not starting elevated then. So indeed moving to `ShellExecute` is causing this. But don't know what would the best way to set the working directory then tbh.
Author
Owner

@zadjii-msft commented on GitHub (May 1, 2023):

Hmm. I bet this especially breaks in 1.18. I wonder actually if "startingDirectory": "." will be really broken, because the Terminal's CWD will always be the CWD of the first terminal window.

Butts.

@zadjii-msft commented on GitHub (May 1, 2023): Hmm. I bet this especially breaks in 1.18. I wonder actually if `"startingDirectory": "."` will be really broken, because the Terminal's CWD will always be the CWD of the _first_ terminal window. Butts.
Author
Owner

@zadjii-msft commented on GitHub (May 1, 2023):

Okay, I've got a possible solution, but I think I ended up building it on top of #5506, and that might be too much to pull in this late in the release.

Basically, the simple idea is:

  • Manually pass the evaluated CWD to _OpenElevatedWT,
  • so that we launch elevate-shim new-tab -p {guid} -d <path>.
  • That'll then ShellExecute({ "shell:AppsFolder\...", "new-tab -p {guid} -d <path>"}),
  • and then the elevated window would treat that as "manually start this profile with the CWD <path>"

I deeply worry that'll cause mysterious edge cases with like, c:\ or other string escaping nonsense.

@zadjii-msft commented on GitHub (May 1, 2023): Okay, I've got a possible solution, but I think I ended up building it on top of #5506, and that might be too much to pull in this late in the release. Basically, the simple idea is: * Manually pass the _evaluated_ CWD to `_OpenElevatedWT`, * so that we launch `elevate-shim new-tab -p {guid} -d <path>`. * That'll then `ShellExecute({ "shell:AppsFolder\...", "new-tab -p {guid} -d <path>"})`, * and then the elevated window would treat that as "manually start this profile with the CWD `<path>`" I deeply worry that'll cause mysterious edge cases with like, `c:\` or other string escaping nonsense.
Author
Owner

@zadjii-msft commented on GitHub (May 1, 2023):

note:

diff --git a/src/cascadia/ElevateShim/elevate-shim.cpp b/src/cascadia/ElevateShim/elevate-shim.cpp
index 50449ddca..ee90aec45 100644
--- a/src/cascadia/ElevateShim/elevate-shim.cpp
+++ b/src/cascadia/ElevateShim/elevate-shim.cpp
@@ -13,6 +13,7 @@
 #include <gsl/pointers>
 #include <shellapi.h>
 #include <appmodel.h>
+#include <wil/filesystem.h>^M

 // BODGY
 //
@@ -96,12 +97,15 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
     SHELLEXECUTEINFOW seInfo{ 0 };
 #pragma warning(pop)

+    auto cwd{ wil::GetCurrentDirectoryW<std::wstring>() };^M
+^M
     seInfo.cbSize = sizeof(seInfo);
     seInfo.fMask = SEE_MASK_DEFAULT;
     seInfo.lpVerb = L"runas"; // This asks the shell to elevate the process
     seInfo.lpFile = cmd.c_str(); // This is `shell:AppsFolder\...` or `...\WindowsTerminal.exe`
     seInfo.lpParameters = GetCommandLine(); // This is `new-tab -p {guid}`
     seInfo.nShow = SW_SHOWNORMAL;
+    seInfo.lpDirectory = cwd.c_str();^M
     LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&seInfo));

     return 0;
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 99a1fdafd..00008642f 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -4181,6 +4181,8 @@ namespace winrt::TerminalApp::implementation
         STARTUPINFOW si{};
         si.cb = sizeof(si);

+        auto cwd{ wil::GetCurrentDirectoryW<std::wstring>() };
+
         LOG_IF_WIN32_BOOL_FALSE(CreateProcessW(exePath.c_str(),
                                                cmdline.data(),
                                                nullptr,
@@ -4188,7 +4190,7 @@ namespace winrt::TerminalApp::implementation
                                                FALSE,
                                                0,
                                                nullptr,
-                                               nullptr,
+                                               cwd.c_str(),
                                                &si,
                                                &pi));

did not just work

@zadjii-msft commented on GitHub (May 1, 2023): note: ```diff diff --git a/src/cascadia/ElevateShim/elevate-shim.cpp b/src/cascadia/ElevateShim/elevate-shim.cpp index 50449ddca..ee90aec45 100644 --- a/src/cascadia/ElevateShim/elevate-shim.cpp +++ b/src/cascadia/ElevateShim/elevate-shim.cpp @@ -13,6 +13,7 @@ #include <gsl/pointers> #include <shellapi.h> #include <appmodel.h> +#include <wil/filesystem.h>^M // BODGY // @@ -96,12 +97,15 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) SHELLEXECUTEINFOW seInfo{ 0 }; #pragma warning(pop) + auto cwd{ wil::GetCurrentDirectoryW<std::wstring>() };^M +^M seInfo.cbSize = sizeof(seInfo); seInfo.fMask = SEE_MASK_DEFAULT; seInfo.lpVerb = L"runas"; // This asks the shell to elevate the process seInfo.lpFile = cmd.c_str(); // This is `shell:AppsFolder\...` or `...\WindowsTerminal.exe` seInfo.lpParameters = GetCommandLine(); // This is `new-tab -p {guid}` seInfo.nShow = SW_SHOWNORMAL; + seInfo.lpDirectory = cwd.c_str();^M LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&seInfo)); return 0; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 99a1fdafd..00008642f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4181,6 +4181,8 @@ namespace winrt::TerminalApp::implementation STARTUPINFOW si{}; si.cb = sizeof(si); + auto cwd{ wil::GetCurrentDirectoryW<std::wstring>() }; + LOG_IF_WIN32_BOOL_FALSE(CreateProcessW(exePath.c_str(), cmdline.data(), nullptr, @@ -4188,7 +4190,7 @@ namespace winrt::TerminalApp::implementation FALSE, 0, nullptr, - nullptr, + cwd.c_str(), &si, &pi)); ``` did not _just work_
Author
Owner

@DHowett commented on GitHub (May 15, 2023):

@zadjii-msft you marked this up for 1.17 servicing but it has a hard dependency on the virtual CWD work. Do you think we should backport them as a pair, or would you be willing to retool the fix to be 1.17-specific?

@DHowett commented on GitHub (May 15, 2023): @zadjii-msft you marked this up for 1.17 servicing but it has a hard dependency on the virtual CWD work. Do you think we should backport them as a pair, or would you be willing to retool the fix to be 1.17-specific?
Author
Owner

@zadjii-msft commented on GitHub (May 17, 2023):

@DHowett Uh, maybe there's a way to retool. The vCWD work is definitely too scary to backport straight to Stable

@zadjii-msft commented on GitHub (May 17, 2023): @DHowett Uh, maybe there's a way to retool. The vCWD work is definitely too scary to backport straight to Stable
Author
Owner

@TGSAN commented on GitHub (Jun 30, 2023):

In version 1.17 Preview, the working directory inheritance was restored, but in the recent update to version 1.18, it broke again. What happened? 🤔 @zadjii-msft

@TGSAN commented on GitHub (Jun 30, 2023): In version 1.17 Preview, the working directory inheritance was restored, but in the recent update to version 1.18, it broke again. What happened? 🤔 @zadjii-msft
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#19705