Scott Hanselman

Reviewing the Elecrow CrowPi2 Raspberry Pi Laptop and STEM Education Platform

August 6, '20 Comments [0] Posted in Hardware
Sponsored By

11540c45729eb73fd9676faf6b05914c_originalI love the Raspberry Pi and I am a fan of the CrowPi from Elecrow. I have two of their first CrowPi device and I use them in demonstrations and talks all the time, especially when talking to students.

They have a Kickstarter ending this week for the new CrowPi2. It's an update of the original CrowPi which was basically a Raspberry Pi in a tiny suitcase...instead the CrowPi2 looks like a laptop! The magical part is that the full exploration and sensor board is hidden underneath a wireless keyboard with trackpad, held on with magnets!

The CrowPi folks sent me an early CrowPi2 because I was a vocal supporter of the previous version, so I did a LIVE video unboxing on twitter as well as a follow up software video on the CrowPi2. I am not being paid for this review and I always am honest with y'all about the stuff I like. I plan on buying a few for my kids' public school science class.

This blog post in Chromium on a Raspberry Pi CrowPi2

It's more than "just a laptop shaped case" for the Raspberry Pi, the CrowPi2 has an integrated 1080p screen, 22 onboard sensors (that can be connected and disconnected with a switch), a microphone and 2MP webcam, speaker, as well as support for both 5v battery and 12v external power.

The keyboard is also quiet clever and very thin. It's held on with magnets and is charged with any micro-USB connector. Hidden underneath is an upgrade of the original CrowPi sensor board!

Sensors hidden under the keyboard

Here's a close up of the sensor board:

20+ Sensors on the CrowPi2

The part I was the most surprised with was that there's 20+ projects already setup out of the box. I usually get a device like this and maybe there's some sample code on the desktop that you can run with Python. The CrowPi2 is more polished in that it has a whole front-end introductory UI that lets you run the samples right away - and they are cool samples! I show a few of the LIVE samples in my Video on Twitter.

The plastic in the early version I got is a little soft, and I might have preferred it in black versus silver, but it's light and drops in a backpack easily. It's somewhat thick (remember this is a Raspberry PI, not an iPad or a millimeter thin laptop) so to be conscious if you think you're getting an Ultrabook. This is a Raspberry Pi-based laptop and learning platform. Would be a great starter for any kid as the Pi4 is pretty legit and it'll even run Chromium!

NOTE: I did try to join a Zoom web-based meeting over Chromium and while the speaker and mic were detected, I wasn't able to get Chromium to see the webcam. I'll report back on this as clearly all the parts are there to allow this little laptop to join at least a web Zoom meeting! That would be even cooler.

UPDATE! I was able to enter a web-based Zoom meeting! There's a little USB cable underneath that snakes out then in again to allow access to the webcam. Very clever! I don't think this is a reliable option for Zoom meetings, but I can confirm that the webcam works!

IMG_5022

Here's a side view of the CrowPi2, as well as how the Raspberry Pi mounts inside.

CrowPi2 from the Side

Raspberry Pi mounted inside

There is even a cool little retractable tray in the back of the CrowPi2 that you can use for a battery (with a micro-USB cable you can run the entire device) or for holding wires, LEDs, and resisters for projects.

Cool tray in the back of the CrowPi2

The real magic is the sample projects - they are quite cool. They've added AI and Machine Learning lessons with Thonny PI, loaded MineCraft Pi. There are games, sensor tests, and they basically exercise the whole main sensor board with Python.

NOTE: I've also installed .NET Core on Raspberry Pi and it works great since it's an ARM Machine. You can even run Docker!

The basic kit is very reasonably priced compared to the much more barebones kits you see on Amazon. While I wouldn't call it a "premium" kit due to the plastic case, it's definitely the best Raspberry Pi kit I've ever used.

Playing Games on the CrowPi

You can go support the new CrowPi2 over on their KickStarter ending this week, it's pretty darn cool.


Sponsor: Bug in prod? Get to the bottom of it, fast, with live production log search in Seq 2020.1.

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

THE EASY WAY how to SSH into Bash and WSL2 on Windows 10 from an external machine

August 4, '20 Comments [7] Posted in Linux | Open Source | Win10
Sponsored By

Some folks always trying to ice skate up hillThis is an interesting blog post on How to SSH into WSL2 on Windows 10 from an external machine. Read it. Know how it works. Learn it. AND DO NOT DO IT BECAUSE IT'S TOO COMPLEX.

DO NOT DO THIS. It's fine. It works. But it's baroque. You're forwarding ports into a little VM'ed local subnet, you're dealing with WSL2 IP addresses changing, you'll have to keep your VM running, and you're generally trying to ice skate up hill.

Here's the thing. In that post - which you should not do - you're turning off the Windows Firewall for your port, forwarding to an internal subnet, and then letting WSL take over.

BUT! Windows 10 already knows how to accept SSH connections. In fact, it's shipped OpenSSH as a "Feature on Demand" for years. The issue is that you (Mac and Linux switchers) don't like the default shell - PowerShell.

So why not change the default Windows shell for SSH to WSL2's Bash?

Boom. Now you have no port forwarding, firewalls are only opening for one process, and your WSL2 instance starts up on entry. Literally the best of all worlds.

How do you set up SSH'ing into WSL2 on your Windows 10 machine

First, open an admin PowerShell prompt (Start menu, type PowerShell, hold ctrl+shift, and hit enter) type this:

> Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'

Name : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

See how I have the Client and not the OpenSSH Server? Add it:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

Now either start the SSHD service, or set it to start automatically:

Start-Service sshd
Get-Service sshd

or automatic:

Set-Service -Name sshd -StartupType 'Automatic'

Configuring the Default Shell for OpenSSH in Windows 10

On my server (the Windows machine I'm SSHing into) I will set a registry key to set the default shell. In this case, I'll use open source cross platform PowerShell Core. You can use whatever makes you happy and WSL2's bash makes me happy.

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\WINDOWS\System32\bash.exe" -PropertyType String -Force

Note that bash.exe in this context starts up "wsl -d YOURDEFAULTDISTRO" so you'll want to know what your Default is, and if you don't like it, change it with wsl --set-default DISTRO.

HEADS UP: You need the FULL AND CORRECT PATH in that command above. It works for any shell. Since I'm using bash.exe, I get WSL2 starting up for free but SSH with this solution is using Windows's SSH keys and Windows auth. Note that when you're entering your password for authentication!

Even better if I wanted to add a menu item (profile) to one local Windows Terminal with an entry to ssh into my WSL on my remote Windows Machine that would automatically log me into it from elsewhere using public keys, I could do that also!

To conclude and sum up:

  • This blog post - the one you are reading uses Windows' OpenSSH and authenticates with Windows and then runs WSL2. WSL2 starts up, uses bash, and Windows handles the TCP traffic.
  • This other blog post - over here - has Windows only forwarding ports, and uses WSL2's Linux OpenSSH and authenticates against Linux. Windows is only involved peripherally. The WSL2 IP address changes on reboot and you'll need to maintain your portproxy rules and firewall rules with the script listened at the end of that post.

Understand what you want and use the right one for you.

Enjoy!


Sponsor: Bug in prod? Get to the bottom of it, fast, with live production log search in Seq 2020.1.

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

How to SSH into WSL2 on Windows 10 from an external machine

July 30, '20 Comments [3] Posted in Linux | Win10
Sponsored By

LinuxCool blog post eh? Good title, right?

DO NOT DO THE INSTRUCTIONS IN THIS POST

until you have read the FOLLOW UP THE EASY WAY how to SSH into Bash and WSL2 on Windows 10 from an external machine and made the right decision for YOU!

OpenSSH has shipped in Windows for 5 years now, so that's cool. You can do lots of things!

But often folks want to SSH not into their Windows 10 machine, but rather, into WSL2 running within/behind their Windows 10 machine. While WSL2 can forward ports from the inside out (for example, localhost:8000 within a WSL2 instance being made available from the local Windows 10 machine) if you want to build a path to a WSL2 port from completely outside a machine, you'll need to be a lot more explicit.

Install OpenSSH-Server in WSL

First, install OpenSSH server inside your Linux Distro:

scott@IRONHEART:~$ sudo apt install openssh-server
[sudo] password for scott:
Reading package lists... Done
Building dependency tree
Reading state information... Done
openssh-server is already the newest version (1:7.6p1-4ubuntu0.3).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Decide on your SSH port number

Next, in WSL2, edit /etc/ssh/sshd_config and uncomment out the Port line.

I edited it with sudo nano /etc/ssh/sshd_config, no shame!

SSH is usually 22, but I like to use something like 2222 so it's less obvious but still easy to remember AND is different from your Window's machine's 22. Note that I told it to listen on 0.0.0.0, so, any adapter. You can also set PasswordAuthentication to "no" if you want to use SSH keys rather than passwords for authentication. Set it to "yes" if you know what you're doing and don't know how to use ssh keys.

/etc/ssh/sshd_config

...STUFF ABOVE THIS...
Port 2222
#AddressFamily any
ListenAddress 0.0.0.0
#ListenAddress ::

...STUFF BELOW THIS...

From within WSL2 get your IP address using "ifconfig." Mine is 172.23.129.80, yours will likely be 172.SOMETHINGELSE and it will change when WSL2 starts up cold.

You may want to ensure it's running, considering WSL2 has no systemd.

service ssh start

Forward Ports into WSL2

Now, from an Administrator Windows prompt - that can be cmd.exe or powershell.exe, it doesn't matter, use the net shell "netsh" to add a portproxy rule. Again, change connectaddress to YOUR WSL2 ipaddress, which is an internal address to your machine.

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=2222 connectaddress=172.23.129.80 connectport=2222

Open the Firewall

Next, from the same Administrator Windows prompt, open an incoming Firewall Port. You can do it from the Advanced Firewall Settings, but even easier you can use netsh again!

netsh advfirewall firewall add rule name=”Open Port 2222 for WSL2” dir=in action=allow protocol=TCP localport=2222

You can list all your portproxy rules like this if you're concerned:

netsh interface portproxy show v4tov4

You can remove them all if you want with

netsh int portproxy reset all

A scripted solution?

GitHub user and community member Daehahn is working on a PowerShell Script to automate this process. The comment thread starts here and the gist for the PowerShell script for wsl2-network.ps1 is here. It resets firewall and portproxies, finds your default distro's new IP, and sets you up again. Save this .ps1 somewhere, read it, and run "unblock-file wsl2-network.ps1" on it so you can set up your system quickly for Shushing into your WSL2 instance!

Note the $Ports variable that likely opens up more than you want or need, remembering that WSL and VS Code will automatically forward ports to localhost when needed for development.

Hope this helps! It would be nice if WSL2 didn't change it's internal IP address every time it starts up so that this could be made even easier and more automated.

To conclude and sum up:

  • This blog post - the one you are reading now, has Windows only forwarding ports, and uses WSL2's Linux OpenSSH and authenticates against Linux. Windows is only involved peripherally. The WSL2 IP address changes on reboot and you'll need to maintain your portproxy rules and firewall rules with the script listened at the end of that post.
  • This other blog post - over here - uses Windows' OpenSSH and authenticates with Windows and then runs WSL2. WSL2 starts up, uses bash, and Windows handles the TCP traffic.

Understand what you want and use the right one for you.

Other cool links:

Hope this helps! Also, please do subscribe to my YouTube channel!


Sponsor: Never miss a bug — send alerts to Slack or email, and find problems before your customers do, using Seq 2020.1.

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

How do I find which directory my .NET Core console application was started in or is running from?

July 28, '20 Comments [4] Posted in DotNetCore
Sponsored By

stressedI got a great question emailed to me today. And while I could find the answer and email them back, I also have a limited number of keystrokes. Plus, every question that moves knowledge forward is a gift, and I don't want to ignore a gift. So instead, I've email my new friend a link to this blog!

Here is their question:

The tl;dr question: how do I find which directory the app was started in?

I have a CLI app in .NET Core 3 that is supposed to sit in your apps folder you have in your path, do something when you run it, then exit.

Unfortunately, it needs a single line of configuration (an API key), which store in a text file. I want to keep the app portable (ie. avoid going into other directories), so I want to store the config file right next to the executable.

And since I want it to be small and easily distributed, I set up .NET to merge and prune the EXE on build. (I think I got the idea from your blog btw, thanks! :) It is a simple app that does a single task, so I figure it should be one EXE, not 50 megabytes in 80 files.

And there the problem lies: If the config file is right next to the exe, I need to know where the exe is located. BUT, it seems that when I have the entire app built into a single EXE like this, .NET actually extracts the embedded DLL to some temporary location in my filesystem, then runs it from there. Every method for finding the startup assembly's location I have found, either by googling or exploring with reflection while it runs, only gives me the location in the temp directory, not the one where the app was actually launched from. The app then attempts to load the config file from this temp directory, which obviously fails.

Let's break this problem down:

  • .NET 3.1 LTS (long term support) has a cool feature where you can ship a single EXE with no dependencies. You ship "myapp.exe" and it just works. One file, no install.
    • When you run the EXE in .NET 3.1, the system "unzips" the app and its dependencies into a temp folder.
  • If you have a config file like myapp.exe.config, you'd like the user to keep that file NEXT TO THE EXE. That way you have two files next to each other and it's simple.
    • But how do you find this config file if you got started from a random temp folder?

Here's how things work in .NET Core 3.1:

using System;
using System.Diagnostics;
using System.IO;

namespace testdir
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"Launched from {Environment.CurrentDirectory}");
Console.WriteLine($"Physical location {AppDomain.CurrentDomain.BaseDirectory}");
Console.WriteLine($"AppContext.BaseDir {AppContext.BaseDirectory}");
Console.WriteLine($"Runtime Call {Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)}");
}
}
}

And here's the output of this app when started from elsewhere. Look carefully at the paths:

~\Desktop> .\testdir\bin\Debug\netcoreapp3.1\win-x64\publish\testdir.exe
Launched from C:\Users\scott\Desktop
Physical location C:\Users\scott\AppData\Local\Temp\.net\testdir\30gxvy1b.yq3\
AppContext.BaseDir C:\Users\scott\AppData\Local\Temp\.net\testdir\30gxvy1b.yq3\
Runtime Call C:\Users\scott\Desktop\testdir\bin\Debug\netcoreapp3.1\win-x64\publish

You'll note that when on .NET 3.1 if you want to get your "original birth location" you have to do a little runtime dance. Starting with your current process, then digging into the MainModules's filename, then getting that file's Directory. You'll want to catch that at startup as it's not a super cheap call you want to make all the time.

How does it work in .NET Core 5 (> preview 7)? Well, because the assemblies are embedded and loaded from memory in 5, so like any other in-memory assembly, they don't have a location. Any use of Assembly.Location is going to be suspect.

NOTE: There is some work happening on an analyzer that would flag weird usage when you're using Single File publish, so you won't have to remember any of this. Additionally, if you are on .NET 5 and you want to have the .NET 3.1 temp file behavior, you can use a compatibility property called IncludeAllContentInSingleFile.

Here's the same app, running in .NET 5 as a single EXE and unfolding directly into memory (no temp files):

Launched from C:\Users\scott\Desktop
Physical location C:\Users\scott\Desktop\testdir\bin\Debug\net5.0\win-x64\publish\
AppContext.BaseDir C:\Users\scott\Desktop\testdir\bin\Debug\net5.0\win-x64\publish\
Runtime Call C:\Users\scott\Desktop\testdir\bin\Debug\net5.0\win-x64\publish

You'll note here that you get the behavior you expect with each call.

Here's the answer then:

    • You should use AppContext.BaseDirectory on .NET 5 to get the truth
    • You can use the runtime calls (and cache them) with MainModule (the last line in the example) for .NET 3.1.

Hope this helps!


Sponsor: Never miss a bug — send alerts to Slack or email, and find problems before your customers do, using Seq 2020.1.

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Official Support for Remote Debugging a .NET Core Linux app in WSL2 from Visual Studio on Windows

July 23, '20 Comments [4] Posted in DotNetCore | Linux | VS2019
Sponsored By

I've blogged before about Developing on Docker with the new and improved Visual Studio Container Tools (and WSL2) and also Remote Debugging a .NET Core Linux app in WSL2 from Visual Studio on Windows.

It's the second one that I'm talking about today. You can now run .NET Core console and web apps in WSL2 and debug them directly from Visual Studio 2019!

What do you need?

Here's the experience in Visual Studio 2019 when the extension is installed. It "just works" and it makes it super easy to switch between running on Windows (under IIS or the Kestrel web server or under Kestrel under your default Linux distribution.

WSL 2 in the Visual Studio Debugging Menu

Check this out, you can see that .NET Core, from the Linux/WSL 2 perspective, is loaded out of /usr/share/dotnet/shared but my source remains on my /mnt/d drive (my Windows D:) and debugging Just Works.

image

You'll also notice that we are running on https://localhost:5001 and that localhost and ports from the Windows point of view maps to localhost and points (via a local tunnel that's transparent) to WSL 2.

How does the SSL cert work if WSL 2's Linux Kestrel web server is serving it?

You can see that there's a symbolic link between my WSL ~/.aspnet folder and my local profile in Windows so that this app shares SSL certs and that the same cert is served with Kestrel on Windows and Kestrel on Linux.

scott@IRONHEART:~$ cd .aspnet
scott@IRONHEART:~/.aspnet$ ls
DataProtection-Keys https
scott@IRONHEART:~/.aspnet$ cd https/
scott@IRONHEART:~/.aspnet/https$ ls
hanselminutes.core.pfx
scott@IRONHEART:~/.aspnet/https$ ls -alogF
total 12
drwxr-xr-x 2 4096 Jun 23 17:02 ./
drwxr-xr-x 4 4096 Jun 23 17:02 ../
lrwxrwxrwx 1 71 Jun 23 17:02 hanselminutes.core.pfx
->
/mnt/c/Users/scott/AppData/Roaming/ASP.NET/Https/hanselminutes.core.pfx*
scott@IRONHEART:~/.aspnet/https$

I broke that line up with the symbolic link -> along 3 lines so it wouldn't wrap on this blog.

Now you can run and debug .NET Core apps on Windows and Linux using both VS Code and Visual Studio 2019! I'm using Visual Studio 2019's free Community Edition and it works great. This helps me save money as I've moved my Podcast site to Linux in Azure and it makes my local development better match my cloud reality. Give it a try!


Sponsor: Centralize and search structured application logs to confidently diagnose problems - even faster and easier with Seq 2020.1!

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

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