Solving the Worst Problem in Programming Education: Windows
Solving the Worst Problem in Programming Education: Windows
Over the years I've tried my best to support Microsoft Windows in my courses because 95% of the world uses Windows. If I want everyone to take my courses then I have to support the operating system that everyone uses. It'd also be ridiculous to tell someone they need to spend $2000 USD on a Mac just to learn to code. Windows is a fully functioning Operating System just like Linux or macOS, so it should be completely reasonable to support everyone who uses it.
The problem you encounter on Windows (and to some degree macOS) is Microsoft heavily prioritizes their Visual Studio system for all programming tasks, so if you want to use something outside that world you're in for quite a bit of obnoxious friction. If you want to code C# or C++ desktop apps for Windows then Visual Studio is the way to go. If you want to learn Python, Rust, Go, JavaScript, C, or many, many other languages it's a slog.
The question is then, why fight Microsoft? Just tell people to use Visual Studio? Because even though the world of non-programmers uses Windows, the world of programmers decidedly do not use Windows. I think if you were to analyze what people use in the vast world of startups, corporations, open source projects, and other places you'd find it's inverted with 95% of programmers not using Windows. Even Microsoft had to admit defeat on this and start supporting Linux in Windows.
This means, if I want to create independent programmers who aren't beholden to any company for their future, then I have to teach them how to use tools outside of the Microsoft platform, but I still need to support people on that platform until they choose to use something else (or not).
There's a secondary practical reason for my own courses: It's easier to support. If I tell people to install Visual Studio I'll then have to create 2 sets of instructions. One set for Linux and macOS people, then another completely different set of instructions for Windows people. In addition to that the instructions for Windows will require screenshots or convoluted videos showing people where to click on stuff.
That means, I need to help people who use Windows get a setup that is more like a Linux and macOS "traditional" configuration. Then they'll be able to use the OS they already have to learn "classical style" programming without spending extra money. This helps students explore more programming languages and platforms so they don't become a slave to the whims of Microsoft.
Past Attempts
In my previous instructions I've had to rely on lists of links to installers. I'd give a list of things to install, tell them to install each one, then have a big test to confirm everything installed. No matter what I did there was always about 30% of people where the instructions wouldn't work. Either that person was on Windows Home vs. Windows Pro or accidentally ran cmd.exe
instead of PowerShell
or had an Anti-Virus running that blocked something. It was always some weird thing I could only figure out with hands on help over chat or emails.
Here's just a few of the problems I've ran into with this approach:
- The official Python Installer The guy who works on this is employed by Microsoft so big surprise it refuses to add Python to the PATH.
- Anaconda For some reason the people who created the Anaconda installer believe the lie that adding Python to the PATH will "destroy the computer." Yeah? Then why does the Python in the Microsoft store add itself to the PATH?
- Cmder I got fed up with these idiots after they seemed to purposefully sabotage PowerShell by adding the
-NoProfile
option by default which kills many tools that need to alter the PowerShell environment. It took me an entire year to find this stupid bug. - Notepad++ This guy thinks his text editor is a political statement rather than just a damn text editor, which makes him hard to trust even if I agree with most of his views. I can't have some wannabe activist deciding to erase all my students' computers because they happen to live in the wrong state or country.
Each of these have caused me weeks, months, or years of support problems because of their stupid decisions. It's so bad I had to create a special page just for the Python print book that I can update with install instructions when things go wrong.
What I Really Want
After years of this total bullshit I decided to sit down and design a solution. The basic features I wanted are:
- An automated meta-install system that can install the required software for each course.
- One that will update this software when there's updates.
- It should be able to install software that's outside of Microsoft's control.
- The final result should be a developer environment that's similar to a classic Unix environment. That means there's a command line terminal and tools.
- Since this is Windows it should setup a basic graphical programmer's editor that's keyboard/mouse friendly.
- It shouldn't exclude people who want to use other tools, so if someone really likes Visual Studio Code then they can use that and still use the installed developer environment.
- Finally, an ability to update these installers quickly to help people remove rogue projects. I call this "The Notepad++ Rule." If a project realizes I'm driving traffic to them and decides to screw over my users I will rat them out to my users and provide a script to violently eject them from our existence...if the user wants that.
I started working on this plan a few months back, taking a look at winget and choco which both work but had a couple of annoying things that didn't make them optimal. With winget
or choco
I'd mostly be replacing a list of links to installers with a list of installer commands to run. It wouldn't really reduce the complexity of getting started by much so I was stuck.
Enter Chris Titus' WinUtil
What do you call someone who speaks 3 languages? Trilingual
How about 2 languages? Bilingual
And 1 language? An American.
I'm a big critic of Youtube being trash at introducing people to new things, but one day I'm watching Youtube on my TV and up pops Chris Titus' WinUtil. I don't even know how they figured out I was interested in something like this. You may think it's because of my search history but keep in mind my TV isn't logged into any account, and usually I get ads in Spanish and Hindi when I never watch anything in those languages. Yet randomly Youtube shows me one of Chris's videos and his winutil
looked like almost exactly what I needed.
What winutil
does is use PowerShell to create a nice GUI meta-installer. It uses a mix of choco
and winget
to install the various software packages you select, as well as provide a bunch of tweaks for Windows. You can also use it to craft minimalist ISO installers, prevent tracking, turn off features, and many other things. Its list of packages are also a good list of possibly improved tools for your Windows experience. Best of all, it was just a straight forward PowerShell script you can install with just this:
irm "https://christitus.com/win" | iex
Now THAT is the experience I'm looking for, and actually I don't even want his GUI. It's nice, but what I really want is a couple of commands and someone gets a simplified standard dev environment. Thankfully, Chris was nice enough to release his project MIT so I could investigate how he's doing this and possibly steal some his code.
Borrowing from WinUtil
After learning enough PowerShell to be deadlier than ebola in a kindergarten I was able to fork Chris' WinUtil a bit to create my own installer. The only thing I stole from WinUtil is the initial setup of winget
and choco
. I did have to add an additional feature to reduce the amount of Administrator
usage since I need to keep people safe who use it. If you view the modified base.ps1 script you'll see I'm doing two things:
- From Chris' script I use the checking for
winget
andchoco
and the installation of those in theInstall-WinUtilWinget
function. - However, I have a small chunk of code that checks if you are running as
Administrator
and if you're not (which you should not be) it re-launches itself to perform theInstall-WinUtilWinget
function asAdministrator
. - This is one part that must be run as
Administrator
and after that all other installs can be done as a normal user. Any installers that do needAdministrator
rights will properly ask for anAdministrator
password. - The other place that needs to be
Administrator
is at the end whenchoco
is first run to install a few more tools, but I'd like to reduce that as well.
Now when you run this base.ps1
script it'll automatically get you a base install going with a bare minimum programming environment that's ready for other languages. See the Project README.md for a list of what's installed or look at the end of the script.
Composible Language Installers
The next thing I wanted was an ability for someone to get a basic setup going via the base.ps1
but then install as many different languages as they need. To accomplish this I created one .ps1
script for each language. These scripts simply confirm that winget
and choco
is installed (and therefore you probably ran the base.ps1
) before then installing packages that create a simple developer experience for that language.
For example, the cpp.ps1 just needs to install conan
and meson
since winlibs
is installed by base.ps1
, but I go ahead and install winlibs
again just to be sure it's there. This works because choco
and winget
are idempotent, meaning they'll only install the package once, or update it if there's a new one.
Another example is rust.ps1 which only installs the 'Rustlang.Rust.GNU' package to get the base rust
compiler package that works with winlibs
.
Or, the python.ps1 script that installs Anaconda and the Microsoft Python from the Microsoft Store because everyone working on Python is a bought and paid for grifter for Microsoft these days, and fighting that is too hard for a little guy like me.
As of this writing I have installers for the following language environments (in Alphabetical order since people seem to be deeply attached to grifting for their favorite language to win some contest):
The project repository has lists of everything that's installed in each script, and I have people save the file so you can view what gets installed and modify it if they want.
How It Works
Let's say you want to install Python and Go. First, you install the base.ps1
package like so:
irm https://learncodethehardway.com/setup/base.ps1 -outfile base.ps1
powershell -executionpolicy bypass .\base.ps1
Then you repeat the process with python.ps1
:
irm https://learncodethehardway.com/setup/python.ps1 -outfile python.ps1
powershell -executionpolicy bypass .\python.ps1
And finally you do it again for go.ps1
:
irm https://learncodethehardway.com/setup/go.ps1 -outfile go.ps1
powershell -executionpolicy bypass .\go.ps1
That's it. You'll need to be at your computer to enter an Administrator
user's password, but other than that it should install most of the things you need. I also recommend you take a look at the bottom of these scripts and confirm it's installing what you want. I also list all of the projects these install on the project README.md and give alternative commands you can run instead of running the scripts.
How It's Tested
Finally, the way I'm testing this is with the bigtest.ps1 script. I run this test like this:
- I fire up a base Windows Home install that has no packages installed yet.
- I then use the above install process to run
base.ps1
and get an initial config working. - Next I run
bigtest.ps1
using the same process and just wait to enter in all the passwords manually until it's done.
I'd like to fully automate this process if I can, but that's a task for another day. I'd also like to automatically download a project for each language to confirm that the language's installs are working as expected. For example, grab a simple rust
project and try to build it.
Please Steal These
The project is MIT licensed and hosted on my git repository. I've also included Chris's license for the pieces of his code I used, which he also MIT licensed.
If you're working on a programming language I highly recommend you take a look at these scripts and adapt them to your language. They solve a ton of problems since the base.ps1
script sets up most everything you need for basic C/C++ compilation. If you take that you can extend it to add any additional packages you need for your language, run compilation steps, and more easily support Windows.
As I've already said, 95% of the world uses Windows. If you want your language to grow then making it easy to install on Windows will help. In the past Windows had bizarre APIs but these days it's fairly normalized given how Microsoft has gone full open source to extract free labor out of the same programmers they used to insult on a daily basis.
C'mon! It'll be fun. I promise.
Report Bugs
You can email me at help@learncodethehardway.com to report bugs or bother me on Twitter @lzsthw. If you have a language you'd like me to include then email me the script. I'll take a look and try to include it if I can, and even if I'm not planning on teaching that language. I want these installers to simply bring more alternatives to Windows and to keep the "classical programming" style alive.
Thank you for your time.
More from Learn Code the Hard Way
Rogue is the Best Project
My pitch for Rogue being the best for both beginners and old crusty coders like me.
Very Deep Not Boring Beginner Projects
A list of projects that anyone with basic programming knowledge can do in any language, but have a lot of depth and aren't boring to do.
C++ Is An Absolute Blast
Where I try to explain why I feel like C\+\+ is so much fun, and to correct some misinformation.
Just Use MSYS2 You Say?
Debunking idiots on HackerNews who think a total beginner can just 'Use MSYS2' on Windows.