Behind the scenes of an indie Windows application.
The last time that I published a Windows application, it was ages ago. So, when a few months ago I decided to develop and publish my product I had to learn and decide everything again.
Here’s my journey from the idea to publishing. Not a step to step tutorial but a journal about decisions and pitfalls.
Well, I’m a productivity geek, and you can bet that I’m never satisfied with the productivity tools. I’ve tried so many of them that at some point I lost faith in finding the chosen one.
I won’t annoy you about what I was searching for. Suffice to say that I wanted a hierarchical logic, compact but informative cards and views, easy integration with the file system, and more. Replace these requirements with the app you have in mind.
Also, while the cloud is a great place to be, I missed Windows. And Windows can be an alternative. You own the database, you (usually) don’t pay subscriptions, you don’t depend on the Internet connection or third-party servers, no web latency, and so on.
The Windows offer for task managers is not crowded. Okay, there are reasons for that, but I wanted my Windows app.
So, like thousands of indie projects start, mine started from my own needs.
And my being a Microsoft freak. Which indeed had a role in seeing opportunities in a Windows app.
At the beginning, a product was not in my mind, at least not in the foreground. I just wanted a custom tool and to experiment.
So, a couple of years ago I started playing with a prototype based on Windows Forms, connected with Evernote. Evernote was the database, and Windows Forms handled logic and UX. I could have an enhanced interface, but also use Evernote on the go.
Not good. Terribly slow and Evernote APIs are too limited for the purpose.
So, I soon switched to another project, still Windows Forms, but without Evernote. Or, better, with Evernote integration but based on the SQL Server Compact database.
That worked much better, and I actually started to use it.
But at some point, I hit two main limits.
Windows Forms too are slow and limited. While I’ve successfully used them in many projects in the past, its interface doesn’t scale well, and I now needed good reactivity with a dynamic layout. I was using Windows Forms just because I knew them well, and I didn’t have much experience with Windows Presentation Foundation (WPF).
Also, the indie developer in me had started to think about a product, and needed more. Too late to stop him.
So, I had to start from scratch and, instead of a custom tool, I had to design a product.
A few months ago I restarted from scratch and had to decide where to go, according to the perspective of a product.
The requirements part was clear to me, and I also had a sufficient idea of what the MVP (Minimum Viable Product) should be.
So, I went straight to the next decision: the technology.
Windows Forms were not an option. I’ve loved them but, apart from their limits, they had been put on life support a long time ago.
UWP (Universal Windows Platform) didn’t (and doesn’t) seem that mature — and maybe even already dead in its pure form — apart from its being confined to Windows 10 and some limited multiplatform. Is it the future? It seems so, but it will take long, and Windows 7 users are still a big crowd. Meanwhile I’ve still nightmares about Metro interface waving in and out my desktop and my old Windows Phones collecting dust.
UWP has the advantage of the Microsoft Store, and touch support. But… Microsoft Store doesn’t seem that popular. And, since my app is primarily intended for the desktop, I’ve seen very few people tapping on the touch screen of their laptop.
No, I’m not going to follow the UWP road until a significant change in the panorama, which I bet won’t happen anytime soon.
WPF is the Purgatory. But a pretty large and durable Purgatory, as it often happens, with Microsoft.
WPF is an excellent and modern technology. While Microsoft is already headed away, WPF is mature, and people will keep wanting traditional desktop apps for many, many years to come.
WPF with .NET 4.6.1 and Entity Framework 6 (EF6), in C#. The prototypes were in Visual Basic, language that I’ve used since its origins, but it definitely was time to switch to C#.
Why not .NET Core? Because it’s too early. WPF is not supported by the current .NET Core 2.
Ready, set, go!
In September 2018 I started rewriting XPlan from scratch.
It took me a few weeks to adapt to the WPF approach and XAML but, once I did, it felt like Paradise. The full power of .NET with a declarative user interface design.
It’s been easier to adapt to EF, even if I’m still not a fan of it. Having designed my own ORM (object-relational mapping) .NET tool in the past, using EF makes me feels like I’m not in control of too many details, especially when something goes wrong. Anyway, once you get accustomed to a few idiosyncrasies, and to LINQ, it works like a charm.
Apart from Visual Studio and .NET, you can guess that a lot was on the table, even if the application had a relatively small scope. User interface, logic, licensing, upgrades, documentation, website, sales, etc.
I wished it could be possible to put the app on sale by the end of the year, but the target soon switched to the end of February 2019, which anyway meant to have the app ready by January, at least.
Microsoft has a peculiar approach to surprises. They get you used to have state-of-art dev tools with whistles and bells, and when you’re off-guard, they place the surprise. Maybe it’s a coaching tactic to keep you alert.
When I was starting to be satisfied with my app and started to think about finalizing, the surprise popped up.
In previous decades, the default database for desktop apps had always usually been Access. SQL Server Compact (.sdf) was an option, which I never used.
With the prototypes of my app, seen the full support of Visual Studio to mdf files (SQL Server), I instantly switched to that. I wanted the option to scale up. Using the same file format for the desktop app and, in future, for a client-server setup was indeed an advantage.
Anyway. I thought that the database was a minor matter and that I could refine the choice later. SQL Compact or something, the local database had never been a problem.
How was I wrong.
My bad, mdf files cannot be managed by the executable. They need an engine anyway. And SQL Server (Express version included) is the engine. During the development period, a LocalDb instance (a vanilla version of SQL Server Express) was silently there.
It turned out that Microsoft forgot years ago that file-based databases are needed.
Access is not supported by Entity Framework. Yes, Microsoft does not support its own popular database with its own recommend ORM. There are workarounds, but they are… well, workarounds.
SQL Compact is (was) perfect for desktop apps. Private install, no admin privileges required, password protection. But… it’s stone dead. As of February 2013, it’s been deprecated.
So, we’re only left with SQL Server Express, which is not file-based and comes with a separate engine. But… Windows 7 and x86 are not supported by SQL Server Express 2017! Also, SQL Server needs a separate setup, with admin permissions, which is not exactly what you hope for customer experience. Not a unique setup, not a single sale, in my case.
Well, for the problem of compatibility with Windows 7 you can think that installing a previous version of SQL Server can solve but… it can’t use the database file you’ve designed because Visual Studio 2017 automatically upgrades the mdf file to its latest version and no backward compatibility nor tool is there. So, you are obliged to use an old SQL Server instance outside Visual Studio for the database design and be careful never to let Visual Studio upgrade it.
What is that, a trap for developers, to keep them and their customers on the latest version of everything?
For the separate setup issue there seemed to be hope in LocalDb, the only remaining option, once Access and SQL Compact are gone.
But LocalDb still needs admin rights. So, forget customers with no admin rights. And it’s still not file-based, so no embedded security.
Also, it comes with a msi but… you can’t run a msi from another msi, so you also can’t use a distribution project for your app.
Of course, there are options outside the Microsoft territory, but none of them convince me. For example, the popular SQLite doesn’t allow you to drop columns or add constraints (maybe schema upgrades became an old-style practice while I was away?).
Anyway, it’s pretty weird that you have everything you need for desktop development, in Visual Studio, and the most basic need of most desktop apps — a file-based database — is not there.
I spent days on that dilemma, for which Microsoft has no straightforward and complete solutions.
I decided to stay with SQL Server Express — LocalDb version — and accepted to renounce to customers without admin permissions, and to encryption, at least in the first period. Sigh.
Also, some ugly workarounds had to be put in place: detect possible previous SQL Server installations, detect which engine to install depending on the operating system and the hardware platform, prompt the user for the extra setup, distribute the extra setup. I included two LocalDb versions (more than 100Mb) in my app setup and then run the DB engine setup at the first run of the application, but it’s not an ideal scenario. I’ll refine it in future with automatic download options to limit the setup size, at least.
More about the problem and the solution here:
That surprise was hard take, especially for an app intended for customers, and with the little time at my disposal. But I had to take the blow and step ahead.
Microsoft, really a bad slip on that.
There’s plenty of solutions for license management. But they usually cost a lot and need some kind of integration with your e-commerce and user management.
I didn’t want to spend much and to depend on third-party technologies for that.
Also, I didn’t want my customers to depend on a website to reinstall their program, sending installation codes to have a key back. I wanted to give them their key, valid for any reinstallation. It’s a risk, of course. But I can black-list pirates in the upgrades (and even change the logic with major upgrades), and an unpopular app is unlikely to be cracked. Reasonable risks for offering honest customers to own their license.
Of course, I had to implement the solution. I had some experience, but the whole thing took more than a couple of weeks. You have to design the key format (which has, of course, to be scrambled/encrypted), the key generation, the protection system (manage expiration or other limitations), and so on. Key will be provided by email. No website automation for now.
Another important item of the to-do list is automatic upgrades.
The concept can be simple. Periodically check your website (tip: HttpWebRequest.GetResponse().GetResponseStream()) for an upgrade (maybe just a txt file with the data of the latest release), prompt the user, download, install.
But I opted for the long road.
I have an xml file on the website with the history metadata. The app downloads that file and scans it checking for upgrades, distinguishing recommended or just optional upgrades. That way the app is also able to prompt the user with all the cumulative changes from the installed version to the possible upgrade. The user can accept, skip the upgrade, be prompted later, or decide to run the upgrade check later manually.
When an upgrade is there, the user can decide for the download. Once downloaded, on the restart, the app prompts for the install. If confirmed, the app runs a separate launcher (simple exe that will run the setup), and closes.
During a limited beta testing, another issue popped up. The antivirus.
It can block the download. I still have no statistics but it’s certainly a significant problem.
They’ll tell you that you just need to sign your app with a certificate, but it’s not that simple, and far from free. At the bare minimum, you have to sign (the exe and the setup) with a certificate and add a timestamp (to avoid the effects of the certificate expiry).
So, I postponed solving this issue — unless it becomes blocking — but I guess I have to address that soon.
A similar but minor issue is the firewall warning the user that the app is contacting the website (for the upgrades).
Finally, there’s the sales thing.
I decided for a one-time license, to limit complexity. A single payment with all minor future upgrades included.
For e-commerce, a lot of possible platforms are already there, of course at some cost, but I wanted to start with my own platform to have full control.
Since the first version of the website is a WordPress setup, I opted for the popular and mature WooCommerce.
For payments, there are various possibilities, but I opted to begin with PayPal, handled by WooCommerce. I had already successfully used PayPal in the past. I can add other payment channels later.
For the regulatory and accounting matters you certainly need some advice, but the mandatory aspects (privacy certainly being the one which needs most attention) usually boils down to a few things, especially if what you have in your hands to start with is a microbusiness or no business at all. An annoying part, but maybe you don’t need to overcomplicate at the beginning.
By the beginning of March 2019, XPlan was on sale.
Not all of what I had in mind as a minimum was there, but a good and solid part was. The cornerstone to build on is there.
However, I’ve done little promotion before, except a landing page and a newsletter that very few subscribed, so nobody knows about the app. Everything has to be done, and I guess that link building is step one (yes, this article is part of it).
Anyway, selling is a different story. And you can bet that for an indie application it’s the hardest part.