-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
starting Terminal with wt no longer returns the main window handle of the resulting window #7084
Comments
Alrighty, just discovered the reason for this being #6860, and fair enough it's not an API, although would it be possible to also reinstate a direct app execution alias as |
What is your use case? |
Could reparenting instead be implemented as a command-line option similar to xterm -into windowId? Related to #4572. |
I'm just gonna put this out there, with the process model changes coming in #5000, I'm fully expecting this (officially unsupported) scenario to break further. |
I'm well-aware this isn't supported officially in any capacity, although this same ability to set an app as a wallpaper works pretty consistently across even more complex apps; I'm not expecting it to be perfect nor would I ever ask for any changes that would solely benefit such a scenario, although it would be really nice to have a traditional alias available as well as the shim. I do however entirely understand if this isn't feasible and'll happily respect that. |
So, okay, this is really cool and I'm sorry we broke it. We've got some changes in store that are probably going to make this worse before it makes it better. Once #5000 lands, even WindowsTerminal.exe isn't really going to have an HWND to hand out... @zadjii-msft: gvim supports a |
I mean something like that would be perfect! I just tried it out in vim and now I have it stuck as my wallpaper so that's fun. And no worries about breaking anything, it's to be expected! Terminal is still super-awesome anyway and I'd hate to have silly little things like this hold it back; I can't wait to see the changes you have planned come to fruition. |
If I can suggest a somewhat obnoxious workaround for now: launching WT with |
I'll probably end up doing that for now, thank you! |
@DHowett what the heck am I even looking at there 🙃 is gvim just, hijacking the notepad HWND? How? I'm not sure that this would be helpful for our window/content process idea, but could be neat for embedding the window in something else (as insane as that is) |
So, little secret here on Windows: your application window can point to a random HWND and say "yup, that's my parent!". Here, Notepad's main window is gvim's parent. I'm imagining more like, yeah, the Terminal could be embedded and literally host its entire UI in somebody else's window. It's largely orthogonal to our multi-process/content process work, and it could be related to (or the underpinnings of) "quake" mode. |
Alright, I'm going to close this one out for now. I'd like to make sure we think about it in #5000, but there's a couple workarounds for the moment. 😄 Sorry about that. If folks re-raise this issue once preview migrates to stable, we can reopen and redirect. |
@zadjii-msft @DHowett @torchgm I am looking for the same thing, but after reading this issue that has been closed, I am not sure what is the proper way to go about detecting the window id for reparenting it. I did a quick test in PowerShell using Start-Process, and while I can grab MainWindowHandle on pwsh.exe, the same property is empty for wt.exe:
This should be equivalent to the technique used in the C# sample code of this ticket. I am running Windows Terminal 1.5.10271.0 and the ticket speaks of a regression that was first observed in 1.2.2022. Is this fixed upstream but not released yet, or is there a different method of detection offered to find the window id for reparenting? It's not clear to me if it's been fixed, or if it is going to be fixed, how, and when. |
Ah, to clarify - this was broken in ~v1.2, and we're about to break this even more before we fix it any time soon. Reparenting the window isn't a currently supported scenario, so any workarounds we give you is certain to break again in the (near) future. I suppose we can use this thread for a discussion of how we might offer that in the future? I suppose it might help to have more details about what exactly you're trying to accomplish here. There's probably a difference between "we just want a single pane embedded in another HWND" vs "We want a straight up whole Windows Terminal instance in another HWND". |
Personally for my use-case I'd prefer the ability to acquire the handle of then reparent the entire WT window, as this is a bit more versatile and means I can avoid making any particularly complex changes just to support it. |
@zadjii-msft ok, in this case it means it's worth creating an official feature request for Windows Terminal reparenting/embedding into a parent window. This is useful to implement an "embedded mode" for a product like Remote Desktop Manager where the user doesn't want multiple separate windows, but multiple tabs inside the same program. For instance, you may have a few tabs with RDP connections alongside a few terminal tabs. System administrators have a lot of diverse connection types, and those that can be hosted inside Windows Terminal are just a small fraction of them. Here is a screenshot showing powershell.exe reparented inside Remote Desktop Manager. We launch powershell.exe, then wait until we can grab Process.MainWindowHandle and reparent it inside our own tab. It works well, the only downside is the powershell.exe terminal will briefly appear separately in between the time it has been created and the time it has been reparented. A better way would be to pass a command-line parameter with the parent window id, which is not possible AFAIK with most programs, but it doesn't mean we couldn't try doing it for Windows Terminal. |
@torchgm @zadjii-msft I installed Windows Terminal 1.1, an older version that still had a working Process.MainWindowHandle and I was able to reparent it inside Remote Desktop Manager. I circled it in red so you can see it, but our own tab control hides most of the Windows Terminal tab control, we can see a little bit of it, and I was able to create new Windows Terminal tabs, or trigger the dropdown selector for a new tab. For this type of integration, the simplest would be to restore Process.MainWindowHandle + add a wt.exe command-line parameter to disable the Windows Terminal tab control, and effectively force it into a "single window mode" where tabs are disabled. Rather than use the Windows Terminal tabs, we would use our own tabs in Remote Desktop Manager and launch multiple instances of Windows Terminal instead, one per tab. One may wonder why it would still be interesting to use Windows Terminal without its tabs: well, it does a whole lot more than tabs, it has better clipboard integration and is vastly more customizable than the old PowerShell terminal or command prompt. |
The configuration you're looking for is This window (in its default configuration) is not designed to be re-parented, and I'm not terribly interested in redesigning our application to serve such a narrow use case. I appreciate what you're trying to do here, but it's just not tenable that we should open the floodgates to an endless march of features so niche. When we have content processes and swap chain panel hosting, perhaps the calculus here changes. |
I think the vastly better solution would be to have a re-usable "terminal" control that could be hosted by other applications, rather than trying to re-host our entire application in another HWND. If only we had considered this scenario as a part of the design of the Terminal 😜. @awakecoding What UI framework are you using for Remote Desktop Connection? WPF? There might be a better solution here. |
I wonder how hard it would be to add such a feature to conhost. That should bypass any UWP complications, at least. |
@DHowett don't be so quick to dismiss this feature request, it's more common and important than you might think. Windows Terminal is becoming the new default terminal on Windows, so instead of pushing ISVs to reimplement their clunky terminal control, you probably want them to reuse Windows Terminal as their go-to solution. I found out I am not the first to inquire about this. @RickStrahl @StefanKoell This being said, simple window reparenting would be good enough for quick and dirty integration, and we'd be happy with it. The ideal solution is what @zadjii-msft suggested: a proper WPF control, which would be the logical equivalent of a WebView control for a browser, except we're embedding Windows Terminal and not a browser window. A WPF control would be an acceptable solution to us, and it would also be a better one in the long run because it is more flexible than a simple window reparenting. |
@KalleOlaviNiemitalo I looked at how Windows Terminal handles its tabs in Process Explorer, and it appears to spawn one OpenConsole.exe subprocess with a bunch of command-line parameters to host each tab. Quick like that, I couldn't find a way to launch it in a way that would give me a usable Process.MainWindowHandle, but if this is what I think it is (just the tab without the Windows Terminal multi-tab management on top), then it might be a very interesting approach to hosting individual tabs inside a parent process. This is probably not exposed externally, but if it's possible to make a quick & dirty prototype with usable reparenting, I'd be willing to give it a shot. |
It really isn't. OpenConsole is a copy of Everything relating to the act of being a terminal is entirely hosted within the WindowsTerminal.exe process. |
See, now I'm much more amenable to productizing the WPF control than I am to productizing "reparent the whole terminal". That's something that would need to get properly prioritized. The control already exists, but it's only for VS to consume right now - which gives us a lot of liberty in changing the interface at will. We've always meant to productize both the WPF and UWP controls at some point. We've got some work planned for the next couple months that is certainly going to affect the API layer for them. Maybe once #5000 / #1256 is sorted out entirely, we can loop back around on this. I'm re-purposing #6999 to track the work of productizing the controls. It's unfortunately not something we'll have time for in the 2.0 timeframe, but it's something we can certainly come back around on. |
Oh well, it was worth a shot then! No problem, the WPF approach looks like the best one anyway. |
@zadjii-msft @DHowett how much work would it take to restore Process.MainWindowHandle on the latest development builds? At a bare minimum, it may be usable for an intermediate integration where we'd just ship a copy of Windows Terminal and implement the embedded mode while waiting for the WPF control. |
Restoring the window handle with our architecture is impossible. It's not something we removed, it's something that disappeared because we had to introduce a shim executable to make the rest of the app platform work. If we remove that shim, a couple other things fail -- mainly, we would lose the ability to launch Terminal elevated with Ctrl+Shift+Enter from the Run dialog and PowerShell/cmd would go back to hanging when you run On the balance, with doing both simultaneously being impossible, I'd prefer elevation and powershell to work correctly. |
If we restore it for 1.7, there's a 99% chance I'm going to break it again in 1.8 😅. Part of the trick here is that If you're just going to ship a copy of the entire Terminal in your application, you might as well just launch the |
@zadjii-msft I just made it work using Windows Terminal 1.1, but now you're making me wonder if I can get it working with the very latest. I basically extracted an MSIX bundle and worked with the files directly. I modified settings.json to disable the tabs and it does exactly what I want, now if only I could control which settings.json files it would use to avoid polluting the global configuration, and if I could get a recent version of Windows Terminal, it would be perfect |
@zadjii-msft reparenting works if I launch WindowsTerminal.exe directly instead of wt.exe, even with the latest version! I extracted the files directly to do it, but all I would need to work around this problem is a trick to detect the full path to the real WindowsTerminal.exe and use it instead of wt.exe. That's something I can live with, I'd be surprised if I can't find a way to do that. Now the only thing missing for me are ways to override the settings.json for the embedded mode only without affecting global configuration. Are there environment variables or command-line parameters to force using a special settings.json file? I need to override things like alwaysShowInTabs, showTabsInTitlebar, etc. Ideally all of it would be controlled from the parent program, independently from the configuration used by the external Windows Terminal. Does the working directory of WindowsTerminal.exe have any impact on this? |
Running |
this isn't unexpected. The directory Terminal lives in isn't intended to have its executables run directly (and this isn't a limitation we can overcome, sorry!) |
Oh no I'm totally aware of this being a limitation, just wanted to make sure it was clear for anyone else reading through this that it won't work for Store releases. |
@torchgm @DHowett @zadjii-msft yeah, I didn't know about this limitation. I found a way to detect the full path, but I hit the access denied error. It's a bummer, but a full copy of the files outside of the MSIX install location would still work.
Any hints about controlling the settings.json when launching WindowsTerminal.exe, assuming I've got a working copy that won't throw the access denied error? |
Instead of trying to hack around the existing terminal app, why not copy the WPF control's source in your own code and consume that? This way it should work and you're not going to be broken by changes they make until stabilization. |
@sylveon I'm not so good with C# and WPF myself, but can you point me to the parts of the sources that have the WPF control? Is it actually fully usable today, just not officially documented and published? |
I know this looks like a dirty hack that will make most people in this thread cringe, but it's actually perfectly acceptable and would take very few code changes on our side to implement. I can detect Windows Terminal + copy the install location to a temporary directory to avoid the "access denied" error, see the end result: Last item to check on my list is how to launch WindowsTerminal.exe and tell it where to read settings.json, such that I can feed it a modified configuration where all tabs are disabled. |
I tried finding a way to force WindowsTerminal.exe to read settings.json from a given location, but it doesn't seem possible: I did notice, however, that it uses a different path when inside the MSIX installation location as opposed to outside of it. C:\Users\mamoreau\AppData\Local\Microsoft\Windows Terminal\settings.json Did I miss the way to tell where to load its settings? Being able to tell an application where to read its files is a common thing, and it definitely makes it much easier for testing with temporary settings that won't pollute the real ones. |
@sylveon @zadjii-msft how usable is the WPF control at this point? @StefanKoell reported not so long ago having tried it without much success, as it wasn't ready for prime-time yet. I know a WPF control is considered proper, but I would still very much like to do the simple window reparenting integration, because unlike the WPF control, it doesn't require shipping a full copy of Windows Terminal. I think both are complementary, not mutually exclusive. Control over the settings.json file to embed Windows Terminal inside a parent application is an issue that would affect both window reparenting and the WPF control integration, but I couldn't find a corresponding feature request ticket for it. Even with a WPF control, it would be a whole lot better for the parent application to simply inject its own settings.json containing global configuration and preconfigured profiles. This would be the only way to handle storing profile configurations inside a password manager or any other type of application. It wouldn't make sense to overwrite the existing settings.json with temporary configuration, so the most straightforward approach would be to find a way to override the location of settings.json with a command-line parameter or an environment variable. Is there such a feature request already? This is beneficial to both approaches to embedding Windows Terminal inside a parent application. From a quick look at the code, it only looks for settings.json inside two predetermined paths: one when inside an MSIX package, and one when "unpacked" or outside an MSIX package. It looks for LocalAppData with the following call, and I am not aware of a trick to force it to return something else (changing $Env:LocalAppData didn't work, but it was worth a shot):
A simple environment variable to force WindowsTerminal.exe to use a given directory for its settings would be enough to solve this problem. All we'd need to do is generate the settings.json on-the-fly and tell WindowsTerminal.exe to use it. |
I don't know how usable it is as I don't write WPF |
This weekend I tried to play around a bit and realized that the WpfControl I tried a couple of months ago wasn't the one which can now be found here: So I cloned this repo and tried again with the new WpfTerminalControl which seems to work different as the one I used before. I seems to be a thin managed wrapper to the actual terminal. Maybe this approach is better than the one I tried. Anyway, I wasn't really able to run the test project: I was able to compile Windows Terminal using the PowerShell build scripts but I couldn't run the test app. I also wasn't able to find information on how it can be run. Are there any instructions out there? |
@DHowett I'm working on my own Windows Terminal distribution (unpackaged MSIX in a nuget package), and launching WindowsTerminal.exe works with reparenting. Now I want to avoid *re-*parenting to simply provide the parent window handle to be used initially, but I'm having trouble figuring out how the primary window gets created through all the modern WinRT stuff. I've used Spy++ to see what the window hierarchy looked like once reparented within RDM: I've searched for code for calls to CreateWindow, but I'm having trouble finding which one is supposed to be the primary window used by Windows Terminal. Can you give me a hint as to what it would be called within the WT source code? Thanks! EDIT: Of course, I had to find it right after asking question. Is it the "Island Window" in https://github.com/microsoft/terminal/blob/main/src/cascadia/WindowsTerminal/IslandWindow.cpp? |
Environment
Steps to reproduce
Open Windows Terminal 1.2.2022 from code that supports returning the main window handle; for example in C# .NET
Expected behavior
The handle for the subsequently opened window is returned. In the example above, a numerical value representing the window handle is printed to the console (such as
856282
)Actual behavior
A handle of
0
is returned.The text was updated successfully, but these errors were encountered: