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
C++/WinRT support for implementing out-of-proc WinRT servers #601
Comments
We'd love to have this support as well. Any thoughts on how hard this would be to implement? I'm less familiar with the plumbing for out-of-proc - any pointers to the underlying APIs involved? |
Any update on this front? |
Oddly enough, this just bit me in the butt today too. It's hard to be hearing "Use CppWinrt and leave WRL behind" when we're missing things like this. |
It would be great to have a bit more info on what exactly folks are looking for here. Here's a simple client/server that works well enough. This could easily be hosted inside an NT service or some other host but the precise details are unique to each host scenario. Regarding Ben's points above: For 1: C++/WinRT has never provided this and instead generates the list from metadata. I doubt we'd start providing this today just for COM. Generally, the list of COM classes should be small. For WinRT classes this isn't an issue. For 2: This already exists and is extensible for different hosting/lifetime models. For 3 and 4: This could be built on top of 2. So, I'm not apposed but it would help if folks can provide more information in terms of requirements. Also, PRs are welcome. This isn't something we've got committed time to work on so if its something that matters to your team feel free to consider a PR. We are of course more than happy to review and provide expert feedback. |
I'm looking for this. But in cppwinrt-speak.
|
I'll go 1 step further: I need Packaged COM OOP Server. Here's the closest docs I could find about it. Or better, follow this for a closer answer. Not just a .exe provided an OOP server. Yes, a Classic COM OOP Server aka exe. Not a COM Service. |
FYI for OS.2020 devs, see this addition to wil that simplifies C++ WinRT WRL integration. |
I'm also personally interested in this - I would like to provide an out of proc WinRT API that allows other programs to send commands to my program. Being in WinRT rather than COM allows easier consumption by managed languages, but being restricted to WRL only for the server implementation makes it harder for me to implement. Kenny's snippet is interesting, but how would consumers from C# or Rust do to create an instance of the remote object? |
Feel free to reopen if there's interest in exploring this further. |
Terminal’s interested in doing this, but we don’t have reopen permission here. /cc @zadjii-msft |
Agree. I'm using WRL despite a spirit of @ChrisGuzak in my head telling me that new code based around WRL is a big no-no in 2020 and I should be using full C++/WinRT. I'm very interested in appeasing that projection I have of Chris and doing it The Right Way (TM). |
Just to set expectations, this is not a wish list. 😉 Someone needs to offer a solution that everyone can review and rally around. I don't have one, partly because there are just too many ways to do OOP and I'm not confident any one solution would satisfy everyone's needs. I also don't have the time to invest in this at the moment. |
FYI I'm still interested in this despite working around it as that won't be the last time I (or anyone else) need go there. @kennykerr there are just too many ways to do OOP |
I don't know that much about it, but I've played with enough wildly different approaches to know that I don't know enough. 😉 First there are hosting differences from NT services, dedicated or shared, and standalone server executables that may register factories at startup, or not. This may or may not impact how the code is written. For example, some registration APIs will block while others will return. Then there are both registry-based and API-based registration for both WinRT-based and COM-based activation. Then you have to figure out all the ways these can be combined and in what context some are valid while others are not. Developers are combining these in a variety of ways, for example to get the magic of WinRT bindings in places where WinRT activation isn't supported. You just have to get Hart/Brian/Kevin going (from COM) and I'm sure they'll give you quite a few more options that I haven't thought of here. |
Closing this issue as there has been no activity. Feel free to keep the conversation going. |
Hello, is there any plan to commit on it? I want to author an WinRT out-of-proc exe server to serve as an IPC server without needs of writting WRL manually. |
There is a helper to at least integrate C++/WinRT Implementation objects into the WRL module count. See the attached file for an example of how you can implement the Exe logic with a couple lines of WRL. The rest is then your C++/WinRT objects regstered with WIL via CoCreatableCppWinRtClass. You can also reuse module_count_wrapper if you want to do other object types such as singletons. |
Isn't this for COM out of process classes? E.g. clients can't just construct the corresponding WinRT class and have to call CoCreateInstance then can cast to the WinRT class |
Correct. Due to Windows limitations, not C++/WinRT, you cannot register activatable (WinRT) classes. That requires TrustedInstaller privileges. COM only requires Admin. Registration Free WinRT exists, but it only supports inproc activation from a dll AFAIK. With that said, doing an initial CoCreateInstance and then casting to a WinRT RuntimeClass (or interface) isn't too bad, as long as you can CoCreateInstance from the client language you're using. C++ is easy, for C# use Interop (for the initial bootstrap), and Rust I'm not sure. C++ usage example |
Yep, you can do the same in Rust. |
You can make a packaged OOP WinRT server and access it via Dynamic Dependencies WinRT registration requires the OOP server be a Windows component (and thus TrustedInstaller privilege) or an MSIX package authored by anyone. Dynamic Dependencies let's anyone consume the latter (it's not just for packaged apps anymore :-) |
My app is packaged so that's an option - though can I implement the server in my main app process instead of as a dedicated server process? Since my idea is to provide third party apps an API to interact with my app, so a dedicated server process means I'm doing double RPC. Can apps create a dependency on a non-framework package as well? Documentation seems to imply it's not doable. Also - dynamic dependencies is Windows 11 only. I can't ask apps to import WASDK's polyfill since WASDK brings in all of WinUI 3 (which, notably, results in conflicts if you're using WinUI 2). I don't have a lifetime manager for my app so that the polyfilled dynamic dependencies keeps it installed while being used and I don't know how I would implement one (this doesn't seem to be documented). The expected use case is that apps import the WinMD, either manually or via NuGet, then the classes "just work", so C# code can eg do |
For marshaling, you'd either need to register a proxy/stub dll with COM or both client and server each need the winmd file (to leverage MBM). I would recommend MBM as you don't have to deal with the fuss of proxy/stub dlls. To leverage MBM, you would ensure
|
Meta: For those reading along, the acronym MBM refers to Metadata Based Marshaling. |
MBM sounds really interesting! I'll give this a try when I can. I suppose I don't need to mess with packaged COM stuff because I only make the class available while running, but packaged COM is to make it start up a server at will (this is for interop between other apps and mine, so I want users to still be in control of when my app runs). |
Packaged COM allows a packaged app to register classic COM objects. I believe it only works for out-of-proc. So, if it's your app, you could have a MyApp.exe and a MyComServer.exe. Your MyComServer.exe would host the Packaged COM objects and your MyApp.exe would run your foreground app. When a client CoCreates one of your objects, COM will take care of starting your MyComServer.exe if it's not running, and you would own the logic for when it shuts down. Any client (including your own MyApp.exe) can CoCreate your packaged COM objects (assuming you set the security appropriately). Your approach will depend on who you want to be the client and server. This likely depends on the user experience flow you want. If you want your app to be the client and the partner apps' to be the servers: if they're packaged they could register via Packaged COM, if they're not-packaged, they'd register the classic style (requiring admin privileges and CLSID reg, etc). You also need a way for that partner to tell you "they exist" and which CLSID you should go CoCreate. i.e. they'd need to register with COM and register with your app (.e.g registry if non-packaged, or AppExtensions if packaged). If you want your app to be the server and the partner apps' to be the clients, then you could leverage Packaged COM. Partner apps can simply make themselves known to your app by CoCreating your packaged COM object(s). This doesn't spin up your MyApp.exe, only your MyComServer.exe. The drawback here is the partner apps have to have something start them for your app to be aware. Regardless, you should still switch from Classic COM to WinRT immediately after activation if you want to leverage WinRT projections and marshaling via MBM. |
I try to use oop to make a Loopback Exemption Manager. The server is a win32 app written in cpp/winrt and the client is a UWP written in .NET. I tried to find out the way to using wrl to manage server by looking the winget. But it is too difficult to find out how to use it. So I use the destructor to watching for disposing... |
It's been 4 years since this ask so I might be too late, but my PR that implements (1) and (3) has been merged in WIL: microsoft/wil#440 We can now implement COM server with cppwinrt-only. No more WRL. Usage example:
|
Wow, does it have any example? |
@wherewhere None for now but updating existing docs to migrate from WRL to cppwinrt+WIL is my next long term task. In the mean time, you can checkout WIL's test. For simplicity the tests use This is my proof-of-concept repository before the PR. The helper class isn't in |
Currently, you cannot implement an OOP server without utilizing a hybrid approach with WRL or COM APIs.
It would be helpful if C++/WinRT provided a mechanism similar to WRL::Module that all implemented WinRT objects in the module would integrate with.
Like WRL, covers:
Not supported by WRL (I don't think), but nice to have:
The text was updated successfully, but these errors were encountered: