Again WinForms and NativeAOT
UPDATE: This was written around beginning of year 2021 so WinForms does not have a lot of completed things. Please ignore things which are “unsupported yet”. Yet is here and shipped in WinForms itslef! Only Clipboard and Accessiblity is required support from WinFormsComInterop. Also I update instructions to match .NET 7 experience.
Let’s have a little talk about WinForms in NativeAOT context again. Time flies and more and more components can be used (note, with proper ComWrappers instance supplied). There two minor issues, one is FolderBrowserDialog
and second is WebBrowser
.
Let’s start with simple one FolderBrowserDialog
. This class works, open dialog, but cannot release it, since it uses Marshal.FinalReleaseComObject
which does not support global ComWrappers instance. This is by design and would be fixed in WinForms. If by a chance you need this right now, I can suggest easy workaround. Please contact me.
WebBrowser has issues of different nature. This is extremely complicated control, and I think I miss some part of API for which I should provide RCW and CCW. One definite place where I do know that is DWebBrowserEvents2
and this is means that no events on WebBrowser
control. This is part which I willing to handle, but require me to implement marshalling of IDispatch
interfaces. This is boring and complicated topic, and I was time-slotted, so it’s not done yet.
There Drag’n’Drop and Clipboard and maybe other locations which I do not support yet, but this is a matter declaratively define support for required interfaces. Please file issues and your use-cases so I would know what target first.
My statement now is following: WinForms can be used in NativeAOT. I decide to test how this statement works in real-world, so I select more or less interesting application on GitHub and made necessary changes to them to run under NativeAOT. Changes was update to .NET 5, maybe remove some outdated concepts from .NET framework, and register my own global ComWrapper instance for marshalling. That’s it.
BattleCity mplementation in WinForms
Original: wwwIgorNet/Battle-City-WinForms: WinForms. Game Battle City. (github.com)
NativeAOT: kant2002/Battle-City-WinForms at kant/nativeaot (github.com)
Yes. I play into that game when I was a child. There actual two version of this game in the repo, and I port only
Ruler application
Original: EdiWang/Ruler: WinForms Ruler, renewed with .NET 5.0 (github.com)
NativeAOT: kant2002/Ruler at nativeaot (github.com)
This is extremely illustrative example, since you can have your changes as simple as last commit in this repo.
Ribbon Controls
Original: RibbonWinForms/RibbonWinForms: An Office Ribbon Control for .NET WinForms (github.com)
NativeAOT: kant2002/RibbonWinForms at nativeaot (github.com)
This is not prettiest demo, but controls should be well-known :)
MaterialSkin
NativeAOT: kant2002/MaterialSkin at kant/nativeaot (github.com)
NotepadClone
Original: luisperezphd/NotepadClone: A Notepad Clone written in C# WinForms (github.com)
NativeAOT: kant2002/NotepadClone at nativeaot (github.com)
SimpleCAD
Original: oozcitak/SimpleCad: A basic CAD-like control surface for winforms. (github.com)
NativeAOT: kant2002/SimpleCad at nativeaot (github.com)
Afterwords
If you look at individual repositories, you will see that each migration of project was consisting from following steps.
- Migrate original project to .NET 7
- Modify project file for your app and add
<PublishAot>true</PublishAot>
to support NativeAOT and add<_SuppressWinFormsTrimError>true</_SuppressWinFormsTrimError>
to support trimming of WinForms. - Add my library with ComWrappers for WinForms
dotnet add package WinFormsComInterop
- Register global ComWrappers
ComWrappers.RegisterForMarshalling(WinFormsComInterop.WinFormsComWrappers.Instance);
- Optionally: Add RD.xml to make working with resources a bit more tolerable.
Content of the file, probably better look at commits in NativeAOT version of repository. - Optionally: Add
<CustomResourceTypesSupport>true</CustomResourceTypesSupport>
to have resource files support.
I would not call these examples extremely complicated, but I did not find on GitHub any presentable project on WinForms which I can run and convert. That would be definitely interesting to try. Drop me link to these projects.
Here the issue where I track support for WinForms. Right now, this is not about NativeAOT, but about proper support for ComWrappers in WinForms. Right now, I supplant custom library to make things working. Eventually this library should self-destruct, and you can use WinForms as is, thanks for coming support for ComWrappers in WinForms. Meanwhile please try convert your WinForms app and let me know how it goes. I invest a bit of time in codegen for ComWrappers, so any features should be trivially added.
What about WPF?
WPF is still a bit problematic. I start playing with support of ComWrappers for WPF in my library, but it’s a more complicated then WinForms, and use Marshal.ReleaseComObject
which do not play well with ComWrappers. As such it’s hard dependency on built-in COM which would not be supported in NativeAOT I left with 2 options: First, Add support for ComWrappers into WPF, which probably would be long. Second, add small change to NativeAOT and recommend compile WPF using this fork.
After that we will hit state, so even WPF application runs, or I hit another limitations in NativeAOT: CLI/C++ support (or lack thereof). Let’s see. If you interested in that scenario, follow this issue in WPF repo and express that you want this scenario and if any PR for ComWrapper support start appearing, support them too.
What about UWP?
I have no idea, if I can run this kind of applications using command line. If I can build, and publish it using dotnet build
or in worst case MSBuild, maybe I can try. If somebody experienced with UWP can lay helping hand, I would be glad to chat. I do not have hopes on that mode, most likely WinUI is better approach.
What about WinUI?
I think WinUI is more realistic to make work in NativeAOT. I need somebody who show me how to compile and publish application, using MSBuild. And then how to run via command line. Note that I already know that dotnet build
is out of option right now. Still I see hopes in that, since at least MSBuild scenario more likely would be supported and maybe I can hack around to inject ILC into build-publish-run cycle without much hassle.
Call to action
I would repeat my call to try NativeAOT and report issues in the official repo. If you curious about practical problems, ask about them on Gitter.