Scott Hanselman

Space Cadet Pinball for Windows 95 recompiled for Linux running on Windows 11 as a Linux app under WSLg

October 18, 2021 Comment on this post [15] Posted in Linux | Win11
Sponsored By

Award for longest blog post title ever? Andrey Muzychenko has a great github repository where they decompiled the 25 year old Space Cadet Pinball application from Windows 95/XP and then recompiled it for Linux (and really any platform now that it's portable code!).

NOTE: Because this is a decompilation/recompilation, it doesn't include the original data files. You'll need those from a Windows XP disk or ISO that you'll need to find yourself.

I recently did a YouTube where I showed that Windows 11 runs Graphical Linux Apps out of the box with WSLg.

Here, they've taken a Windows 95 32-bit app and decompiled it from the original EXE, done some nice cleanup, and now it can be recompiled to other targets like Linux.

So, could I go Windows 95 -> Linux -> Windows 11 -> WSL -> WSLg and run this new native Linux executable again on Windows?

If you don't think this is cool, that's a bummer. It's an example of how powerful (and fun) virtualization has become on modern systems!

Pinball under Linux under Windows 11

I just launched WSL (Ubuntu) and installed a few things to compile the code:

sudo apt-get install libsdl2-image-dev
sudo apt-get install libsdl2-mixer-dev
sudo apt install gcc clang build-essential cmake

Then I cloned the repo under WSL and built. It builds into bin and creates a Linux executable.

NOTE: Place compiled executable into a folder containing original game resources (not included).

I am a digital hoarder so I have digital copies of basically everything I've worked on for the last 30 years. I happened to have a Windows XP virtual disk drive from a VM from years ago that was saved on my Synology.

Virtual hard drive from Windows XP

I was able to open it and get all the original resources and wav files.

Pinball resources

Then I copy all the original resources minus the .exe and then run the newly built Linux version...and it magically pops out and runs on Windows...as a graphical Linux app.

3D Pinball for Windows

Amazing! Have fun!


Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service

Dotnet could not execute because the application was not found or a compatible .NET SDK is not installed

October 07, 2021 Comment on this post [0] Posted in DotNetCore
Sponsored By

I ran into this interesting issue where my System PATH environment variables got out of order. I ran "dotnet --version" and saw an error I'd not seen before. Dotnet "Could not execute because the application was not found or a compatible .NET SDK is not installed." What's that?

How did I diagnose this?

dotnet can't run because the application was not found

From the command prompt, I typed "where dotnet" to ask cmd.exe "which dotnet.exe are you offering me and in what order?" You would use the which command in Linux, the where command in DOS, and the more explicit where.exe dotnet on PowerShell.

Here I can see that Program Files (x86) has a dotnet.exe that is FIRST in the Path before the x64 version I expected.

Digging into GitHub I can see that the bug has been fixed but it's good to know how things get into a weird state and how easy it is to fix. In this case, I just swapped (or removed) the x86 and x64 (native architecture) paths in my System PATH via the environment variables UI in Windows. Just type Start and Environment Variables, click it, and then Double Click (or Edit) the PATH variable for a nice UI experience. You can even "move up and move down" within that UI - far nicer than editing a text file.

This can happen when you install a 32-bit .NET SDK on a 64-bit system and the last one in wins. In my case, I don't need a 32-bit host at all in my PATH so I ended up just removing it from my PATH completely.

Hope this helps you if you hit it and glad it's fixed.


Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service

Shrink your WSL2 Virtual Disks and Docker Images and Reclaim Disk Space

October 05, 2021 Comment on this post [8] Posted in Docker | Linux
Sponsored By

Docker Desktop for Windows uses WSL to manage all your images and container files and keeps them in a private virtual hard drive (VHDX) called ext4.vhdx.

It's usually in C:\Users\YOURNAME\AppData\Local\Docker\wsl\data and you can often reclaim some of the space if you've cleaned up (pruned your images, etc) with Optimize-Vhd under an administrator PowerShell shell/prompt.

You'll need to stop Docker Desktop by right clicking on its tray icon and choosing Quit Docker Desktop. Once it's stopped, you'll want to stop all running WSL2 instances with wsl --shutdown

Mine was 47gigs as I use Docker A LOT so when I optimize it from admin PowerShell from the wsl\data folder

optimize-vhd -Path .\ext4.vhdx -Mode full

...it is now 2 gigs smaller. That's nice, but it's not a massive improvement. I can run docker images and see that many are out of date or old. If I'm not using Kubernetes I can turn it off and delete those containers as well from the Docker settings UI.

I'll run docker system prune -a to AGRESSIVELY tidy up. Read about these commands before your try yourself. -a means all unused images, not just dangling ones. Don't delete anything you love or care about. If you're worried, docker system is safer without the -a.

Now my Docker WSL 2 VHD is 15 gigs smaller! Learn more about WSL, Windows 11, and WSLg on my latest YouTube!

NOTE: You can now get WSL from the Windows Store! Go get it here and then run "wsl --install" at your command line.

If you want, you can also go find your Ubuntu and other WSL disks and Compact them as well. I only think about this once or twice a year, so don't consider this a major cleanup thing unless you're really tight on space.

Ubuntu WSL disks will be in folders with names like

C:\Users\scott\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc\LocalState

or

C:\Users\scott\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04onWindows_79rhkp1fndgsc\LocalState

But you will want to look around for yours. Again, back things up and make sure WSL is shutdown first!

Enjoy! REMEMBER - Be sure to back things up before you run commands as admin from some random person's blog. Have a plan.


Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service

ASP.NET Core Diagnostic Scenarios

September 30, 2021 Comment on this post [2] Posted in ASP.NET | DotNetCore | Open Source
Sponsored By

ThreadingDavid and friends has a great repository filled with examples of "broken patterns" in ASP.NET Core applications. It's a fantastic learning resource with both markdown and code that covers a number of common areas when writing scalable services in ASP.NET Core. Some of the guidance is general purpose but is explained through the lens of writing web services.

Here's a few great DON'T and DO examples, but be sure to Star the repo and check it out for yourself! This is somewhat advanced stuff but if you are doing high output low latency web services AT SCALE these tips will make a huge difference when you're doing a something a hundred thousand time a second!

DON'T - This example uses the legacy WebClient to make a synchronous HTTP request.

public string DoSomethingAsync()
{
var client = new WebClient();
return client.DownloadString(http://www.google.com);
}

DO - This example uses an HttpClient to asynchronously make an HTTP request.

static readonly HttpClient client = new HttpClient();

public Task<string> DoSomethingAsync()
{
return client.GetStringAsync("http://www.google.com");
}

Here's a list of ASP.NET Core Guidance. This one is fascinating. ASP.NET Core doesn't buffer responses which allows it to be VERY scalable. Massively so. As such you do need to be aware that things need to happen in a certain order - Headers come before Body, etc so you want to avoid adding headers after the HttpResponse has started.

DON'T - Add headers once you've started sending the body.

app.Use(async (next, context) =>
{
await context.Response.WriteAsync("Hello ");

await next();

// This may fail if next() already wrote to the response
context.Response.Headers["test"] = "value";
});

DO - Either check if it's started before you send the headers:

app.Use(async (next, context) =>
{
await context.Response.WriteAsync("Hello ");

await next();

// Check if the response has already started before adding header and writing
if (!context.Response.HasStarted)
{
context.Response.Headers["test"] = "value";
}
});

Or even BETTER, add the headers on the OnStarting call back to guarantee they are getting set.

app.Use(async (next, context) =>
{
// Wire up the callback that will fire just before the response headers are sent to the client.
context.Response.OnStarting(() =>
{
context.Response.Headers["test"] = "value";
return Task.CompletedTask;
});

await next();
});

There's a ton of great guidance around async programming. If you are returning something small or trivial, like a simple value, DON'T Task<>:

public class MyLibrary
{
public Task<int> AddAsync(int a, int b)
{
return Task.Run(() => a + b);
}
}

DO use ValueTask<> as this example not only doesn't use an extra threads and avoids heap allocation entirely:

public class MyLibrary
{
public ValueTask<int> AddAsync(int a, int b)
{
return new ValueTask<int>(a + b);
}
}

There's a ton of good learning over there so go check it out! https://github.com/davidfowl/AspNetCoreDiagnosticScenarios


Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service

Differences between Hashtable vs Dictonary vs ConcurrentDictionary vs ImmutableDictionary

September 28, 2021 Comment on this post [9] Posted in DotNetCore | Musings
Sponsored By

DictionariesI'm very much enjoying David Fowler's tweets, and since he doesn't have a blog, I will continue to share and expand on his wisdom so that it might reach a larger audience.

He had a conversation with Stephen Toub where Stephen points out that ".NET has 4 built-in dictionary/map types [and] there’s no guidance on when to use what, mostly individual documentation on each implementation."

  • Hashtable
  • Dictionary
  • ConcurrentDictionary
  • ImmutableDictionary

There is actually some good documentation on C# Collections and Data Structures here that we can compare and combine with Stephen Toub's good advice (via David) as well!

There are two main types of collections; generic collections and non-generic collections. Generic collections are type-safe at compile time. Because of this, generic collections typically offer better performance.

Definitely important to remember. Generics have been around since .NET Framework 2.0 around 15 years ago so this is a good reason to consider avoiding Hashtable and using Dictionary<> instead. Hashtable is weakly typed and while it allows you to have keys that map to different kinds of objects which may seem attractive at first, you'll need to "box" the objects up and boxing and unboxing is expensive. You'll almost always want to use Dictionary instead.

If you're accessing your collection across threads, consider the System.Collections.Concurrent namespace or using System.Collections.Immutable which is thread-safe because you'll always be working on a copy as the original collection is immutable (not modifiable).

David says this about

  • ConcurrentDictionary - "Good read speed even in the face of concurrency, but it’s a heavyweight object to create and slower to update."

Or perhaps

  • Dictionary with lock - "Poor read speed, lightweight to create and medium update speed."
  • Dictionary as immutable object - "best read speed and lightweight to create but heavy update. Copy and modify on mutation e.g. new Dictionary(old).Add(key, value)"
  • Hashtable - "Good read speed (no lock required), same-ish weight as dictionary but more expensive to mutate and no generics!"
  • ImmutableDictionary - "Poorish read speed, no locking required but more allocations require to update than a dictionary."

Another one that isn't often used but I'll add as it's good to know about is

  • KeyedCollection - Generic and ordered. Uses Dictionary and List underneath

This is great advice from David:

Use the most obvious one until it bites you. Most software engineering is like this.

Measure and test, measure and test. Good luck to you!


Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.