Hacker News new | past | comments | ask | show | jobs | submit login
WasmWinforms – .NET WinForms in a browser (github.com)
229 points by yread on Jan 23, 2019 | hide | past | web | favorite | 80 comments

I was one of the main engineers on Windows Forms circa 1998-2005. This blows my mind in so many ways.

May I ask - where are you now? i.e. what do you do as a dev - did you switch to webdev/js?

Sure, I work at Uber on developer tooling

Must have been fun! Any interesting stories to share about that time period?

Off-topic: but why did they opt for Windowed (hWnd’d) controls for WinForms when VB6 seemed fine with windowless controls and while there are advantages to windowed-controls (e.g. getting the latest enhancements to Common Controls) it seems WinForms defaults to using older versions and still overrides things like painting events. Almost as if WinForms couldn’t tell if it wanted to be like AWT or more like WxWidgets.

WinForms wanted to be more like VCL. That's what it most closely resembled.

Common controls, especially shell controls, come in different versions of comctl32 etc. and have been versioned and dynamically selected in the basis of things like application manifests for backward compatibility reasons for a long time.


API structures have different sizes so code usually needs to change to support later versions.

Didn't VB use windowed controls as well? I distinctly remember everything being a ThunderSomething when looking with Spy++.

VB (1-6)’s “built-in” controls like Buttons and Checkboxes were windowless, most of the others were ActiveX controls which were windowed. This carried-over to VBA where some controls are windowless built-ins and the rest are ActiveX too.

VB 1 - 4 used VBX controls implemented in C, only with VB 4 came the support for COM (aka ActiveX, aka subset from OLE 2.0).

Buttons and check boxes weren't windowless that I recall. Generally anything that could take focus needed a hwnd. Labels, lines, pictures, those kinds of things could be windowless. And of course anything implemented in a vbx or ocx would need a window.

Cool! On the one hand I feel like we all deserve an apology, but on the other hand that's a massive system with the kind of developer-base we could only dream of.

Seriously though, why were the fonts hard-coded to use ms sans serif instead of the OS default font (eg Segoe UI last time I checked?)

That's such an insulting thing to say without really pointing out any substantial problems?

I may hate their practices but their dev tools have always been absolutely top-notch within their (locked down) garden. No company has ever come anywhere close to emulating that, closed garden or not.

Good-natured ribbing doesn't come over text, sadly.

Seriously I have tremendous respect for anybody who works on a project that massive, I just meant it in the sense of "there are two kinds of languages, the kind people complain about and the kind nobody uses".

Of course there were a lot of jagged edges in winforms (like the font thing) - I never used a GUI framework that didn't have any of those.

Haha, nah it's all good. Honestly I'm shocked (shocked!) that I still see Winforms on resumes to this day. My real claim to fame is the VS Property Browser, which is System.Windows.Forms.PropertyGrid to this day. I love seeing new versions of VS and being like "yep, still there, that's m'baby".

Lots of stories, here's some quickies:

- Windows Forms was originally WFC from the Visual J++ project. Anders Hejlsberg was the architect as one of his first MS roles, working with him was a huge impact on my career.

- The Winforms team was, I think the first team to ever use C#, which was called COOL (C-Like Obj Oriented Language). Before then we were using a Java-like language that ran on the CLR

- The .NET Framework originated as a mash-up of the Winforms and ASP.NET teams, who were busy building frameworks separately for a while.

- The .NET project was a boiled ocean - everything was new from the runtime (CLR) to the tool (VS.NET), and two languages (C#, VB.NET). We didn't have a working debugger until late in the cycle, everything was always on the floor. This might be an anti pattern.

- I don't remember exactly what the story was with the font...20 years!... but my guess would be that it had to do with dealing with different versions of Windows and which fonts were installed.

Yeah, the boiled ocean was what impressed me about it. That was a monstrous amount of content for a 1.0 release. I was coming from a python and java background so I was used to "batteries included" but .net took that to the next level.

The PropertyGrid was quite lovely. I dimly remember being envious of Visual Studio having that cool no-frills edit-my-object widget and it wasn't initially available as part of the forms lib, but iirc there was some trick you could do to use it... I tried once but gave up on the learning curve because it was so designed for object properties and I wanted to use it to manipulate a datarow. I assume it got a more line-of-business-developer version in its later incarnations.

As a side note, not a .net pro, but I wish you came from a delphi background where component properties are searchable by focusing on a property input and pressing tab to go into name search mode instead of scrolling around. It feels like the feature was cut from VS and properties were sorted by name instead.

First, thank you for your service. You did an excellent job, really. WinForms is on my resume, and I'm proud to have it there. I love it, and consider it the gold standard for GUI development. I'm not the only one with this opinion.[0]

WPF just came at the wrong time, as mobile was about to ascend and added complexity (which I'll admit can definitely add to correctness). Given hindsight, they should've just extended WinForms in some way. Leaving more complex needs than whatever that extension entailed to the Win32 API. UWP is fine and would be the greenfield target, but being Windows 10-only makes it a nonstarter at any enterprise I've worked at. So it's WPF/UWP that are essentially dead to me. Once Windows 7 is completely abandoned, I'll change my tune and stop promoting WinForms and go with UWP. But not today.

I'm all about building out on WinForms, or while not a UI framework, Blazor. The latter of which is part of an application/UI rewrite that we're looking to do for a WinForms app that I maintain, once it hits 1.0.

WinForms does the job and it allows me to almost entirely focus on the business logic.


Completely disagree after years and years working on winforms and wpf and switching between them at my current job. You can really tell the difference when using Wpf, you can see that it was created years later and with testability in mind. Trying to test a winforms app is much more painful and even for debugging you need continuously to switch between code behind, controller, child controllers. In a properly architected wpf app you have no code behind. And good luck with laying out your components manually, without the designer it’s a massive pain compared to xaml. So kudos to the gp and to all the great guys the worked on winforms, but please don’t tell me that they shouldn’t have introduced wpf.

I think you're both right. Winforms was built on the Win32 stack, which is pretty basic and doesn't allow you to cleanly separate concerns. We had to build layout, hwnd recreation for style changes, clean wrappers around multi-hwnd objects (damn you combobox), etc. Some of these concepts around MV*, TDD, etc weren't that well known in 1998-2000.

WPF was designed to merge the best of client with what was happening on the web at that time. Data binding, declarative layout, model-view separation, these are all much better BUT you're also left dealing with styling, transitions, other stuff. WPF is clearly more powerful (I also worked on Silverlight fwiw), but takes more skill to operate.

We were targeting the VB6 user who was creating LOB apps at a big enterprise and wanted to get things done and move on.

I had already covered most of his point when I noted that the complexity can contribute to correctness, so it came off very emotional. I actually would stand by the view that WPF should've never been created, and WinForms extended. I've never heard a compelling argument to change my mind.

Instead, I'd rather have seen a path that led to just WinForms and UWP today. If you read the link that I provided, the author feels the same. WPF is the most pointless of all three. If you want XAML, there is UWP and it's more useful, and has a better future. It's hard to imagine much of a future at times for even UWP with Electron's popularity and HTML/CSS web interfaces.

It's clear that Microsoft is gearing up for massive Electron optimization with their adoption of Chromium, so that's going to just accelerate as those apps run better and use less battery while doing it.

For me, native GUI might just die with WinForms. I'd hate to see it go, it's always going to remain ideal for internal tools.

Talk about a back-handed compliment!

WinForms is the original and best... and I think the only widget kit from it's generation still around and maintained

Actually Delphi VCL is older than WinForms and is still around as well, and much better because Delphi always compiled to native code, which was a disappointment for me that .NET didnßt follow the same model and only had NGEN a kind of approximation, given Anders being the main architect on .NET.

Anders was primarily focused on C#. He contributed greatly to some of the pre-FX frameworks (WFC), but once the VJ++ injunction happened, MS was very focused on getting a modern language out into the world.

The part that you are referencing was part of the CLR (nee COM+) organization. This native compilation didn't happen for a couple of reasons:

1. Serviceability - the idea was that we wanted to be able to roll out new assemblies with fixes (remember this was in the "oh shit" phase of security awareness at MS)

2. Optimizations - there was an idea that you wanted different JIT to happen based on end machine architecture, server vs client, etc.

3. Size - at this point the size of the resulting binaries (for distribution) was still a concern. At that point it seemed better to have fat frameworks updated by Windows Update, and smaller apps that depended on that.

Many of these reasons seems less compelling now. MS was often a bubble in those days. I left in 2012 but it seems better now and it shows in their products.

Many thanks to the insight how things went from inside Microsoft.

I was there during the early days from the customer side, my employer was one of the selected MSFT Partners to get access to the pre-betas as a way to provide early feedback and be in the position to announce .NET based products on .NET 1.0 launch day.

Still remember all the .NET early docs full of red paragraphs, WIP sections or big warnings that some areas were still in the process of being fully defined and subject to change.

I always love to hear these stories.

Because it's built and bundled by a monopolistic company with an (at the time, maybe less now) institutional commitment to backwards compatibility forever. Winforms could have been the worst thing ever written and it would still be around and maintained. See WPF (not the worst but not much loved), that will live a long time, even with Microsoft seeming to back off on forever-backwards-compatability.

True... I wish more companies and developers would have that kind of commitment. Out of all the widget kits I have played with WinForms is still my favorite. (XUL is a close second)

Calculator example breaks when attempting to divide by zero:

    Uncaught abort(20) at Error
        at jsStackTrace (https://webassembly.z19.web.core.windows.net/Calculator/mono.js:1063:12)
        at stackTrace (https://webassembly.z19.web.core.windows.net/Calculator/mono.js:1077:11)
        at abort (https://webassembly.z19.web.core.windows.net/Calculator/mono.js:18097:43)
        at nullFunc_ii (https://webassembly.z19.web.core.windows.net/Calculator/mono.js:14694:2)
        at b20 (wasm-function[10723]:31)
        at emterpret (wasm-function[922]:12351)
        at _do_icall (wasm-function[8343]:63)
        at emterpret (wasm-function[922]:7917)
        at _interp_exec_method_full (wasm-function[7977]:65)
        at emterpret (wasm-function[922]:7129)
Which is weird, because in the actual code[1], there's a division by zero check which should pop up a message box:

    case '/': 
        if (opr2 != 0) 
            result = (opr1 / opr2).ToString(); 
            MessageBox.Show("Can't divide by zero"); 
Given a closer look, I doubt this is a WasmWinforms bug, but rather mono-wasm (or somewhere else along the compilation pipeline).

Edit: I'm wrong, it's a WasmWinforms bug.

[1] https://code.msdn.microsoft.com/windowsdesktop/Simple-Calcul...

Maybe the problem is the MessageBox method.

Given an even closer look, you're right ;) I saw MessageBox here[1] and assumed the implementation would just go through. After all, why would all other components compile fine, except for MessageBox? But actually, it even logs in the console

    dl_mapping_symbol MessageBox - proc name MessageBox not matched
So yep, MessageBox has no matched symbols so it crashes and burns.

[1] https://github.com/roozbehid/WasmWinforms/blob/master/winfor...

ERROR> https://webassembly.z19.web.core.windows.net/Calculator/mono...: Uncaught RangeError: WebAssembly.Memory(): could not allocate memory

I got RangeError: bad Memory initial size

I get that same error in Firefox, but in Chrome it works. Sigh.

Calculator demo uses around 1.5gb of memory so I wouldn't be surprised if it runs into various memory pressure issues.

That explains it as I have only 512MB.

"The original WinForms ran on it so this new stuff should as well", right?

Wow. Is that a VM or an actual PC?


  var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 1258291200;
That is, if the module doesn’t specify how much memory it wants (and it doesn’t), then it asks for around 1.25 GB.

From the ReadMe: "There are many many bugs and this project/product is not at all recommended for production. It is pre-alpha phase!"


More seriously, looking forward to when CLR can compile down to web assembly directly rather than requiring a large runtime. Baby steps.

This is one of the targets of the CoreRT project, and a very limited version of it works today.

CoreRT is working towards that, but it is still pretty much WIP.

i saw that video in the past, but watching it again now took me 15 minutes to realize this was supposed to be a fun video about an absurd future.

Wow, does this mean that (in the near future) we'll be able to take that HUGE repository of WinForms apps and port them to the web? Would be exciting...

They will run, but of course the WinForms UI is not exactly optimized for mobile (even high DPI support is patchy).

Agree. To me the greatest application will be intranet apps and mobile web apps.

I gave up after five minutes with a screen that said "Loading...". Any reason why <textarea> was thought to be so inefficient?

And somehow it's more snappy and responsive than some of the pages that are done in HTML today, amazing.

WebAssembly is amazing technology and in my experience is already pretty mature and can do incredible things. Definitely worth taking some time to understand it I think, especially if you have experience with “non-web” languages like C/C++. I thought Lin Clark’s cartoon intro was excellent: https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webasse...

That is really cool that that is possible! Could the same approach be used for WPF? How do WinForms and WPF differ at that layer? Would WPF be a lot bigger of a project than WinForms?

Kind of, Uno allows for UWP on WebAssembly.


Yes I know it isn't the same XAML.

Well, it is the same XAML, it just uses different controls from a different namespace. At its heart XAML is just a way of encoding object graphs in XML and can work with pretty much anything that has a default ctor and properties. As far as generic serialization formats for XML go it's one of the nicer ones in my book.

My opinion as well, the side remark as oriented towards those that always complain about WPF, Silverlight, UWP and Xamarin XAML being a bit different, when they actually share the same underlying concepts anyway.

Now we just need to embed this in an MVVM WPF application!

Am I the only one worried about how much easier this might make it to trick our less-tech-savvy friends into thinking their device "has a virus"? Might be enough to confuse my parents, at least.

It's just rendering to a canvas tag so it's not doing anything you can't already do in a browser (and haven't been able to do for years)

That was the original goal of asp.net webforms and WinForms, to make it easy to write apps that would work on web and windows with the same code ... this back in 2001. They gave up, and we were stuck with ViewState (and the horrors within)

A similar project is Uno. It lets you run UWP apps on iOS, Android and WebAssembly.


The more WASM projects are being released , the more I’m telling myself that WASM has nothing to offers to regular JavaScript developers.

Solutions like this have already existed and still exist today. ASP.NET Webforms was basically the same attempt as this but with HTML5 base controls.

Running .NET on the browser was a great idea on paper for cross-platform application , but seing how much time it takes to load the entire .NET framework it’s just isn’t a suitable solutions for production.

This isn't a real project, it's just an experiment.

Blazor is the official Microsoft project that uses a small .NET runtime with Razor components and is already smaller and faster than many JS bundles without any optimizations.

I think the point is that you won’t need to load the entire .net framework when the technology has matured. You can probably get away with a 1MB binaries if it is compiled server side, only shipping the dependencies used, etc.

I don’t think this will ever replace javascript for common websites. But think intranet applications, online trading platforms or webmails, or mobile web apps.

So ActiveX (or its offspring) in the browser is apparently back :-)

On a positive note, as I watch the assemblies load, Angular sites with 50k or so npm packages doesn't seem so heavy :-)

ActiveX has never left IE (not Edge). Although Microsoft patches have broken it a few times. So you can run Winforms in the browser on a full Microsoft supported stack for the time being.

Something I've wondered about with Web Assembly applications is, how do I actually view the web assembly/compiled blob? E.g--with normal Javascript, I can go to "sources" tab in developer tools and download all the JS, but how do I download the wasm?

Am I misunderstanding how web assembly works?

If you are using a fairly new version of chrome any wasm should indeed show up under sources, under a special wasm domain. It looks like this https://webassemblycode.com/wp-content/uploads/Chrome-Wasm-D...

It doesn't show the source file because the browser is not actually aware of where the js on the page got the wasm its running from. From the browser's perspective it just fetched an opaque file and then separately got told to run some wasm.

You can see the actual source file for the wasm for one of the demos here, it still shows up in the network tab (but for example if the js on the page generated the wasm then it wouldn't). https://webassembly.z19.web.core.windows.net/mono.wasm

You already cannot get anything usefull out from minified JavaScript.

It's there, if you look at the Network tab in the Dev Tools you will find the mono.wasm binary.

Am I the only one that reads "Watcom assembler" when I see WASM? :)

In any case, it's pretty insane what they do now but I sort of fail to see how W(eb) assembly is different from let's say a Java applet?

It is not native code is it?

That thing is glitchy as F. My machine used almost 1.5gb of ram running that thing. Couldn't barely drag the window or click any buttons, and froze my mouse cursor.

Does anyone have an example/list of popular applications that use .NET WinForms? The only ones I can think of are bespoke...

I wonder at what point Apple is going to add wasm-support to iOS.

It’s starting to feel quite left behind at this point.

I think you may well be wrong. Safari supports wasm. Here is an example for everyone who is reading this from an iOS device. https://suy.io/geopattern/

Sooo, unity webgl may not work on iOS but that doesn’t mean wasm itself doesn’t work.

Just tested, and this demo runs fine on iOS. It's kind of funny to use a classic Windows-style interface on a touchscreen. Loading time needs work, though.

Might be a ram thing. I tested on my iPhone SE and even while waiting a long time, it didn't seem to provide any visible results.

Edit: Trying it in Firefox desktop it fails too[1], so obviously this is not really fully cross-browser compatible yet.

[1] RangeError: bad Memory initial size mono.js:1181:26

<anonymous> https://webassembly.z19.web.core.windows.net/Calculator/mono...

Makes sense. According to other comments in the thread [1] the page requests a wasm heap of 1.25 GB (...hopefully unnecessarily!), while the iPhone SE has 2GB of RAM total, so it's easy to imagine that the remaining amount isn't enough for both other allocations in Safari and other processes. I tested it on my iPhone X which has 3GB of RAM – not that much more, but apparently enough.

[1] https://news.ycombinator.com/item?id=18983109

> the page requests a wasm heap of 1.25 GB

Par for the course in the "modern Web"

Well now this was an unexpected early UI API for Web Assembly.

Why does it look like Windows 95?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact