Wordle cheat script

An article on The Register linked to a GitHub shell script version of Wordle, and what caught my eye was that apparently a Linux installation contains a dictionary of English words in the file /usr/share/dict/words.

If you are stuck in your daily Wordle, you can use this file to figure out solutions:

CommandPurpose
grep -E '^([a-zA-Z]){5}$' /usr/share/dict/wordscollect all 5-letter words
tr '[a-z]' '[A-Z]'convert words to upper case
grep 'RU...'filter words for matching (green) letters
grep '[E]'filter words for letters in the wrong spot (yellow)
grep -v '[ASD]'exclude known wrong letters (dark grey)

Combine the commands (the last 3 are optional) with the respective letters filled in, separated by the pipe “|”:

$ grep -E '^([a-zA-Z]){5}$' /usr/share/dict/words | tr '[a-z]' '[A-Z]' | grep 'RU.E.' | grep -v '[TASDLMN]'
RUPEE

Angular Google Maps Demo

The Angular Components documentation on its Google Maps component does not contain a working demo. Probably that’s because it would need to incorporate a YOUR_API_KEY value…

So I took the sample code from their README.md and README.md files and stitched together a working (uhm api key) sample on StackBlitz.

I noticed that while my code works find on my local machine, the StackBlitz version will raise an error in the console

Error in src/app/google-maps-demo/google-maps-demo.component.ts (14:11)
Cannot find namespace ‘google’.

This error is caused by the fact that the namespace google.maps is only created if the Google Maps API is loaded successfully.

Which brings me to error handling:

Essentially there are 3 cases that need to be dealt with:

  • Success
  • Invalid API key
  • Invalid URL for the Google Maps API call

In case of an invalid API key, the <google-map> component raises the authFailure event

In case of an invalid URL, there is no script to initialize the google namespace, and you can check whether the objects window["google"] and window["google"]["maps"] exist.

The code is also available as a GitHub repository.

ng update will update you automatically

During my Angular Update Odyssey, I found that the Angular Update Guide frequently states

ng update will do this automatically for you.
ng update should take care of this automatically.
ng update will migrate you automatically.

and I wondered when ng update would actually perform all those magic tasks, because I did not notice them.

Then I had the relevation, that ng update only performs the update tasks, if the package update was successful.

If the package update fails due to package dependency conflicts, then no update magic. Bad luck. You need to clean-up by yourself.

Analyzing the update log I keep (essentially a copy-and-paste from the npx update console output), this is what happens:

> npx @angular/cli@10 update @angular/core@10 @angular/cli@10

The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 54 dependencies.

Fetching dependency metadata from registry...
    Updating package.json with dependency @angular-devkit/build-angular @ "0.1002.4" (was "0.901.15")...
    Updating package.json with dependency @angular/cli @ "10.2.4" (was "9.1.15")...
...

  UPDATE package.json (2249 bytes)

npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: my.web.app@1.0.0
npm ERR! Found: @angular-devkit/build-angular@0.901.15
npm ERR! node_modules/@angular-devkit/build-angular
npm ERR!   dev @angular-devkit/build-angular@"^0.1002.4" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev @angular-devkit/build-angular@"^0.1002.4" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: @angular/compiler-cli@10.2.5
npm ERR! node_modules/@angular/compiler-cli
npm ERR!   peer @angular/compiler-cli@"^10.0.0" from @angular-devkit/build-angular@0.1002.4
npm ERR!   node_modules/@angular-devkit/build-angular
npm ERR!     dev @angular-devkit/build-angular@"^0.1002.4" from the root project

My interpretation of the log entries is that

  • ng update fetches the dependencies of the new packages
  • ng update writes package.json with new version numbers
  • npm fails to install because of dependency conflicts
  • ng update gives up, because the new packages are not there

If you’re lucky, the node_modules directory has been deleted, too.

So, for future updates, I will consider the following update strategy:

  • run npx update
  • if the update fails as above, revert the changes in package.json
    – apparently there’s a reason npx update warns

Repository is not clean. Please commit or stash any changes before updating.

  • run npx update --force
  • commit changes
  • fix broken dependencies

mat- is not a known element

Updating an ancient Angular application to a more current version, I came across various warnings and error relating to the Angular Material framework.

Hidden behind the inconspicuous comment

Instead of importing from @angular/material, you should import deeply from the specific component. E.g. @angular/material/button

https://update.angular.io/?v=8.0-9.0

is the task of adding all kinds of import declarations to the modules containing components with Material elements or attributes.

In case of missing elements, the browser console will display a warning

‘mat-xxx’ is not a known element:
1. If ‘mat-xxx’ is an Angular component, then verify that it is part of this module.
2. If ‘mat-xxx’ is a Web Component then add ‘CUSTOM_ELEMENTS_SCHEMA to the ‘@NgModule.schems’ of this component to suppress this message.

In case of missing attributes, the browser console will display a warning

Can’t bind to ‘mat-xxx’ since it isn’t a known property of ‘<element>’

  • First, an import declaration in the module’s .ts file:
    import { MatXxxxModule } from '@angular/material/xxxx';
  • Second, adding the MatXxxxModule in the imports array of modules in the @NgModule declaration
Console Error MessageImport ModuleModule Location
mat-autocomplete is not a known elementMatAutocompleteModuleautocomplete
[matBadge]MatBadgeModulebadge
[mat-button]MatButtonModulebutton
mat-chip-list is not a known elementMatChipsModulechips
mat-dialog is not a known elementMatDialogModuledialog
mat-divider is not a known elementMatDividerModuledivider
mat-form-field is not a known elementMatFormFieldModuleform-field
mat-icon is not a known elementMatIconModuleicon
mat-list is not a known elementMatListModulelist
mat-menu is not a known elementMatMenuModulemenu
mat-paginator is not a known elementMatPaginatorModulepaginator
mat-progress-bar is not a known elementMatProgressBarModuleprogress-bar
mat-select is not a known elementMatSelectModuleselect
[mat-sort-header]MatSortModulesort
mat-spinner is not a known elementMatProgressSpinnerModuleprogress-spinner
mat-tab is not a known elementMatTabsModuletabs
mat-table is not a known elementMatTableModuletable
mat-toolbar is not a known elementMatToolbarModuletoolbar
[matToolTip]MatTooltipModuletooltip

Switching Sound Output between Headset and Speakers

How do you change the sound device a particular application is using for its audio output? I never bothered to think about this question, until the times of the shared home office.

True, in Windows you can change the default sound device, and an application that is started afterwards will use that device. But changing the sound device for a running application? It seems there is no built-in way to do that.

For Windows 7 and higher, I found the SoundSwitch applet (GitHub), which does just that. Located in the notification area, it lets you select the sound device the current application outputs its audio to. Simply click on its icon and select the device, or press a customizable hotkey.

For Ubuntu, I found Sound Switcher Indicator (GitHub, Blog). Upon installation, it can be accessed from the indicator area, and allows the selection of audio input and output devices.

Problems solved 😉

Epilogue

During preparation of this post, I tried to figure out how SoundSwitch actually switches the audio device.

It turns out that it uses the function call SetPersistedDefaultAudioEndpoint() which is also used by an application called EarTrumpet (GitHub) that tags itself as “Volume control for Windows”, but also seems to allow switching audio devices.

A review of this application by Scott Hanselman indicates that the method and its interface are not officially documented:

Internal Audio Interface: IAudioPolicyConfigFactory

Gets them access to new APIs (GetPersistedDefaultAudioEndpoint / SetPersistedDefaultAudioEndpoint) in RS4 that let’s them ‘redirect’ apps to different playback devices. Same API used in modern sound settings.

Code here with no public API yet?

Unsupported .Net SDK version error in Visual Studio Code extension

During the last couple of days, my VSCode installation greeted me with a strange error message on startup:

Installed .NET SDK version 6.0.100-preview.7.21379.14 is newer than the currently supported versions. Project build will not work. Please install .NET Core SDK version 3.1 and include a global.json in the project folder specifying the SDK version to use. More Information

Recently installed .Net SDK 6

VSCode is currently version 1.62.2 (it auto-updated today), and the extension version data is:
– Released on: 28.10.2021, 00:30:16
– Last updated: 28.10.2021, 00:32:34
– Identifier: ms-mssql.sql-database-projects-vscode

The More Information link points to the page Select the .NET version to use and does not seem to apply to installed VSCode extensions.

After a bit of digging, I found a couple of GitHub issues in the azuredatastudio project, which the SQL Database Projects extension is part of.

Issue 16766 deals with the behavior I noticed: SQL projects don’t build when active dotnet version is 6.0 preview

and confirmed by one comment:

Unfortunately, this affects Visual Studio Code as well. Annoyingly, the warning pops up even if no database project is loaded.

I tried changing the extension settings “Sql Database Projects: Net Core SDKLocation” (Full path to .NET Core SDK on the machine) but this did not get rid of the error message.

So I navigated to the install location of the VSCode extension, which can be found under
%userprofile%\.vscode\extensions\ms-mssql.sql-database-projects-vscode-0.13.0
(adjust version number) and tried to figure out how the error message is raised.

It turns out that the extension does not specifically query for the required dotnet version, but rather issues a “dotnet –version”, which returns the highest installed version number:

> dotnet --version
6.0.100-preview.7.21379.14

This version number is checked against the hard-coded upper limit of

t.maxSupportedNetCoreVersionCutoff = "6.0.0";

So I opened the file extension.js and tried to change this value to a SemVer higher than “6.0.100”, such as “7.0.0”, and restarted VSCode. And … the error message was gone!

Ok, so the extension was enabled, and VSCode does not throw an error when it did before, but would the extension still actually work?

So I created a new SQL Database project by Ctrl+Shift+P and selecting “Database Projects: Create Project From Database”, subsequently entering all the connection string data to connect to a database, which resulted in a .sqlproj file and generated CREATE TABLE statements in one .sql file per table.

Sending Email Notifications for Windows Updates

I have this Windows server installed which hosts a couple of websites, and is really not doing much.

Every now and then I need to log in for some server operation, only to find the typical Windows Updates Pending notification. Every time this happens I think to myself, hey, I’d like to get some notification that there are updates available, without having to log in.

So I finally dug around the internets – well, as it turned out, the info was all on StackOverflow:

The result is a tiny PowerShell script called update-mailer.ps1, which queries the Windows Update Service and sends an email accordingly, and can be found on my GitHub PowerShell repository.

To run this script as a Scheduled Task, create a .cmd batch file containing the command

powershell.exe -ExecutionPolicy Bypass -File path\to\update-mailer.ps1

to bypass PowerShell’s restricted execution policy, and call the script from the task.

Concatenating a list of strings in T-SQL

Remember how clumsy it was to concatenate string identifiers of child records within a sub-SELECT and adding this artificial FOR XML PATH('')? (if you don’t remember)

Writing plain SQL again after a long time, I found the “new” function STRING_AGG (introduced in SQL Server 2017) to be a great simplification. I guess mainly because the sub-select can be inlined and the whole SELECT can be GROUP BY’d.

Case in point, I needed to find out which database tables have unique indexes defined, and which columns they indexed.

Here’s the magic:

select o.name, i.name,
    STRING_AGG(c.name, ', ') WITHIN GROUP (ORDER BY ic.index_column_id)
from sys.index_columns ic
inner join sys.indexes i 
    on ic.object_id = i.object_id and ic.index_id = i.index_id
inner join sys.objects o on i.object_id = o.object_id
inner join sys.columns c 
    on ic.object_id = c.object_id and ic.column_id = c.column_id
where o.is_ms_shipped = 0 
and o.name not like '%_history'
and i.is_primary_key = 0
and i.is_unique = 1
group by o.name, i.name
order by 1, 2

Constructing Type-Safe SQL Statements from ORM Classes

Suppose you have a database application, and the database tables are mapped onto C# classes as used by an ORM such as Entity Framework or NHibernate.

Suppose you need to construct an SQL statement manually, because your ORM does not support or implement (or interface to) a given SQL feature.

Of course, you can always write the SQL statement manually, and query data using EF’s Database.SqlQuery() or NHibernate’s CreateSQLQuery().

The problem I found is that as soon as the data model changes, these manually crafted SQL statements are bound to fail.

Let’s have a look at a simple SELECT statement involving a JOIN of two tables (of course ORMs manage such a query, this is just an illustration):

SELECT s.Name AS SupplierName, a.ZipCode AS AddressZipCode, 
       a.City AS AddressCity, a.Street AS AddressStreet
FROM  Supplier s
INNER JOIN Address a ON s.AddressId = a.Id

The statement includes table names, table aliases, table column names, and column aliases, and I want to construct the column names for the SQL statement from the ORM’s mapped classes.

Gladly I already have the GetPropertyName() function to retrieve as class’s property names, so we can focus on enumerating them:

public static string EnumerateColumns<T>(
    string tablePrefix, 
    string columnPrefix, 
    params Expression<Func<T, object>>[] columns)
{
    return string.Join(", ", 
        columns.Select(c =>
            (tablePrefix != null ? (tablePrefix + ".") : "") +
            GetPropertyName(c) +
            (columnPrefix != null 
                ? (" AS " + columnPrefix + GetPropertyName(c)) 
                : "")));
}

So we have a function handling optional table aliases and optional column name prefixes, which we can invoke for every joined table of our statement:

var sql = "SELECT "
    + EnumerateColumns<Supplier>("s", "Supplier", s => s.Id, s => s.Name)
    + ", "
    + EnumerateColumns<Address>("a", "Address", 
        a => a.ZipCode, a => a.City, a => a.Street)
+ @"
FROM " + nameof(Supplier) + @" s
INNER JOIN " + nameof(Address) + " a ON s." 
    + nameof(Supplier.AddressId) + " = a." + nameof(Address.Id);

Console.WriteLine(sql);

There is a little bit of cheating hidden in this code, assuming that table names match their class names, and column names match their property names. If they names differ, you can mark up the class declaration with some attribute and query it using GetCustomAttributes(), or EF’s pluralization service (if it is used).

The full code for this article available on my GitHub.

Updating TortoiseGit to use github’s Personal Access Token

I recently got github’s email on their changes to authentication tokens, but of course ignored as long as I could.

We recently updated the format of our API authentication tokens, providing additional security benefits to all our customers.

So today was the day to update my local authentication token in TortoiseGit.

I headed over to github’s Personal Access Token page to generate a new token.

But it was not really clear how to add it as authentication for repositories existing on my local PC.

After some google-fu, I opened the TortoiseGit Settings dialog in the root directory of one of my repositories,

TortoiseGit credentials (right-click on repository directory)

changed the Credential helper to Advanced, and entered my github username.

The next TortoiseGit/Push… command open an authentication dialog where I copied the github token in the password field.

After the push was completed, I could verify that the new token was added in Windows under Control Panel / Accounts / Credential Manager / Windows Credentials

Updated Windows credentials